1. 理解模型
首先我们先了解一下tomcat的大致工作原理。tomcat的核心是servlet容器,我们称它为Catalina
Connector是用来“连接”容器里边的请求的。它的工作是为接收到每一个 HTTP 请求构造一个 request 和 response 对象。然后它把流程传递给容器。容器从连接器接收到 requset 和 response 对象之后调用 servlet 的 service 方法用于响应。
这是自己实现的时候的流程
2. 服务器搭建
我们先来熟悉一下整个流程
- 构建HttpServletRequestImpl对象
- 构建HttpServletResponseImpl对象
- 根据请求的对象找到Servlet对象
- 调用Servlet的service(req, resp)方法
- 调用resp.send(socket.getOutputStream())
- socket.close();
接下来定义我们自己的标准
这里呢需要大家对继承、多态有良好的理解
后面所写的Servlet都是继承HttpServlet如果没有重写doGet() 或者 doPost()方法,在访问的时候就会出现405,这是因为在HttpServlet这个抽象类实现的时候就写成了405,也就是Tomcat默认的样子。然后通过Service方法来判断是doGet还是doPost,这种方式也是模板方式。定义标准之后来具体实现
这些是需要实现的
需要构建HttpServletRequest和HttpServletResponse对象,这里使用到工厂模式,通过Server作为主入口,定义线程池来处理请求任务,通过ServletManager来管理Servlet的生命周期,初始化一次,提供服务多次,销毁一次,同时还有处理静态资源的Servlet和处理404的Servlet
这是所有实现的方法
同时还需要写一个类似webapp的目录来模拟,这里的web.xml,是通过两个Map来实现
//key: servlet-name
//value: servlet-class
public static Map<String, String> servlet = new HashMap<>();
//key: url-pattern
//value: servlet-name
public static Map<String, String> servletMapping = new HashMap<>();
static {
/*
<servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>com.jiangkunzhang.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
*/
servlet.put("Hello", "com.jiangkunzhang.HelloServlet");
servletMapping.put("/hello", "Hello");
}
这是整个流程图
3. 启动服务器
首先先来在浏览器输入http://127.0.0.1:8888/hello?target=jiangkunzhang
显示如下的页面 /hello是我们自己写的一个Servlet
接下来请求静态页面
在浏览器输入http://127.0.0.1:8888/jiangkunzhang/go.html
显示如下的页面
输入这个http://127.0.0.1:8888/world.html
请求不同位置的静态资源
再换一种类型来测试
http://127.0.0.1:8888/jiangkunzhang/apache.png
和我们的预期是一致的
4. 总结
tomcat的功能比我们的简易http服务器强大的多。但是通过这个最简单的http服务器,对我们学习网络部分的知识,理解Servlet相关的知识有很大的帮助,同时这个服务器还有不完善的地方,比如实现Cookie 和 Session,以及请求的转发相关的功能,后面进一步的完善。
项目完整代码:项目代码