1. 原理简介
在提 Servlet 原理之前,有几个盲点是需要留意的:
- 常见的 Web 服务器,如 Tomcat ,是包含了 Servlet 容器的,Servlet 容器只是 Web 服务器的一部分
- Servlet 容器,是管理 Servlet 的,一个 Servlet 容器中,可能有很多个 Servlet
- 在 Java 中,一个 Servlet 可以理解为就是我们写的一个 Java 实现类
- 浏览器向 Web 服务器发起 Http 请求。Web 服务器接收请求后,转给 Servlet 容器处理请求。如果是首次访问,没有请求需要的 Servlet ,则对应地,新建一个 Servlet,如果有,则直接使用。
- Servlet 容器创建一个 HttpRequest 对象,同时也创建一个HttpResponse 对象,并将浏览器的请求信息封装到 HttpRequest 这个对象中。
- Servlet 容器调用 Servlet 的 service 方法,把 HttpRequest 对象与 HttpResponse 对象作为参数传给 Servlet。
- Servlet 从 HttpRequest 中获取请求信息,并进行逻辑处理。
- Servlet 生成响应数据,放到 HttpResponse 中,进行返回。
- Servlet 容器拿到 HttpResponse 的响应结果,返回给浏览器。
2. 生命周期
Servlet 的生命周期可以归纳为:Servlet 加载及实例化—>初始化—>服务—>销毁
- Servlet 加载及实例化:实例化以及加载servlet,new的过程
- 初始化:初始化init(ServletConfig)
- 服务:处理请求,调用 Servlet 的 service,doget,dopost 方法将 Request 和 Response ,作为参数传递
- 销毁:即退出服务,调用 destory 方法释放资源
(1)在正常情况下,Servlet只会初始化一次,而处理服务会调用多次,销毁也只会调用一次。但如果一个Servlet长时间不使用的话,也会被容器自动销毁,需要再次使用时会重新进行初始化操作,因此在特殊情况下初始化可能会进行多次,销毁也可能进行多次。
(2)在 Servlet 实例创建之后,在 Servlet 能为用户请求提供服务之前,容器会在 Servlet 实例上调用 init() 方法。如果有自己的初始化代码,就应该覆盖 Servlet 类的 init() 方法,否则会调用 GenericServlet 的 init() 方法。
3. Servlet的mapping映射
3.1 一对一映射
servlet-class和请求路径是一对一映射的情况
<!-- 注册servlet-->
<servlet>
<servlet-name>Get</servlet-name>
<servlet-class>com.yuhuofei.servlet.HelloServlet</servlet-class>
</servlet>
<!-- 配置servlet的请求路径-->
<servlet-mapping>
<servlet-name>Get</servlet-name>
<url-pattern>/doGet</url-pattern>
</servlet-mapping>
3.2 一对多映射
servlet-class和请求路径是一对多映射的情况
<!-- 注册servlet-->
<servlet>
<servlet-name>Get</servlet-name>
<servlet-class>com.yuhuofei.servlet.HelloServlet</servlet-class>
</servlet>
<!-- 配置servlet的请求路径-->
<servlet-mapping>
<servlet-name>Get</servlet-name>
<url-pattern>/doGet</url-pattern>
</servlet-mapping>
<!-- 配置servlet的请求路径-->
<servlet-mapping>
<servlet-name>Get</servlet-name>
<url-pattern>/doGet01</url-pattern>
</servlet-mapping>
<!-- 配置servlet的请求路径-->
<servlet-mapping>
<servlet-name>Get</servlet-name>
<url-pattern>/doGet02</url-pattern>
</servlet-mapping>
3.3 访问路径优先级问题
如果指定了特定的访问路径,会优先访问;如果没有指定,则访问缺省的或者是通配的。
如下所示,如果直接指定访问 localhost:8080/doGet 那么就会请求 com.yuhuofei.servlet.HelloServlet 中的内容;如果没有指定,即访问 localhost:8080/,这个时候会请求 com.yuhuofei.servlet.HelloServlet404 中的内容。
<!-- 注册servlet-->
<servlet>
<servlet-name>Get</servlet-name>
<servlet-class>com.yuhuofei.servlet.HelloServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>Get404</servlet-name>
<servlet-class>com.yuhuofei.servlet.HelloServlet404</servlet-class>
</servlet>
<!-- 配置servlet的请求路径-->
<servlet-mapping>
<servlet-name>Get</servlet-name>
<url-pattern>/doGet</url-pattern>
</servlet-mapping>
<!-- 配置servlet的请求路径-->
<servlet-mapping>
<servlet-name>Get404</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>