MyTomcat(迷你版)
程序员文章站
2022-05-13 21:46:37
...
Tomcat对于请求实际上会进行下面的处理:
第一:提供Socket服务
Tomcat的启动,必然是Socket服务,只不过它支持HTTP协议而已!
第二:进行请求的分发
要知道一个Tomcat可以为多个Web应用提供服务,那么很显然,Tomcat可以把URL下发到不同的Web应用。
第三:需要把请求和响应封装成request/response
通过输入流,对HTTP协议进行解析,拿到了HTTP请求头的方法以及URL。
package com.mytomcat;
import java.io.IOException;
import java.io.InputStream;
public class MyRequest {
private String url;
private String method;
public MyRequest() {
// TODO Auto-generated constructor stub
}
// public MyRequest(String url, String method) {
// super();
// this.url = url;
// this.method = method;
// }
/**
* 通过输入流,对HTTP协议进行解析,拿到HTTP请求头的方法以及URL。
* @param inputStream
* @throws IOException
*/
public MyRequest(InputStream inputStream) throws IOException{
String httpRequest = "";
byte[] httpRequestBytes = new byte[1024];
int length = 0;
if((length = inputStream.read(httpRequestBytes)) > 0){
httpRequest = new String(httpRequestBytes, 0, length);
}
String httpHead = httpRequest.split("\n")[0];
url = httpHead.split("\\s")[1];
method = httpHead.split("\\s")[0];
System.out.println(this);
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
}
基于HTTP协议的格式进行输出写入。
package com.mytomcat;
import java.io.IOException;
import java.io.OutputStream;
public class MyResponse {
private OutputStream outputStream;
public MyResponse() {
// TODO Auto-generated constructor stub
}
public MyResponse(OutputStream outputStream){
this.outputStream = outputStream;
}
/**
* 基于HTTP协议的格式进行输出写入。
* @param content
* @throws IOException
*/
public void write(String content) throws IOException{
StringBuffer buffer = new StringBuffer();
buffer.append("HTTP/1.1 200 OK\n")
.append("Content-type: text/html\n")
.append("\r\n")
.append("<html><body>")
.append(content)
.append("</body></html>");
outputStream.write(buffer.toString().getBytes());
outputStream.close();
}
}
Servlet常见的doGet/doPost/service方法。
package com.mytomcat;
public abstract class MyServlet {
public abstract void doGet(MyRequest myRequest, MyResponse myResponse);
public abstract void doPost(MyRequest myRequest, MyResponse myResponse);
public void service(MyRequest myRequest, MyResponse myResponse){
if("POST".equalsIgnoreCase(myRequest.getMethod())){
doPost(myRequest, myResponse);
}else if("GET".equalsIgnoreCase(myRequest.getMethod())){
doGet(myRequest, myResponse);
}
}
}
以下两个java类做测试用:
package com.mytomcat;
import java.io.IOException;
public class FindGirlServlet extends MyServlet {
@Override
public void doGet(MyRequest myRequest, MyResponse myResponse) {
// TODO Auto-generated method stub
try {
myResponse.write("get--------FindGirlServlet");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void doPost(MyRequest myRequest, MyResponse myResponse) {
// TODO Auto-generated method stub
try {
myResponse.write("post-----------FindGirlServlet");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.mytomcat;
import java.io.IOException;
public class HelloWorldServlet extends MyServlet {
@Override
public void doGet(MyRequest myRequest, MyResponse myResponse) {
// TODO Auto-generated method stub
try {
myResponse.write("get--------HelloWorldServlet");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void doPost(MyRequest myRequest, MyResponse myResponse) {
// TODO Auto-generated method stub
try {
myResponse.write("post-----------HelloWorldServlet");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
web.xml中通过<servlet></servlet>和<servlet-mapping></servlet-mapping>来进行指定哪个URL交给哪个servlet进行处理。
package com.mytomcat;
public class ServletMapping {
private String servletName;
private String url;
private String clazz;
public ServletMapping() {
// TODO Auto-generated constructor stub
}
public ServletMapping(String servletName, String url, String clazz) {
super();
this.servletName = servletName;
this.url = url;
this.clazz = clazz;
}
public String getServletName() {
return servletName;
}
public void setServletName(String servletName) {
this.servletName = servletName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
}
package com.mytomcat;
import java.util.ArrayList;
import java.util.List;
/**
* web.xml中通过<servlet></servlet>和<servlet-mapping></servlet-mapping>
* 来进行指定哪个URL交给哪个servlet进行处理。
* @author kiss
*
*/
public class ServletMappingConfig {
public static List<ServletMapping> servletMappings = new ArrayList<ServletMapping>();
static{
servletMappings.add(new ServletMapping("findgirl", "/girl", "com.mytomcat.FindGirlServlet"));
servletMappings.add(new ServletMapping("helloworld", "/hellworld", "com.mytomcat.HelloWorldServlet"));
}
}
利用反射实例化具体的Servlet进行处理即可。
package com.mytomcat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class MyTomcat {
private Integer port = 8080;
private Map<String, String> urlServletMap = new HashMap<String, String>();
public MyTomcat() {
// TODO Auto-generated constructor stub
}
public MyTomcat(Integer port) {
super();
this.port = port;
}
// public MyTomcat(Integer port, Map<String, String> map) {
// super();
// this.port = port;
// this.urlServletMap = map;
// }
/**
* 启动mytomcat
*/
public void start(){
initServletMapping();
ServerSocket serverSocket = null;
try {
//相当于服务器启动了,并且监听了port
serverSocket = new ServerSocket(port);
System.out.println("MyTomcat is start-------");
while(true){
//等待客户端 连接port端口
Socket socket = serverSocket.accept();
//获取连接的输入输出流
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
MyRequest myRequest = new MyRequest(inputStream);
MyResponse myResponse = new MyResponse(outputStream);
dispatch(myRequest, myResponse);
socket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(serverSocket != null){
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 初始化url与对应处理的servlet的关系
*/
private void initServletMapping(){
for (ServletMapping servletMapping : ServletMappingConfig.servletMappings) {
urlServletMap.put(servletMapping.getUrl(), servletMapping.getClazz());
}
}
/**
* 请求分发
* @param myRequest
* @param myResponse
*/
private void dispatch(MyRequest myRequest, MyResponse myResponse){
String clazz = urlServletMap.get(myRequest.getUrl());
try {
//反射
@SuppressWarnings("unchecked")
Class<MyServlet> myServletClass = (Class<MyServlet>) Class.forName(clazz);
MyServlet myServlet = myServletClass.newInstance();
myServlet.service(myRequest, myResponse);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
}
启动mytomcat
目前在浏览器上测试,会有两次连接,后一次连接丢失参数,导致会报空指针异常,还没找到原因。用postman测试工具测试一切正常。
上一篇: C# null,string.Empty,"",DBNull 的区别
下一篇: 线程安全使用(五)