# Servlet

# 认识 Servlet

Servlet 是运行在 Web 服务器端的 Java 应用程序段,可以生成动态的 Web 页面,属于客户端与服务器响应的中间层。实际上,JSP 在底层就是一个 Servlet。

Servlet 属于 JSP 底层,学习他有助于了解底层细节,Servlet 毕竟是一个 Java 类,适合纯编程。


让一个 Java 类继承 HttpServlet,并且重写 doGet () 方法,这样就属于一个 Servlet 类了


# 配置 Servlet 是

通过 web.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>WelcomServlet</servlet-name>
        <servlet-class>servlets.WelcomServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>WelcomServlet</servlet-name>
        <url-pattern>/servlets/WelcomServlet</url-pattern>
    </servlet-mapping>
</web-app>

以上配置表示给 servlets.WelcomServlet 取名为 WelcomServlet

在访问的时候:

http://localhost:8080 / 项目名 /servlets/WelcomServlet

注意:servlet-name 命名可以随意,但是两个 servlet-name 要一样


# Servlet 的运行机制

当浏览器发送给服务器一个 Servlet 的请求时,如果这个 Servlet 是第一次被调用,那么服务器将会自动创建一个 Servlet 实例,并运行它;而如果这个 Servlet 已经被实例化,那么服务器只是会新启动一个线程来运行它。所以,多个线程有可能会去访问共享的全局变量,因此,在使用这些全局变量时,一定要特别小心让这些线程不会访问到不同步的数据。除非是需要共享的信息。

# Servlet 的生命周期和常用方法

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

  • Servlet 初始化后调用 init () 方法。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 销毁前调用 destroy() 方法。
  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的

生命周期

# init () 方法

init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。

Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是也可以指定 Servlet 在服务器第一次启动时被加载。

当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init () 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。

# service () 方法

service () 方法是执行实际任务的主要方法 Servlet 容器(即 Web 服务器)调用 service () 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。

每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service () 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。

service () 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以不用对 service () 方法做任何动作,只需要根据来自客户端的请求类型来重写 doGet () 或 doPost () 即可。一般情况下不重写这个方法

# doGet () 方法

GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet () 方法处理。

# doPost () 方法

POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost () 方法处理。

# destroy () 方法

destroy () 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy () 方法可以让 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。

在调用 destroy () 方法之后,servlet 对象被标记为垃圾回收。

# Servlet 过滤器

Servlet 过滤器可以被当做一个只需要在 web.xml 文件中配置就可以灵活使用、重用的模块化组件。它能够对 JSP、HTML 和 Servlet 文件进行过滤


实现一个过滤器需要以下步骤:

  1. 实现接口

    javax.servlet.Filter;
  2. 实现三个方法

    1. 初始化方法

      public void init(FilterConfig config);
    2. 消亡方法

      public void destroy();
    3. 过滤函数

      public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain);
      // 使用过滤器解决乱码问题
      // 在本方法内设置
      // request.stCharacterEncoding("gb2312");
      // chain.doFilter(request,resonse);

然后再 web.xml 里面配置过滤器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <filter>
        <filter-name>用来设定过滤器的名字</filter-name>
        <filter-class>用来设定过滤器的类路径</filter-class>
        <init-param>
            <param-name></param-name>
            <param-value></param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>上面设定的名字</filter-name>
        <url-pattern>指定过滤的模式</url-pattern>
    </filter-mapping>
</web-app>

一般常见的过滤模式:

  1. 过滤掉所有文件

    <filter-mapping>
            <filter-name>FilterName</filter-name>
            <url-pattern>/*</url-pattern>
    </filter-mapping>

    意义:访问所有文件之前过滤器都要进行过滤

  2. 过滤一个或者多个 Servlet

    <filter-mapping>
            <filter-name>FilterName</filter-name>
            <url-pattern>/PATH/ServletName1</url-pattern>
        </filter-mapping>
        <filter-mapping>
            <filter-name>FilterName</filter-name>
            <url-pattern>/PATH/ServletName2</url-pattern>
        </filter-mapping>

    意义:过滤 ServletName1 和 ServletName2

  3. 过滤一个或者多个目录

    <filter-mapping>
            <filter-name>FilterName</filter-name>
            <url-pattern>/PATH/*</url-pattern>
        </filter-mapping>

    意义:在访问之前 PATH 路径下的资源时,过滤器需要进行过滤

注意:过滤器的 doFilter 是在 Servlet 被调用之前调用的