miniTomcat运行机制
处理请求的request
import java.io.IOException;
import java.io.InputStream;
public class MyRequest {
private String url;
private String method;
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);
}
// 请求头的内容
// HTTP请求协议
// GET /favicon.icoHTTP/1.1
// Accept: */*
// Accept-Encoding :gzip,deflate
// User-Agent:Mozilla/5.0 (Windows NT 6.1;WOW64;Trident/7.0;rv:11.0) like Ge
// Host: localhost:8080
// Connection: Keep-Alive
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;
}
}
url :除上下文外的mapping(例如:http://localhost:8080/girl)中的‘/girl’
method:请求服务器的方法,常用的为:GET,POST,DELTE等
通过url的值就和web.xml中的中的值等效
服务器响应response
import java.io.IOException;
import java.io.OutputStream;
public class MyResponse {
private OutputStream outputStream;
public MyResponse(OutputStream outputStream) throws IOException{
this.outputStream=outputStream;
}
public void write(String content) throws IOException{
/* HTTP 响应协议
HTTP/1.1 200 OK
Content -Type: text/html
<html><body></body></html>
*/
StringBuffer httpResponse=new StringBuffer();
httpResponse.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(httpResponse.toString().getBytes());
outputStream.close();
}
}
处理请求的servlet
import javax.xml.ws.Response;
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 (myRequest.getMethod().equalsIgnoreCase("POST")){
doPost(myRequest,myResponse);
}else if (myRequest.getMethod().equalsIgnoreCase("GET")){
doGet(myRequest,myResponse);
}
}
}
根据请求的方式,判断调用的方法
mapping文件
public class ServletMapping {
private String servletName;
private String url;
private String clazz;
public ServletMapping(String servletName,String url,String clazz){
this.servletName=servletName;
this.url=url;
this.clazz=clazz;
}
public ServletMapping(){
}
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;
}
}
用来存放类的名称与类的全路径,映射的关系
存放所有类与映射的关系
import java.util.ArrayList;
import java.util.List;
public class ServletMappingConfig {
public static List<ServletMapping> servletMappingList=new ArrayList<ServletMapping>();
static {
servletMappingList.add(new ServletMapping("findGirl","/girl","mytomcat.FindGirlServlet"));
servletMappingList.add(new ServletMapping("helloWorld","/world","mytomcat.HelloWorldServlet"));
}
}
这个相当于一个容器,存放所有的映射关系
测试类
import java.io.IOException;
public class HelloWorldServlet extends MyServlet {
public void doGet(MyRequest myRequest,MyResponse myResponse){
try{
myResponse.write("get world...");
}catch (IOException e){
e.printStackTrace();
}
}
public void doPost(MyRequest myRequest,MyResponse myResponse){
try{
myResponse.write("post world...");
}catch (IOException e){
e.printStackTrace();
}
}
}
import java.io.IOException;
public class FindGirlServlet extends MyServlet {
public void doGet(MyRequest myRequest,MyResponse myResponse){
try{
myResponse.write("get girl...");
}catch (IOException e){
e.printStackTrace();
}
}
public void doPost(MyRequest myRequest,MyResponse myResponse){
try{
myResponse.write("post girl");
}catch (IOException e){
e.printStackTrace();
}
}
}
tomcat容器
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 int port = 8080;
private Map<String,String> urlServletMap = new HashMap<String, String>();
public MyTomcat(int port){
this.port = port;
}
public void start(){
//初始化 url 与对应处理的servlet的关系
initServletMapping();
ServerSocket serverSocket=null;
try{
serverSocket=new ServerSocket(port);
System.out.println("MyTomcat is start");
while (true){
Socket socket=serverSocket.accept();//tomcat运行后
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) {
e.printStackTrace();
}finally {
if(serverSocket!=null){
try{
serverSocket.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
private void initServletMapping(){
for (ServletMapping servletMapping:ServletMappingConfig.servletMappingList){
urlServletMap.put(servletMapping.getUrl(),servletMapping.getClazz());
}
}
private void dispatch(MyRequest myRequest,MyResponse myResponse){
String clazz=urlServletMap.get(myRequest.getUrl());
//反射
try{
Class<MyServlet> myServletClass=(Class<MyServlet>)Class.forName(clazz);
MyServlet myServlet=myServletClass.newInstance();
myServlet.service(myRequest,myResponse);
}catch (ClassNotFoundException e){
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
new MyTomcat(8080).start();
}
}
根据手写tomcat分析tomcat运行的全过程
tomcat启动操作
1.指定端口后,执行start()方法
1.1 将类与映射的关系放入容器,相当于web项目中,加载web.xml文件
1.2 启动对端口的监听程序
2.客户端请求的处理
2.1 生成request和response
2.2使用request,response进行请求的分发
2.3通过请求的url得到要执行的类的路径
2.4利用反射创建servlet,执行service方法