Sevlet 中 Filter 的使用

作者: uniapp | 来源:发表于2018-07-01 15:25 被阅读22次

    网站开发过程中,一般都会采用前端发送网络请求,后端响应的模式,也即是 C/S 模式。通过 Filter 能够在 C/S 中建立一道闸门,拦截前端发送的请求。拦截后可以对请求进行预处理,然后在交个服务端进行处理。 Filter 在很多歌场景下都很有用。

    Filter 生命周期

    建立自己的 FilterMyFilter

    public class MyFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.print("****** init ******");
        }
    
        //每次过滤都会执行的方法
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.print("****** doFilter2 ******");
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
            System.out.print("****** destroy ******");
        }
    }
    

    能够看到 MyFilter 中需要实现的 3 个方法 init、doFilter 和 destroy。 init 方法在 web 网站初始化的时候调用;doFilter在被过滤的对象执行时调用;destroy 在 MyFilter 销毁时调用。

    Filter 在 web 网站的应用
    1. 通过 Filter 统一全站响应的数据编码格式
      web.xml文件中,将 MyFilter 设置为拦截全站所有的网络请求:
    <filter>
        <filter-name>Filter1</filter-name>
        <filter-class>filter.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Filter1</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    MyFilterdoFilter 方法中设置数据编码格式:

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse)servletResponse;
        servletResponse.setContentType("text/html;charset=" + encoding);
        filterChain.doFilter(servletRequest, servletResponse);      
    }
    
    1. 控制浏览器缓存
      在 Filter 中针对图片设置一定时间的缓存时间,避免反复加载图片资源消耗带宽。
      web.xml 中设置 MyFilter 拦截图片资源的网络请求:
    <filter>
        <filter-name>Filter1</filter-name>
        <filter-class>filter.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Filter1</filter-name>
        <url-pattern>*.png</url-pattern>
        <url-pattern>*.jpg</url-pattern>
        <url-pattern>*.gif</url-pattern>
        <url-pattern>*.bmp</url-pattern>
    </filter-mapping>
    

    MyFilterdoFilter 方法中设置数据编码格式:

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse)servletResponse;
        HttpServletRequest req = (HttpServletRequest)servletRequest;
        //不缓存
        /*res.setHeader("cache-control", "no-cache");
        res.setHeader("pragma", "no-cache");
        res.setDateHeader("expires", 0);*/
        //缓存1小时
        res.setDateHeader("expires", System.currentTimeMillis() + 1000l*60*60);
        filterChain.doFilter(servletRequest, servletResponse);      
    }
    
    1. 解决全站乱码问题
      get/post 请求中,参数默认采用ISO8859-1编码格式,会造成中文无法正常显示的错误。需要将请求参数改为utf-8格式,才能正常显示中文字符。
      使用 MyFilter 拦截所有网络请求,对 Request 采用包装类 MyHttpServletRequestWrapper 拦截调用的方法,重写 getParameterMap 方法。当在 request 中调用 getParameter 方法时,就会调用包装类中的方法,对中文进行自动转化。
    public class MyFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest)servletRequest;
            HttpServletResponse res = (HttpServletResponse)servletResponse;
            MyHttpServletRequestWrapper myRequest = new MyHttpServletRequestWrapper(req);
            filterChain.doFilter(myRequest,res);
    
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
    class MyHttpServletRequestWrapper extends HttpServletRequestWrapper{
    
        private HttpServletRequest request;
        public MyHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);
            this.request = request;
        }
    
        @Override
        public String getParameter(String name) {
            Map<String, String[]> map = getParameterMap();
            String[] values = map.get(name);
            if (values != null){
                return values[0];
            }else {
                return null;
            }
        }
        //Map 方法是基础方法
        private boolean hasEncoding = false;//防止反复解码;
        @Override
        public Map<String, String[]> getParameterMap() {
            String method = request.getMethod();
            if ("post".equalsIgnoreCase("method")){
                try{
                    request.setCharacterEncoding("utf-8");
                }catch (UnsupportedEncodingException e){
                    e.printStackTrace();
                }
            }else {
                Map<String, String[]> map = request.getParameterMap();
                Set<String> keys = map.keySet();
    
                if (!hasEncoding){
                    hasEncoding = true;
                    for (String key: keys){
                        String[] values = map.get(key);
                        for(int i = 0; i < values.length; i++){
                            try {
                                values[i] = new String(values[i].getBytes("ISO8859-1"),"UTF-8");
    
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
    
                        }
                    }
                }
    
            }
    
            return super.getParameterMap();
    
        }
    
        @Override
        public String[] getParameterValues(String name) {
            Map<String, String[]> map = getParameterMap();
            String[] values = map.get(name);
            return values;
        }
    }
    
    总结

    Filter 相当于在前端的请求和后台服务间设立的一道大门,通过该大门可以实现请求的统一处理、个别请求和定制化处理和请求的放行和拒绝等功能。灵活使用 Filter 能够减少重复代码,加快网站开发效率。

    关注和喜欢都是对我的鼓励和支持~

    相关文章

      网友评论

        本文标题:Sevlet 中 Filter 的使用

        本文链接:https://www.haomeiwen.com/subject/eswtuftx.html