标签:
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
标签:
原文地址:http://www.cnblogs.com/huzi007/p/4572384.html