初探ServletFilter过滤器

一、什么是过滤器

Servlet过滤器是在Java Servlet规范2.3中定义的,它能够对Servlet容器的请求和响应对象进行检查和修改。   

Servlet过滤器本身并不产生请求和响应对象,它只能提供过滤作用。Servlet过期能够在Servlet被调用之前检查Request对象,修改Request Header和Request内容;在Servlet被调用之后检查Response对象,修改Response Header和Response内容。

Servlet过期负责过滤的Web组件可以是Servlet、JSP或者HTML文件。

过滤器是一个服务器端的组件,它可以截取用户端的请求与响应信息,并对这些信息过滤。

 

二、过滤器链

一个 Web 应用中可以一次编写多个过滤器,这些过滤器的组合

称之为过滤器链。

在过滤器链中,过滤器的执行顺序依据过滤器在部署描述符web .xml 中注册的顺序

过滤器链体现了一种职责链模式,是设计模式中的一种。

 职责链模式:

   能够使多个对象,都有机会处理请求,它将多个对象连成一个链条,

并沿着这个链条传递请求,直到有一个对象最终处理它为止。

 职责链模式能够避免请求的发送者和接受者之间的耦合关系。

   对于过滤器而言,请求传递给具体的Web 资源之前,都会经过

过滤器的处理,在 Web 资源处理完该请求之后-返回响应给客户

端之前,响应信息也会被过滤器处理一遍

  

一个简单的过滤器链实例

  

访问指定资源之前打印若干日志,访问指定资源之后再打印若干日志

点击选择工程名,右键->New->Filter,包名为:com.whohim.filter,

类名为:FilterOne、FilterTwo

FilterOne.java:

package com.whohim.filter;

  

import java.io.IOException;

  

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

  

  

public class FilterOne implements Filter {

  

 

public FilterOne() {

System.out.println("===== FilterOne 构造方法 =====");

}

 

 

publicvoid init(FilterConfig fConfig) throws ServletException {

System.out.println("===== FilterOne 初始化方法 =====");

String initParam=fConfig.getInitParameter("param");

System.out.println("param = "+initParam);

}

  

 

publicvoid doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

System.out.println("===== 开始执行FilterOne doFilter方法 =====");

chain.doFilter(request, response);

System.out.println("===== 结束执行FilterOne doFilter方法 =====");

}

  

 

publicvoid destroy() {

System.out.println("===== FilterOne 销毁方法 =====");

}

  

}

  

  

  

FilterTwo.java:

  

package com.whohim.filter;

  

import java.io.IOException;

  

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

  

/**

* 多个过滤器组合起来,为过滤器链

* 在过滤器链中,过滤器的执行顺序是部署描述符中注册的顺序

*

* 过滤器链体现了一种职责链模式是设计模式中的一种

*/

public class FilterTwo implements Filter {

  

 

public FilterTwo() {

System.out.println("===== FilterTwo 构造方法 =====");

}

  

 

publicvoid init(FilterConfig fConfig) throws ServletException {

System.out.println("===== FilterTwo 初始化方法 =====");

}

  

 

publicvoid doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

System.out.println("===== 开始执行FilterTwo doFilter方法 =====");

chain.doFilter(request, response);

System.out.println("===== 结束执行FilterTwo doFilter方法 =====");

}

 

 

publicvoid destroy() {

System.out.println("===== FilterTwo 销毁方法 =====");

}

  

}

  

  

  

在部署描述符web.xml 中注册 filter:

  

<?xmlversion="1.0"encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://xmlns.jcp.org/xml/ns/javaee"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1">

<display-name>MyServlet</display-name>

<welcome-file-list>

<welcome-file>index.html</welcome-file>

<welcome-file>index.htm</welcome-file>

<welcome-file>index.jsp</welcome-file>

<welcome-file>default.html</welcome-file>

<welcome-file>default.htm</welcome-file>

<welcome-file>default.jsp</welcome-file>

</welcome-file-list>

 

<filter>

<filter-name>FilterOne</filter-name>

<filter-class>com.whohim.filter.FilterOne</filter-class>

<init-param>

<param-name>param</param-name>

<param-value>whohim</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>FilterOne</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

  

<filter>

<filter-name>FilterTwo</filter-name>

<filter-class>com.whohim.filter.FilterTwo</filter-class>

</filter>

<filter-mapping>

<filter-name>FilterTwo</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

 

</web-app>

  

  

部署描述符web.xml 在 WEB-INF 目录下,如果没有,手动创建即可

  

点击选择工程名,右键->Java EE Tools->Generate Deployment Descriptor Stub

  

启动 Tomcat 时,过滤器的执行:  

<!-- 定义Filter -->

<filter>

<!-- Filter的名字 -->

<filter-name>log</filter-name>

<!-- Filter的实现类 -->

<filter-class>lee.LogFilter

</filter-class>

</filter>

<!-- 定义Filter拦截的URL地址 -->

<filter-mapping>

<!-- Filter的名字 -->

<filter-name>log</filter-name>

<!-- Filter负责拦截的URL 全部以/的请求,如果<url-pattern>/*.action </>,将会以拦截*.action的请求-->

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

在Servlet2.4中filter-mapping中加入了新的标签<dispatcher> ,里面有4个值即REQUEST, FORWARD,INCLUDE和ERROR,默认不写这个标签的时候是REQUEST,该标签是根据客户端传过来的地址进行过滤,FORWARD方法传过来的request方法可以拦截,<ERROR-PAGE>错误页面传过来的拦截,INCLUDE包含过来的过滤,一般REQUEST传过来的拦截.该标签可以加入多个.

下面例子是引用网上的:

例1:

Xml代码

<filter-mapping>

<filter-name>Logging Filter</filter-name>

<url-pattern>/products/*</url-pattern>

</filter-mapping>

 

这种情况下,过滤器将会作用于直接从客户端发过来的以/products/…开始的请求。因为这里没有制定任何的< dispatcher >元素,默认值是REQUEST。

例2:

Xml代码

<filter-mapping>

<filter-name>Logging Filter</filter-name>

<servlet-name>ProductServlet</servlet-name>

<dispatcher>INCLUDE</dispatcher>

</filter-mapping>

 

这种情况下,如果请求是通过request dispatcher的include方法传递过来的对ProductServlet的请求,则要经过这个过滤器的过滤。其它的诸如从客户端直接过来的对ProductServlet的请求等都不需要经过这个过滤器。

指定filter的匹配方式有两种方法:直接指定url-pattern和指定servlet,后者相当于把指定的servlet对应的url-pattern作为filter的匹配模式

filter的路径匹配和servlet是一样的,都遵循servlet规范中《SRV.11.2 Specification of Mappings》一节的说明

例3:

Xml代码

<filter-mapping>

<filter-name>Logging Filter</filter-name>

<url-pattern>/products/*</url-pattern>

<dispatcher>FORWARD</dispatcher>

<dispatcher>REQUEST</dispatcher>

</filter-mapping>

在这种情况下,如果请求是以/products/…开头的,并且是通过request dispatcher的forward方法传递过来或者直接从客户端传递过来的,则必须经过这个过滤器。

三、过滤器的分类

第一个案例:


public class FirstFilter implements Filter {

    @Override

    public void destroy() {

        System.out.println("destroy---FirstFilter");

    }

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throwsIOException, ServletException {

        System.out.println("start----doFilter--FirstFilter");

//      chain.doFilter(request, response);

        HttpServletRequest req =(HttpServletRequest)request;

        HttpServletResponse response2 =(HttpServletResponse) response;

        //重定向

        response2.sendRedirect(req.getContextPath()+"/main.jsp");

        //转发

//      req.getRequestDispatcher("main.jsp").forward(request, response);

//      req.getRequestDispatcher("main.jsp").include(request, response);

        System.out.println("end------doFilter--FirstFilter");

    }

    @Override

    public void init(FilterConfig filterConfig) throwsServletException {

        System.out.println("init----FirstFilter");

    }

}


public class ErrorFilter implements Filter {

    @Override

    public void destroy() {

        // TODO Auto-generated method stub

    }

    @Override

    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throwsIOException, ServletException {

        // TODO Auto-generated method stub

        System.out.println("检测到有错误信息");

        arg2.doFilter(arg0, arg1);//加上这句就能拦截404网页

    }

    @Override

    public void init(FilterConfig arg0) throwsServletException {

        // TODO Auto-generated method stub

    }

}


web.xml:

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5"

    xmlns="http://java.sun.com/xml/ns/javaee"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <display-name></display-name> 

  <welcome-file-list>

    <welcome-file>index.jsp</welcome-file>

  </welcome-file-list>

    <filter>

        <filter-name>FirstFilter</filter-name>

        <filter-class>com.imooc.filter.FirstFilter</filter-class>

        <init-param>

            <param-name>name</param-name>

            <param-value>zhangsan</param-value>

        </init-param>

    </filter>

    <filter-mapping>

        <filter-name>FirstFilter</filter-name>

        <url-pattern>/index.jsp</url-pattern>

    </filter-mapping>

    

   <!--  <filter-mapping>

        <filter-name>FirstFilter</filter-name>

        <url-pattern>/main.jsp</url-pattern>

        <dispatcher>FORWARD</dispatcher>

    </filter-mapping> -->

  

    <!--

    <filter>

        <filter-name>SecondFilter</filter-name>

        <filter-class>com.imooc.filter.SecondFilter</filter-class>

    </filter>

    <filter-mapping>

        <filter-name>SecondFilter</filter-name>

        <url-pattern>/index.jsp</url-pattern>

    </filter-mapping>

  -->

 

  <error-page>

    <error-code>404</error-code>

    <location>/error.jsp</location>

  </error-page>

  <!--

  <error-page>

    <error-code>500</error-code>

    <location>/error500.jsp</location>

  </error-page>

   -->

    <filter>

        <filter-name>ErrorFilter</filter-name>

        <filter-class>com.imooc.filter.ErrorFilter</filter-class>

    </filter>

    <filter-mapping>

        <filter-name>ErrorFilter</filter-name>

        <url-pattern>/error.jsp</url-pattern>

        <dispatcher>ERROR</dispatcher>

    </filter-mapping>

 

</web-app>


@WebFilter是什么?

@WebFilter用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。

例子:


@WebFilter(filterName = "AsynFilter",value = {"/index.jsp"},dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.ASYNC})

public class AsyncFilter implements Filter {

    @Override

    public void destroy() {

        // TODO Auto-generated method stub

    }

    @Override

    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)

            throws IOException, ServletException {

        System.out.println("begin..Filter");

        arg2.doFilter(arg0, arg1);

        System.out.println("end..Filter");

    }

    @Override

    public void init(FilterConfig arg0) throwsServletException {

        // TODO Auto-generated method stub

    }

}


(异步)AsyncFilter:

/**

 * Servlet implementation class AsynServlet

 */

@WebServlet(asyncSupported = true, urlPatterns = {"/AsynServlet" })

public class AsynServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    /**

     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse

     *      response)

     */

    protected void doGet(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());

    }

    public class Executor implements Runnable {

        private AsyncContext context;

        public Executor(AsyncContext context) {

            this.context = context;

        }

        @Override

        public void run() {

            // 执行复杂业务

            try {

                Thread.sleep(1000 * 5);

                context.getRequest();

                context.getResponse();

                System.out.println("业务执行完成" + newDate());

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

}

登录及转码案例:

public class LoginServlet extends HttpServlet {

    /**

     * Constructor of the object.

     */

    public LoginServlet() {

        super();

    }

    /**

     * Destruction of the servlet. <br>

     */

    public void destroy() {

        super.destroy(); // Just puts "destroy" string in log

        // Put your code here

    }

    

    /**

     * The doPost method of the servlet. <br>

     *

     * This method is called when a form has its tag value method equals to post.

     *

     * @param request the request send by the client to the server

     * @param response the response send by the server to the client

     * @throws ServletException if an error occurred

     * @throws IOException if an error occurred

     */

    public void doPost(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {

        String username =request.getParameter("username");

        String password =request.getParameter("password");

        

        System.out.println(username);

        

        if("admin".equals(username) &&"admin".equals(password)){

            //校验通过

            HttpSession session = request.getSession();

            session.setAttribute("username", username);

            response.sendRedirect(request.getContextPath()+"/sucess.jsp");

        }else{

            //校验失败

            response.sendRedirect(request.getContextPath()+"/fail.jsp");

        }

        

    }

    /**

     * Initialization of the servlet. <br>

     *

     * @throws ServletException if an error occurs

     */

    public void init() throws ServletException {

        // Put your code here

    }

}


public class LoginFilter implements Filter {

    private FilterConfig config;

    @Override

    public void destroy() {

    }

    @Override

    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)

            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest)arg0;

        HttpServletResponse response = (HttpServletResponse) arg1;

        HttpSession session = request.getSession();

        /*

         * 编码转换

         */

        String charset = config.getInitParameter("charset");

        if (charset == null) {

            charset = "UTF-8";

        }

        request.setCharacterEncoding(charset);

        /*

         * 编码转换

         */

        String noLoginPaths =config.getInitParameter("noLoginPaths");

        if (noLoginPaths != null) {

            String[] strArray = noLoginPaths.split(";");

            for (int i = 0; i < strArray.length; i++) {

                if (strArray[i] == null || "".equals(strArray[i]))

                    continue;

                if(request.getRequestURI().indexOf(strArray[i]) != -1) {

                    // indexOf 字符在字串strArray[i]后出现的第一个位置.没有找到返回-1

                    arg2.doFilter(arg0, arg1);

                    return;

                }

            }

        }

        if (session.getAttribute("username") != null) {

            arg2.doFilter(arg0, arg1);

        } else {

            response.sendRedirect("login.jsp");

        }

    }

    @Override

    public void init(FilterConfig arg0) throwsServletException {

        config = arg0;

    }

}


web.xml:

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5"

    xmlns="http://java.sun.com/xml/ns/javaee"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <display-name></display-name>

  <servlet>

    <description>This is the description of my J2EE component</description>

    <display-name>This is the display name of my J2EE component</display-name>

    <servlet-name>LoginServlet</servlet-name>

    <servlet-class>com.imooc.serlvet.LoginServlet</servlet-class>

  </servlet>

  <servlet-mapping>

    <servlet-name>LoginServlet</servlet-name>

    <url-pattern>/servlet/LoginServlet</url-pattern>

  </servlet-mapping>    

  <welcome-file-list>

    <welcome-file>index.jsp</welcome-file>

  </welcome-file-list>

    <filter>

        <filter-name>LoginFilter</filter-name>

        <filter-class>com.imooc.filter.LoginFilter</filter-class>

        <init-param>

            <param-name>noLoginPaths</param-name>

            <param-value>login.jsp;fail.jsp;LoginServlet</param-value>

        </init-param>

        <init-param>

            <param-name>charset</param-name>

            <param-value>UTF-8</param-value>

        </init-param>

    </filter>

    <filter-mapping>

        <filter-name>LoginFilter</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>

</web-app>

猜你喜欢

转载自blog.csdn.net/a600849155/article/details/81129895
今日推荐