java进阶知识--Servlet技术 一、初识Servlet 二、Servlet配置 三、过滤器--Filter 四、监听器--Listener

 1.1 概述

    Servlet就是一个用java语言编写的接口,定义了Java类被浏览器访问到的规则。
    Servlet技术是应用到web服务器端的扩展技术,对http请求进行处理,主要用于处理各种业务逻辑。

    注意:1. 对http请求进行处理,实际为servlet接口的实现类HttpServlet提供了处理请求的方法;
       2. Servlet的具体细节需要由Servlet容器进行实现,Servlet对象在Servlet容器启动时被初始化。

 1.2 特点

    功能强大、可移植、性能高效、安全性高、可扩展性好。

 1.3 生命周期

    1. 创建:执行init方法,只执行一次
      * Servlet什么时候被创建?
        * 默认情况下,第一次被访问时,Servlet被创建
        * 可以配置执行Servlet的创建时机,默认下的默认值为-1。
          * 在<servlet>标签下配置
            1. 第一次被访问时创建
              * <load-on-startup>的值为负数
            2. 在服务器启动时创建
              * <load-on-startup>的值为0或正整数
              * Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
        * 多个用户同时访问时,可能存在线程安全问题。
          * 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对其修改值。
    2. 运行:执行service方法,执行多次
      * 每次访问Servlet时,Service方法都会被调用一次。
    3. 销毁:执行destroy方法,只执行一次
      * Servlet被销毁时执行。服务器关闭时,Servlet被销毁。
      * destroy方法在Servlet被销毁之前执行,一般用于释放资源。
      * 只有服务器正常关闭时,才会执行destroy方法。

  1.4 Servlet的体系结构

        Servlet -- 接口
          |
        GenericServlet -- 抽象类
          |
        HttpServlet  -- 抽象类
        
        * GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象
          * 将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可
        * HttpServlet:对http协议的一种封装,简化操作:
          1. 定义类继承HttpServlet
          2. 复写doGet/doPost方法

二、Servlet配置

 2.1 web.xml配置

    在web.xml中配置,以告知web容器哪一个请求调用哪一个Servlet对象处理,对Servlet起到一个注册的作用

// 声明Servlet对象
<servlet>
	<servlet-name>WfxServlet</servlet-name>						--Servlet名称
	<servlet-class>com.wfx.WfxServlet</servlet-class>			--Servlet对象的完整位置
</servlet>
// 映射Servlet
<servlet-mapping>
	<servlet-name>WfxServlet</servlet-name>						--Servlet名称
	<url-pattern>/WfxServlet</url-pattern>						--映射访问URL
</servlet-mapping>

    执行流程:

      1. 当服务器接收到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径;
      2. 查找web.xml文件,是否有对应的<url-pattern>标签体内容与资源路径一致;
      3. 如果有,则在找到对应的<servlet-class>全类名;
      4. tomcat会将字节码文件加载进内存,并且创建其对象;
      5. 调用其方法。如:service()方法。

 2.2 Servlet3.0 注解配置

 小贴士:

  Servlet3.0新特性
    ①支持注解配置。新增注解@WebServlet、@WebFilter、@WebListener、@WebInitParam等,通过使用注解就无需在web.xml文件中对Servlet、过滤器或者监听器等进行配置。
    ②对文件上传的支持。文件上传需两步:a.添加@MultipartConfig注释。 b.从request对象中获取Part文件对象。
    ③异步处理:Servlet线程将请求交给一个异步线程来执行业务处理,线程本身返回至容器,异步线程处理完业务后,可以直接生成响应数据,或者将请求继续转发给其他Servlet。
      (这样,Servlet线程不再是一直处于阻塞状态以等待业务逻辑的处理,而是启动异步之后可以立即返回。)
  异步处理机制可以应用于Servlet和过滤器两种组件,那么如何开启异步处理特性?(默认情况下为关闭异步处理)
    ==》方法一(配置文件):<async-supported>true</async-supported>
    ==》方法二(注解):@WebServlet和@WebFilter注解提供了asyncSupported属性,默认情况下为false,将其设置成true即可。

    执行步骤:

      1. 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
      2. 定义一个类,实现Servlet接口
      3. 复写方法
      4. 在类上使用@WebServlet注解,进行配置
        * @WebServlet("资源路径")

    资源路径:Servlet访问路径

      1. 一个Servlet可以定义多个访问路径: @WebServlet({"/url1","/url2","/url3"})
      2. 路径定义规则:
        a.  /xxx:路径匹配
        b.  /xxx/xxx:多层路径,目录结构
        c.  *.do:扩展名匹配

    @WebServlet注解源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
	String name() default "";			//相当于<Servlet-name>

	String[] value() default {};		//代表urlPatterns()属性配置

	String[] urlPatterns() default {};	//相当于<url-pattern>

	int loadOnStartup() default -1;		//相当于<load-on-startup>

	WebInitParam[] initParams() default {};

	boolean asyncSupported() default false;

	String smallIcon() default "";

	String largeIcon() default "";

	String description() default "";

	String displayName() default "";
}

三、过滤器--Filter

 3.1 概述

    实质上就是在web应用服务器上的一个web应用组件,用于拦截客户端和目标资源的请求,并对这些请求进行一定过滤处理再发送给目标资源。(过滤器可以改变请求中的内容)

    过滤器对象放置在javax.servlet包中,均为接口:
      Filter(核心对象)接口:每一个过滤器对象都要直接或间接的实现此接口,其定义了三个方法:
        init()方法:过滤器初始化方法,该方法在过滤器初始化时被调用。
        doFilter()方法:对请求进行过滤处理。
        destory()方法:销毁方法,以便释放资源。
      FilterConfig接口:由Servlet容器进行实现,主要用于获取过滤器中的配置信息。
      FilterChain接口(传递工具):由Servlet容器进行实现,在这个接口中,只有一个doFilter方法。
        doFilter()方法:将过滤后的请求传递给下一个过滤器,直到传递给目标资源。

 3.2 执行步骤

    1. 定义一个类,实现接口Filter
    2. 复写方法
    3. 配置拦截路径
      * web.xml配置
      * 注解配置

   3.2.1 web.xml配置

<!-- 过滤器的配置 -->
// 过滤器的声明
<filter>
	<filter-name>WfxFilter</filter-name>						--过滤器名称
	<filter-class>com.wfx.WfxFilter</filter-class>				--过滤器完整类名
	<init-param>												--初始化参数(可选)
		<param-name>encoding</param-name>						--参数名
		<param-value>UTF-8</param-value>						--参数值
	</init-param>
</filter>
// 过滤器映射
<filter-mapping>
	<filter-name>WfxFilter</filter-name>						--过滤器名称
	<url-pattern>/WfxFilter</url-pattern>						--过滤器URL映射(/*表示匹配所有请求)
</filter-mapping>

   3.2.2 注解配置@WebFilter("/拦截路径") 

@WebFilter("/拦截路径")	//访问所有资源之前,都会执行该过滤器
public class WfxFilter implements Filter {
	/**
	* 在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源。
	*/
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		//初始化
	}

	/**
	* 每一次请求被拦截资源时会执行。执行多次。
	*/
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 
			throws IOException, ServletException {
		//放行
		filterChain.doFilter(servletRequest, servletResponse);
	}

	/**
	* 在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。
	* 只执行一次。用于释放资源。
	*/
	@Override
	public void destroy() {

	}
}

   3.2.3 过滤器配置详解

       * 拦截路径配置:
        1. 具体资源路径。  比如:/index.jsp  只有访问index.jsp资源时,过滤器才会被执行
        2. 拦截目录。    比如:/user/*    访问/user下的所有资源时,过滤器都会被执行
        3. 后缀名拦截。   比如:*.jsp     访问所有后缀名为jsp资源时,过滤器都会被执行
        4. 拦截所有资源。  比如:/*       访问所有资源时,过滤器都会被执行
      * 拦截方式配置:资源被访问的方式
        * web.xml配置
          * 设置<dispatcher></dispatcher>标签即可
        * 注解配置:
          * 设置dispatcherTypes属性
            1. REQUEST:默认值。浏览器直接请求资源
            2. FORWARD:转发访问资源
            3. INCLUDE:包含访问资源
            4. ERROR:错误跳转资源
            5. ASYNC:异步访问资源

 3.3 过滤器链(配置多个过滤器)

    过滤器先后顺序问题:
      1. web.xml配置: <filter-mapping>谁定义在上边,谁先执行
      2. 注解配置:按照类名的字符串比较规则比较,值小的先执行
        * 如: AFilter 和 BFilter,AFilter就先执行了。

四、监听器--Listener

 4.1 概述

    由容器管理,用于监听web容器的有效期事件。(比如数据库连接的建立与释放,session的创建与销毁,程序启动和关闭等)

    监听原理:可以监听由于web应用中状态而引起的servlet容器产生的相应事件,然后接受并处理这些事件。

 4.2 事件监听机制

    * 事件:一件事情(监听ServletContext对象创建的)
    * 事件源:事件发生的地方(如tomcat)
    * 监听器:一个对象(监听器类)
    * 注册监听:将事件、事件源、监听器绑定在一起。当事件源上发生某个事件后,执行监听器代码。

 4.3 监听器的创建

    监听器的创建有很多种,如servlet上下文监听、http会话监听、servlet请求监听,根据不同场景实现不同接口。

    步骤:

      1. 定义一个类,实现ServletContextListener接口
        * ServletContextListener接口:监听ServletContext对象的创建和销毁
          * 方法:
            * void contextInitialized(ServletContextEvent sce):ServletContext对象创建后会调用该方法
            * void contextDestroyed(ServletContextEvent sce):ServletContext对象被销毁之前会调用该方法
      2. 复写方法
      3. 配置
        * web.xml配置
          <listener>
            <listener-class>监听器类</listener-class>
          </listener>
          * 指定初始化参数<context-param>
        * 注解配置
          * @WebListener

 小贴士:

  关于监听器、过滤器、拦截器三大组件的细节与区别,可参考以下链接进一步了解

  https://www.cnblogs.com/lukelook/p/11079113.html#t1

  https://www.sohu.com/a/287773228_120045139

  https://www.zhihu.com/question/35225845