Servlet是什么
Servlet本质就是一个接口,在servlet-api.jar
这个jar包中就定义了Servlet
接口。我们知道接口的作用其实就是定义一种规范,Servlet
接口定义的则是关于Servlet生命周期以及处理http请求的一种规范。Servlet中定义了5个方法,Servlet容器会通过调用这几个方法与具体的Servlet来交互,包括管理创建、销毁Servlet实例,处理Http请求等。
Servlet
接口中的方法:
1 | public interface Servlet { |
Servlet容器
首先,我们从服务端编程说起,如下是使用Socket编写服务端的一个示例:
1 | public class ServerSocketHandler implements Runnable { |
从这个简单的示例可以看出,服务端在处理客户端的网络请求时,主要做了3件事情:
- 接收请求
- 处理请求
- 响应请求
Servlet一整套体系(即Java Servlet API)的引入,就是为了简化这个服务端编程的过程。Servlet容器,顾名思义里面存放着Servlet对象,当客户端发送Http请求时容器会将接收到的请求封装为ServletRequest,并且将响应封装为ServletResponse,然后找到对应的Servlet实例,调用Servlet的service方法处理请求。如下图:
上图中的Tomcat就是最常用的Servlet容器。
web.xml
为了理解地更深入一点,我们需要了解一下web.xml文件。
web.xml文件是Tomcat中Web项目中的一个配置文件,主要用于配置Filter、Listener、Servlet等,但并不是必须的,一个Java Web项目没有web.xml文件也是照样能跑起来的。Tomcat启动的时候,会根据web.xml文件中配置的Servlet、Filter等创建对应的实例,当客户端发送一个请求过来,再根据配置的请求路径找到对应的Servlet实例,将请求交给它去处理。
如下就是一个名为HelloServlet
的 Servlet 在web.xml文件中的配置示例:
1 | <servlet> |
@WebServlet注解
在 Servlet3.0 以后,我们也可以不用再web.xml里面配置Servlet,只需要在Servlet类上加上@WebServlet
注解就可以配置该Servlet的属性了。
1 | "annoationServlet", urlPatterns = "/test/testAnnotationServlet") (name = |
比如基于SpringBoot的项目就没有web.xml文件,想要配置Servlet的话就可以通过注解的方式配置。
Servlet相关的接口和类
前面说到Servlet是接口,具体的实现类就可以处理网络请求,我们编写Servlet时一般不会直接去实现Servlet,而是去继承HttpServlet
。HttpServlet
则继承自GenericServlet
这个抽象类。下面分析一下这三者。
Servlet接口的方法
方法声明 | 功能描述 |
---|---|
void init(ServletConfig config) | 容器在创建好 Servlet 对象后,就会调用此方法。该方法接收一个 ServletConfig 类型的参数,Servlet 容器通过该参数向 Servlet 传递初始化配置信息 |
ServletConfig getServletConfig() | 用于获取 Servlet 对象的配置信息,返回 Servlet 的 ServletConfig 对象 |
String getServletInfo() | 返回一个字符串,其中包含关于 Servlet 的信息,如作者、版本和版权等信息 |
void service (ServletRequest request,ServletResponse response) | 负责响应用户的请求,当容器接收到客户端访问 Servlet 对象的请求时,就会调用此方法。 容器会构造一个表示客户端请求信息的 ServletRequest 对象和一个用于响应客户端的 ServletResponse 对象作为参数传递给 service() 方法。 在 service() 方法中,可以通过 ServletRequest 对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用 ServletResponse 对象的方法设置响应信息 |
void destroy() | 负责释放 Servlet 对象占用的资源。当服务器关闭或者 Servlet 对象被移除时,Servlet 对象会被销毁,容器会调用此方法 |
GenericServlet
在GenericServlet
一个重要点是增加了一个成员变量ServletConfig,并且在init(ServletConfig config)
方法中对它赋值,再重新定义了一个抽象的init()
方法。
1 |
|
但GenericServlet
并没有实现service (ServletRequest request,ServletResponse response)
方法,需要子类去实现。
HttpServlet
HttpServlet
继承了GenericServlet
,本身也是个抽象类,不能直接进行实例化。这个类包含了对http协议请求的通用处理,HttpServlet
主要有两大功能,具体如下。
- 根据用户请求方式的不同,定义相应的
doXxx()
方法处理用户请求。例如,与 GET 请求方式对应的doGet()
方法,与 POST 方式对应的doPost()
方法。当定义的类继承 HttpServlet 后,只需要根据请求方式重写对应的 doXxx() 方法即可,而不需要重写 service() 方法。 - 通过
service()
方法将 HTTP 请求和响应分别强转为HttpServletRequest
和HttpServletResponse
类型的对象。
BaseHttpServlet
如果在项目中使用要写Servlet,通常会写一个抽象类继承自HttpServlet
,比如类名为BaseHttpServlet
,并且把get、post等方法都统一用一个方法去处理。例如:
1 |
|
v1.5.2