侧边栏壁纸
  • 累计撰写 793 篇文章
  • 累计创建 1 个标签
  • 累计收到 1 条评论
标签搜索

目 录CONTENT

文章目录

过滤器

Dettan
2021-04-10 / 0 评论 / 0 点赞 / 164 阅读 / 2,097 字
温馨提示:
本文最后更新于 2022-07-23,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
在动态代理技术里,由于不管用户调用代理对象的什么方法,都是调用开发人员编写的处理器的invoke方法(这相当于invoke方法拦截到了代理对象的方法调用)。并且,开发人员通过invoke方法的参数,还可以在拦截的同时,知道用户调用的是什么方法,因此利用这两个特性,就可以实现一些特殊需求,例如:拦截用户的访问请求,以检查用户是否有访问权限、动态为某个对象添加额外的功能。

在字符过滤器中使用动态代理解决中文乱码
package me.gacl.web.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 CharacterEncodingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //解决以Post方式提交的中文乱码问题
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }
}
从运行结果可以看出,上述的过滤器的确是不能解决以get方式提交中文参数的乱码问题,下面使用动态代理技术改造上述的过滤器,使之能够解决以get方式提交中文参数的乱码问题,改造后的过滤器代码如下:
package me.gacl.web.filter; 2  3 import java.io.IOException; 4 import java.lang.reflect.InvocationHandler; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Proxy; 7  8 import javax.servlet.Filter; 9 import javax.servlet.FilterChain;10 import javax.servlet.FilterConfig;11 import javax.servlet.ServletException;12 import javax.servlet.ServletRequest;13 import javax.servlet.ServletResponse;14 import javax.servlet.http.HttpServletRequest;15 import javax.servlet.http.HttpServletResponse;16 17 /**18 * @ClassName: CharacterEncodingFilter19 * @Description: 解决中文乱码的字符过滤器20 * @author: 孤傲苍狼21 * @date: 2014-9-14 下午10:38:1222 *23 */ 24 public class CharacterEncodingFilter implements Filter {25 26     @Override27     public void init(FilterConfig filterConfig) throws ServletException {28 29     }30 31     @Override32     public void doFilter(ServletRequest req, ServletResponse resp,33             FilterChain chain) throws IOException, ServletException {34         35         final HttpServletRequest request = (HttpServletRequest) req;36         HttpServletResponse response = (HttpServletResponse) resp;37         //解决以Post方式提交的中文乱码问题38         request.setCharacterEncoding("UTF-8");39         response.setCharacterEncoding("UTF-8");40         response.setContentType("text/html;charset=UTF-8");41         //获取获取HttpServletRequest对象的代理对象42         ServletRequest requestProxy = getHttpServletRequestProxy(request);43         /**44          * 传入代理对象requestProxy给doFilter方法,45          * 这样用户在使用request对象时实际上使用的是HttpServletRequest对象的代理对象requestProxy46          */47         chain.doFilter(requestProxy, response);48     }49 50     51     /**52     * @Method: getHttpServletRequestProxy53     * @Description: 获取HttpServletRequest对象的代理对象54     * @Anthor:孤傲苍狼55     *56     * @param request57     * @return HttpServletRequest对象的代理对象58     */ 59     private ServletRequest getHttpServletRequestProxy(final HttpServletRequest request){60         ServletRequest proxy  = (ServletRequest) Proxy.newProxyInstance(61                 CharacterEncodingFilter.class.getClassLoader(),62                 request.getClass().getInterfaces(),63                 new InvocationHandler(){64                     @Override65                     public Object invoke(Object proxy, Method method, Object[] args)66                             throws Throwable {67                         //如果请求方式是get并且调用的是getParameter方法68                         if (request.getMethod().equalsIgnoreCase("get") && method.getName().equals("getParameter")) {69                             //调用getParameter方法获取参数的值70                             String value = (String) method.invoke(request, args);71                             if(value==null){72                                 return null;73                             }74                             //解决以get方式提交的中文乱码问题75                             return new String(value.getBytes("iso8859-1"),"UTF-8");76                         }else {77                             //直接调用相应的方法进行处理78                             return method.invoke(request, args);79                         }80                     }81                 });82         //返回HttpServletRequest对象的代理对象83         return proxy;84     }85     86     @Override87     public void destroy() {88 89     }90 }
我们在过滤器中使用动态代理技术生成一个HttpServletRequest对象的代理对象requestProxy,然后把代理对象requestProxy进行chain.doFilter(requestProxy, response)传递给用户使用,这样用户实际上使用的就是HttpServletRequest对象的代理对象requestProxy。然而这一过程对于用户来说是透明的,用户是不知道自己使用的HttpServletRequest对象是一个代理对象requestProxy,由于代理对象requestProxy和目标对象HttpServletRequest具有相同的方法,当用户调用getParameter方法接收中文参数时,实际上调用的就是代理对象requestProxy的invoke方法,因此我们就可以在invoke方法中就判断当前的请求方式以及用户正在调用的方法,如果判断当前的请求方式是get方式并且用户正在调用的是getParameter方法,那么我们就可以手动处理get方式提交中文参数的中文乱码问题了。



在字符过滤器中使用动态代理压缩服务器响应的内容后再输出到客户端
压缩过滤器的代码如下:
1 package me.gacl.web.filter; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.IOException; 5 import java.io.OutputStreamWriter; 6 import java.io.PrintWriter; 7 import java.lang.reflect.InvocationHandler; 8 import java.lang.reflect.Method; 9 import java.lang.reflect.Proxy; 10 import java.util.zip.GZIPOutputStream; 11 12 import javax.servlet.Filter; 13 import javax.servlet.FilterChain; 14 import javax.servlet.FilterConfig; 15 import javax.servlet.ServletException; 16 import javax.servlet.ServletOutputStream; 17 import javax.servlet.ServletRequest; 18 import javax.servlet.ServletResponse; 19 import javax.servlet.http.HttpServletRequest; 20 import javax.servlet.http.HttpServletResponse; 21 22 /** 23 * @ClassName: GzipFilter 24 * @Description: 压缩过滤器,将web应用中的文本都经过压缩后再输出到浏览器 25 * @author: 孤傲苍狼 26 * @date: 2014-9-15 下午9:35:36 27 * 28 */ 29 public class GzipFilter implements Filter { 30 31 @Override 32 public void init(FilterConfig filterConfig) throws ServletException { 33 34 } 35 36 @Override 37 public void doFilter(ServletRequest req, ServletResponse resp, 38 FilterChain chain) throws IOException, ServletException { 39 40 final HttpServletRequest request = (HttpServletRequest) req; 41 final HttpServletResponse response = (HttpServletResponse) resp; 42 final ByteArrayOutputStream bout = new ByteArrayOutputStream(); 43 final PrintWriter pw = new PrintWriter(new OutputStreamWriter(bout,"UTF-8")); 44 45 chain.doFilter(request, getHttpServletResponseProxy(response, bout, pw)); 46 pw.close(); 47 //拿到目标资源的输出 48 byte result[] = bout.toByteArray(); 49 System.out.println("原始大小:" + result.length); 50 51 ByteArrayOutputStream bout2 = new ByteArrayOutputStream(); 52 GZIPOutputStream gout = new GZIPOutputStream(bout2); 53 gout.write(result); 54 gout.close(); 55 56 //拿到目标资源输出的压缩数据 57 byte gzip[] = bout2.toByteArray(); 58 System.out.println("压缩大小:" + gzip.length); 59 60 response.setHeader("content-encoding", "gzip"); 61 response.setContentLength(gzip.length); 62 response.getOutputStream().write(gzip); 63 } 64 65 /** 66 * @Method: getHttpServletResponseProxy 67 * @Description: 获取HttpServletResponse对象的代理对象 68 * @Anthor:孤傲苍狼 69 * 70 * @param response 71 * @param bout 72 * @param pw 73 * @return HttpServletResponse对象的代理对象 74 */ 75 private ServletResponse getHttpServletResponseProxy( 76 final HttpServletResponse response, 77 final ByteArrayOutputStream bout, 78 final PrintWriter pw) { 79 80 return (ServletResponse) Proxy.newProxyInstance(GzipFilter.class.getClassLoader(), 81 response.getClass().getInterfaces(), 82 new InvocationHandler(){ 83 @Override 84 public Object invoke(Object proxy, Method method, Object[] args) 85 throws Throwable { 86 if(method.getName().equals("getWriter")){ 87 return pw; 88 }else if(method.getName().equals("getOutputStream")){ 89 return new MyServletOutputStream(bout); 90 }else{ 91 return method.invoke(response, args); 92 } 93 } 94 }); 95 } 96 97 @Override 98 public void destroy() { 99 100 }101 102 class MyServletOutputStream extends ServletOutputStream{103 104 private ByteArrayOutputStream bout = null;105 public MyServletOutputStream(ByteArrayOutputStream bout){106 this.bout = bout;107 }108 @Override109 public void write(int b) throws IOException {110 bout.write(b);111 }112 113 }114 }
在web.xml中注册上述的GzipFilter
1 <filter> 2 <description>配置压缩过滤器</description> 3 <filter-name>GzipFilter</filter-name> 4 <filter-class>me.gacl.web.filter.GzipFilter</filter-class> 5 </filter> 6 7 <!--jsp文件的输出的内容都经过压缩过滤器压缩后才输出 --> 8 <filter-mapping> 9 <filter-name>GzipFilter</filter-name>10 <url-pattern>*.jsp</url-pattern>11 <!-- 配置过滤器的拦截方式-->12 <!-- 对于在Servlet中通过13 request.getRequestDispatcher("jsp页面路径").forward(request, response) 14 方式访问的Jsp页面的要进行拦截 -->15 <dispatcher>FORWARD</dispatcher>16 <!--对于直接以URL方式访问的jsp页面进行拦截,过滤器的拦截方式默认就是REQUEST-->17 <dispatcher>REQUEST</dispatcher>18 </filter-mapping>19 <!--js文件的输出的内容都经过压缩过滤器压缩后才输出 -->20 <filter-mapping>21 <filter-name>GzipFilter</filter-name>22 <url-pattern>*.js</url-pattern>23 </filter-mapping>24 <!--css文件的输出的内容都经过压缩过滤器压缩后才输出 -->25 <filter-mapping>26 <filter-name>GzipFilter</filter-name>27 <url-pattern>*.css</url-pattern>28 </filter-mapping>29 <!--html文件的输出的内容都经过压缩过滤器压缩后才输出 -->30 <filter-mapping>31 <filter-name>GzipFilter</filter-name>32 <url-pattern>*.html</url-pattern>33 </filter-mapping>
GzipFilter过滤器会将*.jsp,*.js,*.css,*.html这些文件里面的文本内容都经过压缩后再输出到客户端显示。
0

评论区