EzrealYi
前述:
在写这篇笔记之前,对笔记中的设计模式进行介绍:
本篇笔记中将要使用到的设计模式是:装饰(包装)设计模式
(1)装饰(包装)设计模式口诀:
①定义一个类,实现被装饰对象的接口
②定义一个成员变量,记住被装饰对象的引用
③定义构造方法,传入被装饰对象的实例
④改写要修改的方法
⑤不需要改写的方法,调用被装饰对象的原来的方法
(2)什么时候使用装饰设计模式
当我们需要对一个类进行增强的时候,增强后的类不再当前类的范畴
例如:现在有一个 Animal类 Cat和Dog都属于动物类型,因此可以直接继承
现在新来一个“电子狗 ”,不属于动物的范围,但是有需要用其中的方法,这时候我们选择使用装饰(包装)设计模式
一:需求:统一解决请求参数中文乱码
二、优化思路:
使用一个过滤器,在请求到达servlet之前,先对request对象设置编码
四、结果反馈
要求所有的请求都要进行设置编码,因此所有的request都要拦截,进行增强,那么web.xml应该加上:
1 <!-- 设置编码 --> 2 <context-param> 3 <param-name>charset</param-name> 4 <param-value>UTF-8</param-value> 5 </context-param> 6 7 <!--配置乱码过滤器--> 8 <filter> 9 <filter-name>EncodingFilter</filter-name> 10 <!--包名及文件名--> 11 <filter-class>com.zy.web.Filter.EncodingFilter</filter-class> 12 <init-param> 13 <param-name>charset</param-name> 14 <param-value>UTF-8</param-value> 15 </init-param> 16 </filter> 17 <filter-mapping> 18 <filter-name>EncodingFilter</filter-name> 19 <url-pattern>/*</url-pattern> 20 </filter-mapping>
三:代码实现:
1、过滤器代码
1 package com.zy.web.Filter; 2 3 import com.zy.web.Encoding.EncodingRequest; 4 5 import javax.servlet.*; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.IOException; 9 10 public class EncodingFilter implements Filter { 11 @Override 12 public void init(FilterConfig filterConfig) throws ServletException { 13 } 14 15 @Override 16 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 17 // 将请求和响应强制转换成Http形式 18 HttpServletRequest request = (HttpServletRequest) req; 19 HttpServletResponse response = (HttpServletResponse) res; 20 21 String charset = request.getServletContext().getInitParameter("charset"); 22 if (charset == null || charset.isEmpty()) { 23 charset = "UTF-8"; 24 } 25 26 // 处理响应乱码 27 response.setContentType("text/html;charset=" + charset); 28 response.setCharacterEncoding(charset); 29 EncodingRequest encodingRequest = new EncodingRequest(request, charset); 30 chain.doFilter(encodingRequest, res); 31 } 32 33 @Override 34 public void destroy() { 35 36 } 37 }
2、自定义增强类(EncodingRequest)
1 package com.zy.web.Encoding; 2 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletRequestWrapper; 5 import java.io.UnsupportedEncodingException; 6 import java.util.Map; 7 import java.util.Set; 8 9 public class EncodingRequest extends HttpServletRequestWrapper { 10 private String charset; 11 // 定义了一个成员变量,用来保存构造函数传入的requset对象 12 private HttpServletRequest request = null; 13 // 定义一个标记,用来标注:当前requset中,请求参数,是否已经编码过了 14 private boolean flag = false; 15 16 /** 17 * Constructs a request object wrapping the given request. 18 * 19 * @param request the {@link HttpServletRequest} to be wrapped. 20 * @param charset 21 * @throws IllegalArgumentException if the request is null 22 */ 23 public EncodingRequest(HttpServletRequest request, String charset) { 24 super(request); 25 this.charset = charset; 26 this.request = request; 27 } 28 29 @Override 30 public Map<String, String[]> getParameterMap() { 31 // 获得请求方式request.getMethod()方法 32 String method = this.request.getMethod(); 33 // post请求 34 if ("post".equalsIgnoreCase(method)) { 35 // 设置编码格式 36 try { 37 request.setCharacterEncoding(charset); 38 } catch (UnsupportedEncodingException e) { 39 e.printStackTrace(); 40 } 41 Map<String, String[]> map = this.request.getParameterMap(); 42 return map; 43 44 } else if ("get".equalsIgnoreCase(method)) { 45 // get请求 46 // 分析:get请求需要对每一个参数都进行转换,因此需要对map中的每个元素进行遍历 47 // 首先获得map集合 48 Map<String, String[]> map = this.request.getParameterMap(); 49 50 //第一次获取请求参数,flag==false,执行后面的额乱码处理动作 51 //第二次获取请求参数的时候,flag==true,不执行后面的处理,直接返回已经编码过的map集合 52 if (flag) { 53 return map; 54 } 55 if (map == null) { 56 return super.getParameterMap(); 57 } else { 58 if (!map.isEmpty()) { 59 // 然后获得map集合的key 60 Set<String> key = map.keySet(); 61 62 // 通过key将map中的元素取出来 63 for (String string1 : key) { 64 String[] value = map.get(string1); 65 // 接下来需要将String中的每一个都进行遍历,转换参数 66 for (int i = 0; i < value.length; i++) { 67 try { 68 String string2 = new String( 69 value[i].getBytes("iso-8859-1"), charset); 70 value[i] = string2; 71 } catch (UnsupportedEncodingException e) { 72 e.printStackTrace(); 73 } 74 } 75 } 76 flag = true; 77 } 78 return map; 79 80 } 81 } else { 82 //位置请求方式,自定义对象处理不了,使用父类的方法处理 83 return super.getParameterMap(); 84 } 85 } 86 87 @Override 88 public String[] getParameterValues(String name) { 89 //请求参数没有name,返回null 90 if (name == null || name.equals("")) { 91 return super.getParameterValues(name); 92 } else { 93 //请求没有任何param,返回"" 94 if (this.getParameterMap().isEmpty()) { 95 return new String[0]; 96 } else { 97 return this.getParameterMap().get(name); 98 } 99 } 100 } 101 102 @Override 103 public String getParameter(String name) { 104 if (name == null || name.equals("")) { 105 return super.getParameter(name); 106 } else { 107 if(this.getParameterValues(name) == null){ 108 return null; 109 } 110 if (this.getParameterValues(name).length == 0) { 111 return ""; 112 } else { 113 return this.getParameterValues(name)[0]; 114 } 115 } 116 } 117 }
对于request.getParameter(Name)返回值为空时,接受对象的String为null,便于在jsp、servlet中判断处理结果。