filter高级应用

Filter高级应用:
 Decorator模式 
 1)包装类需要和被包装对象 实现相同接口,或者继承相同父类
 2)包装类需要持有 被包装对象的引用 
  在包装类中定义成员变量,通过包装类构造方法,传入被包装对象 
 3)在包装类中,可以控制原来那些方法需要加强
 不需要加强 ,调用被包装对象的方法
 需要加强,编写增强代码逻辑 
 ServletRequestWrapper 和 HttpServletRequestWrapper 
 提供对request对象进行包装的方法,但是默认情况下每个方法都是调用原来request对象的方法,
 也就是说包装类并没有对request进行增强 
 如果要增强就可以在这两个包装类基础上,继承HttpServletRequestWrapper 和 HttpServletRequestWrapper 覆盖需要增强的方法即可
 6.完全解决get和post乱码的过滤器 
 在Filter中,对request对象进行包装,增强获得参数的方法 
 getParameter 
 getParameterValues
 getParameterMap
 参考代码:

 1 public class GenericEncodingFilter implements Filter {
 2     @Override
 3     public void destroy() {
 4     }
 5     @Override
 6     public void doFilter(ServletRequest request, ServletResponse response,
 7             FilterChain chain) throws IOException, ServletException {
 8         // 转型为与协议相关对象
 9         HttpServletRequest httpServletRequest = (HttpServletRequest) request;
10         // 对request包装增强
11         HttpServletRequest myrequest = new MyRequest(httpServletRequest);
12         chain.doFilter(myrequest, response);
13     }
14     @Override
15     public void init(FilterConfig filterConfig) throws ServletException {
16     }
17 }
 1 // 自定义request对象
 2 class MyRequest extends HttpServletRequestWrapper {
 3 
 4     private HttpServletRequest request;
 5 
 6     private boolean hasEncode;
 7 
 8     public MyRequest(HttpServletRequest request) {
 9         super(request);// super必须写
10         this.request = request;
11     }
12     // 对需要增强方法 进行覆盖
13     @Override
14     public Map getParameterMap() {
15         // 先获得请求方式
16         String method = request.getMethod();
17         if (method.equalsIgnoreCase("post")) {
18             // post请求
19             try {
20                 // 处理post乱码
21                 request.setCharacterEncoding("utf-8");
22                 return request.getParameterMap();
23             } catch (UnsupportedEncodingException e) {
24                 e.printStackTrace();
25             }
26         } else if (method.equalsIgnoreCase("get")) {
27             // get请求
28             Map<String, String[]> parameterMap = request.getParameterMap();
29             if (!hasEncode) { // 确保get手动编码逻辑只运行一次
30                 for (String parameterName : parameterMap.keySet()) {
31                     String[] values = parameterMap.get(parameterName);
32                     if (values != null) {
33                         for (int i = 0; i < values.length; i++) {
34                             try {
35                                 // 处理get乱码
36                                 values[i] = new String(values[i]
37                                         .getBytes("ISO-8859-1"), "utf-8");
38                             } catch (UnsupportedEncodingException e) {
39                                 e.printStackTrace();
40                             }
41                         }
42                     }
43                 }
44                 hasEncode = true;
45             }
46             return parameterMap;
47         }
48         return super.getParameterMap();
49     }
50     @Override
51     public String getParameter(String name) {
52         Map<String, String[]> parameterMap = getParameterMap();
53         String[] values = parameterMap.get(name);
54         if (values == null) {
55             return null;
56         }
57         return values[0]; // 取回参数的第一个值
58     }
59     @Override
60     public String[] getParameterValues(String name) {
61         Map<String, String[]> parameterMap = getParameterMap();
62         String[] values = parameterMap.get(name);
63         return values;
64     }
65 }

增强Response对象,对响应数据进行压缩
 先说一下在Tomcat服务器内,提供对响应压缩 配置实现 
 在conf/server.xml 中 
 <Connector port="80" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8443"/> 添加 compressableMimeType="text/html,text/xml,text/plain" compression="on"

 1 public class GzipFilter implements Filter {
 2     @Override
 3     public void destroy() {
 4     }
 5     @Override
 6     public void doFilter(ServletRequest request, ServletResponse response,
 7             FilterChain chain) throws IOException, ServletException {
 8         // 自定义缓冲区,重写response的getWriter和getOutputStream
 9         HttpServletResponse httpServletResponse = (HttpServletResponse) response;
10         // 字节缓存区
11         // 将数据写入内存数组中
12         final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
13         HttpServletResponse myresponse = new HttpServletResponseWrapper(
14                 httpServletResponse) {
15             private PrintWriter out;
16             @Override
17             // 重写getWriter 流获得是对 getOutputStream 编码获得
18             public PrintWriter getWriter() throws IOException {
19                 System.out.println("getWriter...");
20                 if (out == null) {
21                     // 确保PrintWriter只有一个对象,flushbuffer中输出缓冲区内容
22                     out = new PrintWriter(new OutputStreamWriter(
23                             byteArrayOutputStream, getCharacterEncoding()));
24                 }
25                 return out;
26             }
27             @Override
28             public ServletOutputStream getOutputStream() throws IOException {
29                 System.out.println("getOutputStream...");
30                 return new ServletOutputStream() {
31                     @Override
32                     // 将数据写到哪
33                     public void write(int b) throws IOException {
34                         // 将响应数据 写入自定义缓存区
35                         byteArrayOutputStream.write(b);
36                     }
37                 };
38             }
39             @Override
40             public void flushBuffer() throws IOException {
41                 getOutputStream().flush();
42                 getWriter().flush();
43             }
44         };
45         // 目标资源执行,只有目标资源执行后,才有响应数据
46         chain.doFilter(request, myresponse);
47         myresponse.flushBuffer();
48         // 目标资源已经执行过,数据已经在 byteArrayOutputStream 缓存区
49         byte[] data = byteArrayOutputStream.toByteArray(); // data是未压缩数据
50         System.out.println("未压缩数据长度:" + data.length);
51         // 读data数据进行压缩
52         byte[] gzipData = gzip(data);// gzipData是压缩后数据
53         System.out.println("压缩后数据长度:" + gzipData.length);
54         // 原来response 目的地是客户端浏览器
55         httpServletResponse.setHeader("Content-Encoding", "gzip");
56         httpServletResponse.setContentLength(gzipData.length);
57         httpServletResponse.getOutputStream().write(gzipData);
58         httpServletResponse.getOutputStream().flush();
59     }
60     // 对data数据进行gzip压缩
61     public byte[] gzip(byte[] data) {
62         // 定义字节缓存区,用gzip方式向缓存区写数据
63         ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
64         try {
65             GZIPOutputStream gzipOutputStream = new GZIPOutputStream(
66                     arrayOutputStream);
67             gzipOutputStream.write(data);// 将原数据 压缩gzip格式写入新的缓存区
68             gzipOutputStream.close();
69             arrayOutputStream.flush();
70             return arrayOutputStream.toByteArray();// 返回压缩后的内容
71         } catch (IOException e) {
72             e.printStackTrace();
73             throw new RuntimeException("压缩失败!");
74         }
75     }
76     @Override
77     public void init(FilterConfig filterConfig) throws ServletException {
78     }
79 }

天下代码一般仿写:http://blog.csdn.net/javadaddy/article/details/8142559

原文地址:https://www.cnblogs.com/huzi007/p/4572384.html