• 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
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Outlook 2003 最小化到系统托盘方法 [转]
    Sql Server 得到当月第一天
    禁止用户对系统数据库表的SELECT权限
    解决IE二级链接无法打开故障
    服务器安全设置全攻略
    使用TSQL脚本在SQL Server创建角色,并给角色赋予相应权限
    Redis内部阻塞式操作有哪些?
    UML和OO
    PetShop 4 详解(转载)
    Blog开通了
  • 原文地址:https://www.cnblogs.com/kindleheart/p/9780703.html
Copyright © 2020-2023  润新知