• Java Web(四) 过滤器Filter


    Filter概述

    Filter意为滤镜或者过滤器,用于在Servlet之外对request或者response进行修改。Filter提出了过滤链的概念。一个FilterChain包括多个Filter。客户端请求request在抵达Servlet之前会经过FilterChian里的所有Filter,服务器响应response在从Servlet抵达客户端浏览器之前也会经过FileterChain里的所有Filter。Filter处理过程如图所示。

    img

    Filter接口

    一个Filter必须实现javax.servlet.Filter接口。Filter有三个方法。

    public interface Filter {
        default void init(FilterConfig filterConfig) throws ServletException {
        }
    
        void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
    
        default void destroy() {
        }
    }
    

    这三个方法反映了Filter的生命周期,其中init与dstory只会被调用一次,分别在web程序加载和卸载的时候调用。而doFilter()方法每次有客户端请求时都会被调用一次。Filter的所有工作集中在doFilter方法中,另外可从init方法传入的filterConfig对象得到filter的初始化参数。

    下面是Filter的一个简单实现。

    public class TestFilter implements Filter {
        public void destroy() {
            System.out.println("我被销毁了");
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            System.out.println("在请求到达Servlet之前我输出了");
            chain.doFilter(req, resp);
            System.out.println("在响应到达客户端之前我输出了");
        }
    
        public void init(FilterConfig config) throws ServletException {
            System.out.println("我被初始化了");
            //得到初始化数据
            String value1 = config.getInitParameter("name1");
            String value2 = config.getInitParameter("name2");
            System.out.println(value1 + " " + value2);
        }
    
    }
    

    chain.doFilter(req, resp)将request递交给下一个FilterChain的下一个Filter,如果都走完了则交给Servlet处理。

    Filter配置

    Filter需要在web.xml或@WebFilter注解中配置才能生效。Filter的配置与Servlet的配置非常类似。

    在web.xml中需要配置<filter>与<filter-mapping>标签。

    <filter>
      <filter-name>filtername</filter-name>
      <filter-class>filter.TestFilter</filter-class>
      <init-param>
        <param-name>paraName</param-name>
        <param-value>paraValue</param-value>
      </init-param>
    </filter>
    <filter-mapping>
      <filter-name>filtername</filter-name>
      <url-pattern>*.do</url-pattern>
      <dispatcher>REQUEST</dispatcher>
      <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
    

    <filter>配置Filter名称,实现类,和初始化参数,可同时配置多个初始化参数,<filter-mapping>配置在什么规则下使用Filter,这两者的filter-name必须匹配。

    <url-pattern>配置URL的规则,可以配置多个,可以使用通配符()。例如"/jsp/"适用于本contextPath下以"/jsp"开头的Serlvet,"*.do"适用于所有以".do"结尾的Servlet路径。

    <dispatcher>配置到达Servlet的方式。有四种取值:REQUEST,FORWORD,INCLUDE,ERROR。可以同时配置多个<dispatcher>,如果没有配置<dispatcher>,默认为REQUEST。它们的区别为:

    • REQUEST:表示仅当直接请求Servlet时才生效。
    • FORWORD:表示仅当某Servlet通过FORWARD到该Servlet时才生效。
    • INCLUDE:JSP中可以通过jsp:include/请求某Servlet,仅在这种情况下有效。
    • ERROR:JSP中可以通过<%@ page errorPage="error.jsp" %>指定错误处理页面,仅在这种情况下有效。

    注意:一个Web程序可以配置多个Filter,这多个Filter的执行顺序有先有后,规则是<filter-mapping>配置在前面的Fliter执行要早与配置在后面的Filter,多个Filter之间可能会相互影响。

    在@WebFilter注解中配置,这样就简单多了

    @WebFilter(
            filterName = "MyFilter",
            urlPatterns = "*.do",
            initParams = {
                    @WebInitParam(name="paramName", value = "paramValue")
            },
            dispatcherTypes = REQUEST
    )
    

    应用:字符过滤器

    在Servlet里获取请求参数时经常遇到乱码问题,在每个Servlet里处理编码问题就非常麻烦,可以利用过滤器统一处理字符编码问题。你肯定会想到亲自实现那个HttpServletRequest接口,但是如果自己实现的话,要重写里面所有的方法,非常麻烦,所以java提供了HttpServletRequestWrapper类,它已经帮你实现了httpServletRequest接口,你只需要重写你想要重新定义的方法即可。

    /**
        增强了所有的获取参数的方法
        request.getParameterValues("name");
        request.getParameter("name");
        request.getParameterMap();
     */
    class MyRequest extends HttpServletRequestWrapper{
        private HttpServletRequest request;
        private boolean flag = true;
        public MyRequest(HttpServletRequest request) {
            super(request);
            this.request=request;
        }
        
        @Override
        public String getParameter(String name) {  
            if(name==null || name.trim().length()==0){
                return null;
            }
            String[] values = getParameterValues(name);
            if(values==null || values.length==0){
                return null;
            }
            return values[0];
        }
        
        @Override
        public String[] getParameterValues(String name) {
            if(name==null || name.trim().length()==0){
                return null;
            }
            Map<String, String[]> map = getParameterMap();
            if(map==null || map.size()==0){
                return null;
            }
            return map.get(name);
        }
        
        @Override
        public Map<String,String[]> getParameterMap() {  
            
            /**
             * 首先判断请求方式
             * 若为post  request.setchar...(utf-8)
             * 若为get 将map中的值遍历编码就可以了
             */
            String method = request.getMethod();
            if("post".equalsIgnoreCase(method)){
                try {
                    request.setCharacterEncoding("utf-8");
                    return request.getParameterMap();
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }else if("get".equalsIgnoreCase(method)){
                Map<String,String[]> map = request.getParameterMap();
                if(flag){
                    for (String key:map.keySet()) {
                        String[] arr = map.get(key);
                        //继续遍历数组
                        for(int i=0;i<arr.length;i++){
                            //编码
                            try {
                                arr[i]=new String(arr[i].getBytes("iso-8859-1"),"utf-8");
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    flag=false;
                }
                return map;
            }
            return super.getParameterMap();
        }
        
    }
    

    接着编写EncodeFilter过滤器,对请求的文本进行编码处理。

    /**
     * 统一编码
     */
    @WebFilter(
            filterName = "EncodingFilter",
            urlPatterns = "/*"
    )
    public class EncodingFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException { }
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request=(HttpServletRequest) req;
            HttpServletResponse response=(HttpServletResponse) resp;
            chain.doFilter(new MyRequest(request), response);
        }
    
        @Override
        public void destroy() { }
    
    }
    
    作者:kindleheart
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    POJ 2723 Get Luffy Out(2-SAT)
    ZOJ 3613 Wormhole Transport
    HDU 4085 Peach Blossom Spring
    NBUT 1221 Intermediary
    NBUT 1223 Friends number
    NBUT 1220 SPY
    NBUT 1218 You are my brother
    PAT 1131. Subway Map (30)
    ZSTU OJ 4273 玩具
    ZSTU OJ 4272 最佳淘汰算法
  • 原文地址:https://www.cnblogs.com/kindleheart/p/9780703.html
Copyright © 2020-2023  润新知