采用Filter的方法解决HttpServletRequest.getParameter乱码的问题
2013-07-08 17:08
633 查看
其实就是利用这么一个原理:
这个filter解决了什么问题呢?其实就是解决了使用request.getParameter时的乱码问题,比如说,你有一个a.html或者a.jsp发送request给servlet_b,servlet_b利用request.getParameter把参数提取出来,然后送到c.jsp去显示,如果你的a.html/jsp使用的编码是GB2312或者UTF-8之类的,那么在传输的过程中就可能出现乱码(具体我就不描述了,你拿这个代码去试试就知道乱码到底出现在哪里)
在web.xml中关于这个filter的一个参数是enable,如果你想关闭这个filter,那么令enable为false即可
完整的代码如下,先给出测试代码(见/article/6726035.html):
input_attribute.html
AttributeSetterServlet.java
req.getParameter读取attribute,然后req.setAttribute(attribute),接着跳转到display_attribute.jsp
display_attribute.jsp
request.getAttribute("attribute")提取attribute
------------------------------Filter代码-------------------------------
I18nServletFilter:
注意,由于编码的filter是属于最基本的的filter,所以在web.xml中一定要把编码的filter放在靠前的位置,至少是要放在encoding-sensitive的filter和servlet之前
此filter从web.xml中读取参数charset,charset就是你希望使用的编码参数,比如说GBK、UTF-8之类的
这个filter使用了一个自定义的类叫做I18nHttpServletRequestWrapper,继承自HttpServletRequestWrapper,HttpServletRequestWrapper提供了实现HttpServletRequest的基本框架,client可以继续extends(参考design pattern:adapter),所以I18nHttpServletRequestWrapper重写了的getParameter()以及getParameterValues()方法,添加了encoding的代码,确保了getParameter()和getParameterValues()返回的内容都是由charset参数指定的编码。并且,这个filter一但被调用,那么chain.doFilter()就会把这里的wrapper给传递下去,从而确保在filter-chain后面的filter或者其他的servlet的编码问题都得到解决。
HttpServletRequestWrapper
上面已经解释过了,这个是利用decorator pattern对HttpServletRequest进行了一次封装,对getParameter()以及getParameterValues()方法增加编码转换的功能
web.xml
总结:
这个什么I18nServletFilter是我先前在翻阅资料的时候找到的,现搬过来吧,又解决不了编码的问题
自己捣鼓了半天吧,好歹算是能用了,但是总的感觉就是:Verbose + Error-prone.
推荐使用/article/6726035.html给出的方法
byte[] bytes = str.getBytes("iso-8859-1"); String result = new String(bytes, charset); // 将str转化为你指定的charset encoding
这个filter解决了什么问题呢?其实就是解决了使用request.getParameter时的乱码问题,比如说,你有一个a.html或者a.jsp发送request给servlet_b,servlet_b利用request.getParameter把参数提取出来,然后送到c.jsp去显示,如果你的a.html/jsp使用的编码是GB2312或者UTF-8之类的,那么在传输的过程中就可能出现乱码(具体我就不描述了,你拿这个代码去试试就知道乱码到底出现在哪里)
在web.xml中关于这个filter的一个参数是enable,如果你想关闭这个filter,那么令enable为false即可
完整的代码如下,先给出测试代码(见/article/6726035.html):
input_attribute.html
AttributeSetterServlet.java
req.getParameter读取attribute,然后req.setAttribute(attribute),接着跳转到display_attribute.jsp
display_attribute.jsp
request.getAttribute("attribute")提取attribute
------------------------------Filter代码-------------------------------
I18nServletFilter:
注意,由于编码的filter是属于最基本的的filter,所以在web.xml中一定要把编码的filter放在靠前的位置,至少是要放在encoding-sensitive的filter和servlet之前
此filter从web.xml中读取参数charset,charset就是你希望使用的编码参数,比如说GBK、UTF-8之类的
这个filter使用了一个自定义的类叫做I18nHttpServletRequestWrapper,继承自HttpServletRequestWrapper,HttpServletRequestWrapper提供了实现HttpServletRequest的基本框架,client可以继续extends(参考design pattern:adapter),所以I18nHttpServletRequestWrapper重写了的getParameter()以及getParameterValues()方法,添加了encoding的代码,确保了getParameter()和getParameterValues()返回的内容都是由charset参数指定的编码。并且,这个filter一但被调用,那么chain.doFilter()就会把这里的wrapper给传递下去,从而确保在filter-chain后面的filter或者其他的servlet的编码问题都得到解决。
/** * If this filter is enabled, it will wrap the default * HttpServletRequest with I18nHttpServletRequestWrapper and * pass it to filters/servlets following this filter in the chain, * the purpose is to add charset-conversion functionality to the * HttpServletRequest, so that when you invoke getParameter() * or getParameterValues(), the returned string is encoded in the * specified charset. The charset name is specified by the init-param * of this filter. * */ public class I18nServletFilter implements Filter { private FilterConfig filterConfig; private String charsetName = "UTF-8"; private boolean enable = false; //Handle the passed-in FilterConfig public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; String enableString = filterConfig.getInitParameter("enable"); if (enableString != null && enableString.equalsIgnoreCase("true")) { this.enable = true; } String charset = filterConfig.getInitParameter("charset"); if (charset != null && charset.trim().length() != 0) { this.charsetName = charset; } } //Process the request/response pair public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { if (this.enable) { try { if (this.charsetName != null) { // System.out.println(this + ", " + this.charsetName); // @Debug I18nHttpServletRequestWrapper requestWrapper = new I18nHttpServletRequestWrapper( (HttpServletRequest) request, this.charsetName); // 注意:传递下去的是requestWrapper而不是request filterChain.doFilter(requestWrapper, response); } else { filterChain.doFilter(request, response); } } catch(ServletException sx) { filterConfig.getServletContext().log(sx.getMessage()); } catch(IOException iox) { filterConfig.getServletContext().log(iox.getMessage()); } } else { filterChain.doFilter(request, response); } } // Clean up resources public void destroy() { filterConfig = null; charsetName = null; } }
HttpServletRequestWrapper
上面已经解释过了,这个是利用decorator pattern对HttpServletRequest进行了一次封装,对getParameter()以及getParameterValues()方法增加编码转换的功能
/** * This class wraps the default HttpServletRequest to provide * a charset-conversion functionality, so that getParameter() * and getParameterValues() can return parameter-strings encoded * in your specified charset. * * The charset is specified by the constructor * of this class. * */ public class I18nHttpServletRequestWrapper extends HttpServletRequestWrapper { private Map<String, String[]> paramMap = new HashMap<String, String[]>(); private String charsetName = "iso-8859-1"; /** * 每次I18nServletFilter.doFilter()被调用,就会新建一个I18nHttpServletRequestWrapper. * 那么I18nHttpServletRequestWrapper就会提取出HttpServletRequest中的所有parameters并 * 存放到paramMap中. * * 由于服务器跳转是request范围的,所以服务器跳转始终是一个request,只会new一个I18nHttpServletRequestWrapper * */ public I18nHttpServletRequestWrapper(HttpServletRequest request, String charsetName) { super(request); // System.out.println("constructing " + this); // @Debug this.charsetName = charsetName; initParameterMap(request); } private void initParameterMap(HttpServletRequest request) { if (request == null) { return; } Map<String,String[]> map = request.getParameterMap(); Set<String> names = map.keySet(); String[] values; for (Iterator<String> i = names.iterator(); i.hasNext(); ) { String name = i.next(); values = map.get(name); for (int j = 0; j < values.length; j++) { values[j] = convertCharset(values[j]); } this.paramMap.put(name, values); } } public String getParameter(String name) { String[] values = this.getParameterValues(name); if (values != null && values.length > 0) { return values[0]; } else { return null; } } public String[] getParameterValues(String name) { return this.paramMap.get(name); } private boolean isInParamValues(String s) { for (String[] values : paramMap.values()) { for (String value : values) { if (s.equals(value)) { return true; } } } return false; } @Override public void setAttribute(String name, Object o) { /* * 防止已经被编码过的String被重新编码、 * 比如说,一个String x本来是iso-8859-1,通过convertCharset转码成为了utf-8 * 然后,你又调用convertCharset(x),那么convertCharset就会首先把x解码成 * iso-8859-1的byte(导致乱码,因为此时x已经是utf-8编码了),然后再用utf-8编码(还是乱码) * * 那么已经被编码过的String来源有哪些? * 1、通过request.setAttribute已经添加的string attribute value * 2、已经在paramMap中的value * */ if (o instanceof String && !isInParamValues((String)o) && !o.equals(getAttribute(name))) { // System.out.println("setAttr:check " + paramMap + "\n" + getAttribute(name)); // @Debug o = convertCharset((String)o); } super.setAttribute(name, o); } private String convertCharset(String str) { if (str == null) { return null; } try { // System.out.println("before convert: " + str); // @Debug str = new String(str.getBytes("iso-8859-1"), this.charsetName); // System.out.println("\tafter convert: " + str); // @Debug return str; } catch (UnsupportedEncodingException ex) { Logger.getLogger(this.getClass().toString()).log(Level.SEVERE, ex + ", charset = " + this.charsetName); } return null; } }
web.xml
<!-- i18nservletfilter --> <filter> <filter-name>i18nservletfilter</filter-name> <filter-class>org.foo.filterdemo.I18nServletFilter</filter-class> <init-param> <param-name>enable</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>charset</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>i18nservletfilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
总结:
这个什么I18nServletFilter是我先前在翻阅资料的时候找到的,现搬过来吧,又解决不了编码的问题
自己捣鼓了半天吧,好歹算是能用了,但是总的感觉就是:Verbose + Error-prone.
推荐使用/article/6726035.html给出的方法
相关文章推荐
- 多次读取HttpServletRequest的inputstream方法 问题解决
- HttpRequest Post中文转utf-8乱码问题解决方法
- springMvc 完美解决 multipart/form-data 方式提交请求 在 Filter 中 ServletRequest.getParameter方法 获取不到参数的问题
- 20160324servlet学习笔记HttpServletRequest对象中文乱码解决方法
- 使用filter解决request.getParameter的中文乱码问题
- 利用HttpServletRequestWrapper和filter改变request的getParameter方法
- HttpServletRequest解决中文乱码的问题
- springMvc 完美解决 multipart/form-data 方式提交请求 在 Filter 中 ServletRequest.getParameter方法 获取不到参数的问题
- XMLHttpRequest 乱码问题 在firefox IE的不同解决方法
- 【javaweb:Proxy&Filter】采用动态代理和过滤器解决request的全局乱码问题
- HttpServletRequest/HttpServletResponse乱码问题解决
- XMLHttpRequest乱码问题在Firefox与IE下的不同解决方法
- 采用Filter的方法解决Servlet的编码问题
- springMvc 完美解决 multipart/form-data 方式提交请求 在 Filter 中 ServletRequest.getParameter方法 获取不到参数的问题
- 关于httpclient3 postMethod乱码问题解决方法
- 简易解析ajax,javascript-XMLHttpRequest,解决乱码问题
- 如何解决找不到方法HttpServletRequest.getServletContext() ---- NoSuchMethodError
- 解决XMLHttpRequest中文乱码问题
- HttpServletRequest请求乱码问题解决方案