zoukankan      html  css  js  c++  java
  • Java Web进阶——Filter过滤器

    一、过滤器的介绍:

    • 在Servlet规范2.3中定义了过滤器,它是一个服务器端的组件,可以截取用户端的请求与响应信息,并且对这些信息进行过滤。
    • Servlet过滤器本身并不生成请求和响应对象,只是提供过滤功能。
    • Servlet过滤器能够在Servlet被调用之前检查Request对象,并修改Request Header和Request内容。
    • Servlet过滤器可以过滤的Web组件包括Servlet,JSP和HTML等文件。

    本文源码——GitHub:

     https://github.com/imperio-wxm/wordpressCode/tree/master/Filter


    二、过滤器在实际开发中的应用场景

    1.对用户请求进行统一认证
    2.编码转换
    3.对用户发送的数据进行过滤替换
    4.转换图像格式
    5.对相应的内容进行压缩

    三、过滤器的工作原理

    【没有过滤器】:

    用户直接访问WEB资源。

    【有过滤器】:

    WEB容器启动时进行过滤器的加载,用户发出请求到过滤器,过滤器判断请求是否符合规则,符合规则的请求通过过滤器发送给WEB资源,WEB资源响应的信息返回给过滤器,过滤器再将WEB资源的响应返回给用户。


    四、过滤器的生命周期(类似Servlet的生命周期)

    1.实例化——通过web.xml进行配置加载,在容器启动时只会实例化一次
    2.初始化——调用init()方法,加载信息只会执行一次
    3.过滤——使用doFilter()方法进行多次过滤
    4.销毁——WEB容器关闭时调用destroy()方法进行销毁

    所有的Servlet过滤器都必须实现javax.servlet.Filter接口,并实现该接口中的三个方法。

    【init()方法】
    • 这是过滤器的初始化方法,web容器创建过滤器实例后将调用这个方法。这个方法中可以web.xml文件中过滤器的参数。
    【doFilter()方法】
    • 这个方法完成实际的过滤操作。这个地方是过滤器的核心方法,当用户请求访问与过滤器关联的URL时,web容器将先调用过滤器的doFilter方法。
    • FilterChain方法参数可以调用chain.doFilter方法,将请求传给下一个过滤器(或目标资源),或利用转发、重定向请求转发到其他资源。
    【destroy()方法】
    • web容器在销毁过滤器实例前调用该方法,在这个方法中可以释放过滤器占用的资源。

    【生命周期代码演示】

    复制代码
    package com.filter;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    /**
     * Created by wxm-Imperio
     */
    public class FirstFilter implements Filter {
       @Override
       public void destroy() {
          System.out.println("destroy,firstFilter");
       }
       @Override
       public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 
          throws IOException, ServletException { System.out.println("start,doFilter,firstFilter"); filterChain.doFilter(servletRequest, servletResponse); System.out.println("End,doFilter,firstFilter"); } @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("init。firstFilter"); } }
    复制代码

    【web.xml配置】

    复制代码
    <filter>
         <filter-name>Filter的名字</filter-name>
         <filter-class>Filter类的名字</filter-class>
         <init-param>
         <description>描述信息可以省略或者放在此处</description>
         <param-name>参数名称</param-name>
         <param-value>参数的值</param-value>
         </init-param>
    </filter>
    <filter-mapping>
         <filter-name>Filter的名字</filter-name>
         <url-pattern>URL</url-pattern>
         <dispatcher></dispatcher>//过滤器类型
    </filter-mapping>
    复制代码

    注意:一般Filter配置在所有的Servlet之前。


    五、支持多个过滤器

    • 每个过滤器有不同的URL地址
    • 当不同的过滤器URL地址相同时,会生成过滤器链:
    • 用户请求——依次每个过滤器——web资源(顺序是:服务器按照web.xml中过滤器定义的先后顺序组成一条链)
    【用户请求】——>【过滤器1Chain.doFilter前代码——>过滤器1Chain.doFilter——>过滤器2Chain.doFilter前代码——>过滤器1Chain.doFilter.......】——>【Servlet的Service方法处理请求】——>...........【过滤器2Chain.doFilter后代码——>过滤器1Chain.doFilter后代码】——>【返回用户请求】

    【过滤器链的web.xml配置】

    复制代码
    <!--过滤器1的配置信息--!>
    <filter>
         <filter-name>Filter1的名字</filter-name>
         <filter-class>Filter1类的名字</filter-class>
         <init-param>
         <description>描述信息可以省略或者放在此处</description>
         <param-name>参数名称</param-name>
         <param-value>参数的值</param-value>
         </init-param>
    </filter>
    <filter-mapping>
         <filter-name>Filter1的名字</filter-name>
         <url-pattern>URL</url-pattern>
         <dispatcher></dispatcher>//过滤器类型
    </filter-mapping>
    
    <!--过滤器2的配置信息--!>
    <filter>
         <filter-name>Filter2的名字</filter-name>
         <filter-class>Filter2类的名字</filter-class>
         <init-param>
         <description>描述信息可以省略或者放在此处</description>
         <param-name>参数名称</param-name>
         <param-value>参数的值</param-value>
         </init-param>
    </filter>
    <filter-mapping>
         <filter-name>Filter2的名字</filter-name>
         <url-pattern>URL</url-pattern>
         <dispatcher></dispatcher>//过滤器类型
    </filter-mapping>
    复制代码

    注意:过滤器的执行顺序就是在web.xml里配置的顺序。


    六、过滤器的分类

    Servlet2.5:

    1.REQUEST(默认)用户直接访问页面时,web容器将会调用过滤器。
    2.FORWORD 目标源是通过RequestDispatcher的forword方法访问时,该过滤器被调用。
    3.INCLUDE 目标资源时通过RequestDispatcher的include方法调用时,过滤器被调用。
    4.ERROR 目标资源是通过声明式异常处理机制调用时,过滤器将被调用。
     
    【语法】
    @WebFilter(servletNames = {"SimpleServlet"} filterName = "SimpleFilter")
    
    public class LessThanSixFilter implements Filter {
    //类中内容
    }

    【ERROR的配置信息】

    复制代码
    <error-page>
       <error-code>404</error-code>
       <location>/error.jsp</location>
    </error-page>
    
    <filter>
       <filter-name>errorFilter</filter-name>
       <filter-class>com.filter.ErrorFilter</filter-class>
    </filter>
    <filter-mapping>
       <filter-name>errorFilter</filter-name>
       <url-pattern>/error.jsp</url-pattern>
    </filter-mapping>
    复制代码

    【ErrorFilter过滤器代码】

    复制代码
    public class ErrorFilter implements Filter {
       @Override
       public void destroy() {
       }
       @Override
       public void init(FilterConfig filterConfig) throws ServletException {
       }
       @Override
       public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 
        throws IOException, ServletException { System.out.println("检测到有错误信息"); } }
    复制代码

    Servlet3.0:

    (新增)ASYNC 支持异步处理
    • @WebFilter(引言)用于将一个声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置相应的类部署为过滤器

    【异步操作处理代码:过滤器不等待线程,直接执行后面内容,实现异步处理】

    AsynServlet

    复制代码
    //设置Servlet支持异步
    @WebServlet(name = "AsynServlet", asyncSupported = true)
    public class AsynServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException { System.out.println("Servlet执行开始时间" + new Date()); //实现异步操作 AsyncContext context = request.startAsync(); //开启异步线程 new Thread(new Executor(context)).start(); System.out.println("Servlet执行结束时间" + new Date()); } protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException { doPost(request, response); } //内部类模拟线程 public class Executor implements Runnable { private AsyncContext context; //实现构造方法 public Executor(AsyncContext context) { this.context = context; } @Override public void run() { //执行相关的复杂业务 try { Thread.sleep(1000 * 10); //context.getRequest(); //context.getResponse(); System.out.println("业务执行完成时间" + new Date()); } catch (InterruptedException e) { e.printStackTrace(); } } } }
    复制代码

    AsvnFilter过滤器

    复制代码
    //注解
    @WebFilter(filterName = 
      "AsynFilter", value = {"/AsynServlet"}, asyncSupported = true, dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.ASYNC}) public class AsynFilter implements Filter { @Override public void destroy() { } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
         throws IOException, ServletException { System.out.println("Start..........AsynFilter"); filterChain.doFilter(servletRequest, servletResponse); System.out.println("End..........AsynFilter"); } }
    复制代码

    web.xml配置

    复制代码
    <servlet>
       <servlet-name>AsynServlet</servlet-name>
       <servlet-class>com.servlet.AsynServlet</servlet-class>
    </servlet>
    <servlet-mapping>
       <servlet-name>AsynServlet</servlet-name>
       <url-pattern>/AsynServlet</url-pattern>
    </servlet-mapping>
    复制代码

    七、FilterConfig的使用

    Filter的init方法中提供了一个FilterConfig对象,提供相关的操作:

    如获取Filter中配置的初始化参数web.xml配置:

    复制代码
    <filter>
          <filter-name>LoginFilter</filter-name>
          <filter-class>com.itzhai.login.LoginFilter</filter-class>
          <init-param>
              <param-name>username</param-name>
              <param-value>arthinking</param-value>
          </init-param>
    </filter>
    复制代码

    在init()方法中获取:

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //获取Filter初始化参数
        String username = filterConfig.getInitParameter("username");
    }

    在Filter中访问application:

    ServletContext context = filterConfig.getServletContext();

    也可以在doFilter方法中根据转换好的request获取:

    HttpServletRequest req = (HttpServletRequest)request;
    ServletContext context = req.getSession().getServletContext();

    八、项目实例

    慕课网中用户登录的加强版Demo,利用过滤器对用于请求和服务器回应进行过滤。

    GitHub源码:https://github.com/imperio-wxm/projectDemo

  • 相关阅读:
    计算几何——交点、面积的计算
    计算几何——认识基本object:点、线、面 。
    图的拓扑排序——卡恩算法
    Manacher
    如何不改造 HBase 就能应对复杂查询场景
    如何做沟通
    大数据磁盘阵列技术
    Android系统架构开篇
    Apache Kylin 原理介绍与新架构分享(Kylin On Parquet)
    遭遇突然提问慌了?掌握关键2点完美应对zz
  • 原文地址:https://www.cnblogs.com/AutumnRhyme/p/4316280.html
Copyright © 2011-2022 走看看