基于Netty框架手写一个Tomcat容器

Netty作为底层通信框架,用来实现Web容器自然也不难,我们先介绍一下整体实现思路。我们知道,Tomcat是基于J2EE规范的Web容器,主要入口是web.xml文件。web.xml文件中主要配置Servlet、Filter、Listener等,而Servlet、Filter、Listener在J2EE中只是抽象的实现,具体业务逻辑由开发者来实现。本章内容,就以最常用的Servlet为例来详细展开。

1 环境准备

1.1 定义GPServlet抽象类

首先,我们创建GPServlet类。我们都知道GPServlet生命周期中最常用的方法是doGet()方法和doPost()方法,而doGet()方法和doPost()方法是service()方法的分支实现,看下面的简易版Servlet源码实现。

从上面的代码中,我们看到,doGet()方法和doPost()方法中有两个参数GPRequest和GPResponse对象,这两个对象是由Web容器创建的,主要是对底层Socket的输入输出的封装。其中GPRequest是对Input的封装,GPResponse是对Output的封装。

1.2 创建用户业务代码

下面基于GPServlet来实现两个业务逻辑FirstServlet和SecondServlet。FirstServlet类的实现代码如下。

SecondServlet类的实现代码如下。

1.3 完成web.properties配置

为了简化操作,我们用web.properties文件代替web.xml文件,具体内容如下。

上述代码分别给两个Servlet配置了/firstServlet.do和/secondServlet.do的URL映射。

4.2 基于传统I/O手写Tomcat

下面我们来看GPRequest和GPResponse的基本实现。

4.2.1 创建GPRequest对象

GPRequest主要就是对HTTP的请求头信息进行解析。我们从浏览器发送一个HTTP请求,如在浏览器地址栏中输入http://localhost:8080,后台服务器获取的请求其实就是一串字符串,具体格式如下。

在GPRequest获得输入内容之后,对这一串满足HTTP的字符信息进行解析。我们来看GPRequest简单直接的代码实现。

在上面的代码中,GPRequest主要提供了getUrl()方法和getMethod()方法。输入流InputStream作为GPRequest的构造参数传入,在构造函数中,用字符串切割的方法提取请求方式和URL。

4.2.2 创建GPResponse对象

接下来看GPResponse的实现,与GPRequest的实现思路类似,就是按照HTTP规范从Output输出格式化的字符串,来看代码。

上面的代码中,输出流OutputStream作为GPResponse的构造参数传入,主要提供了一个write()方法。通过write()方法按照HTTP规范输出字符串。

4.2.3 创建GPTomcat启动类

前面4.2.1和4.2.2两节只是对J2EE规范的再现,接下来就是真正Web容器的实现逻辑,分为三个阶段:初始化阶段、服务就绪阶段、接受请求阶段。

第一阶段:初始化阶段,主要是完成对web.xml文件的解析。

上面代码中,首先从WEB-INF读取web.properties文件并对其进行解析,然后将URL规则和GPServlet的对应关系保存到servletMapping中。

第二阶段:服务就绪阶段,完成ServerSocket的准备工作。在GPTomcat类中增加start()方法。

第三阶段:接受请求阶段,完成每一次请求的处理。在GPTomcat中增加process()方法的实现。

每次客户端请求过来以后,从servletMapping中获取其对应的Servlet对象,同时实例化GPRequest和GPResponse对象,将GPRequest和GPResponse对象作为参数传入service()方法,最终执行业务逻辑。最后,增加main()方法。

服务启动后,运行效果如下图所示。

4.3 基于Netty重构Tomcat实现

了解了传统的I/O实现方式之后,我们发现Netty版本的实现就比较简单了,来看具体的代码实现。

4.3.1 重构GPTomcat逻辑

话不多说,直接看代码。

代码的基本思路和基于传统I/O手写的版本一致,不再赘述。

4.3.2 重构GPRequest逻辑

我们先来看代码。

和基于传统的I/O手写的版本一样,提供getUrl()方法和getMethod()方法。在Netty的版本中,我们增加了getParameter()的实现,供大家参考。

4.3.3 重构GPResponse逻辑

还是继续看代码。

相对于基于传统的I/O手写的版本而言,主要变化就是利用Netty对HTTP的默认支持,可以使用现成的API。

4.3.4 运行效果演示

启动容器,我们在浏览器地址栏中输入http://localhost:8080/firstServlet.do,可以得到如下图所示的结果。

在浏览器地址栏中输入http://localhost:8080/secondServlet.do,可以得到如下图所示的结果。

展开阅读全文

页面更新:2024-04-12

标签:容器   字符串   框架   逻辑   对象   阶段   传统   版本   代码   文件   方法

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top