采用Filter的方法解决HttpServletRequest.getParameter乱码的问题
其实就是利用这么一个原理:
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即可
完整的代码如下,先给出测试代码(见http://www.cnblogs.com/qrlozte/p/3515171.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.
推荐使用http://www.cnblogs.com/qrlozte/p/3515171.html给出的方法
采用Filter的方法解决HttpServletRequest.getParameter乱码的问题的更多相关文章
- 采用Filter的方法解决Servlet的编码问题
这样比你自己在Servlet代码中硬编码request.setCharacterEncoding, response.setCharacterEncoding方便多了 总之,如果你添加了这个filte ...
- 解决httpServletRequest.getParameter获取不到参数
用httpServletRequest.getParameter接收post请求参数,发送端content Type必须设置为application/x-www-form-urlencoded:否则会 ...
- request.getParameter()及解决数据库中文乱码问题——实习第七天
今天老师让我们自己做一个小项目,我开始着手于实现这个小项目.途中遇到过几个小问题,在此做个小记录, 相信后期还是会借鉴的. 1,从前台传入数据给后台传入数据,并没有传入成功: 输出的为Null. 当然 ...
- 使用Filter解决登录中乱码问题
使用Filter解决登录中乱码问题 衔接:https://www.cnblogs.com/zst18980621948/p/10654088.html 1.工作目录 新增Filter类 2.Login ...
- 解决get方法提交参数中文乱码问题:
解决get方法提交参数中文乱码问题: 1找到你们的tomcat的目录 2在这个目录下面\tomcat61-32\tomcat61\conf 3找到server.xml ,用notepad打开(没有就下 ...
- 【转】解决jsp参数传递乱码的问题
解决jsp参数传递乱码的问题 计算机生于美国,英语是他的母语,而英语以外的其它语言对他来说都是外语.他跟我们一样,不管外语掌握到什么程度,也不会像母语那样使用得那么好,时常也会出一些“拼写错误”问题. ...
- Java_Web学习笔记_过滤器应用案例(解决全站字符乱码)
解决全站字符乱码(POST和GET中文编码问题) servlet: l POST:request.setCharacterEncoding(“utf-8”); l GET: String user ...
- 解决全站字符乱码(POST和GET中文编码问题)
1 说明 乱码问题: 获取请求参数中的乱码问题: POST请求:request.setCharacterEncoding(“utf-8”): GET请求:new String(request.getP ...
- 大白话讲解如何解决HttpServletRequest的请求参数只能读取一次的问题
大家在开发过程中,可能会遇到对请求参数做下处理的场景,比如读取上送的参数中看调用方上送的系统编号是否是白名单里面的(更多的会用request中获取IP地址判断).需要对请求方上送的参数进行大小写转换或 ...
随机推荐
- 获取每月第一天最后一天 java
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); //获取前月的第一天 Calendar cal_1=Ca ...
- 【OpenERP】Report 生成
以模块oecnj_trainning为例,模块路径: ~/openerp/addons/oecn_training/ ,以下简写为 path/oecn/ Report生成方法:(手写) rml + r ...
- Android中保存静态秘钥实践(转)
本文我们将讲解一个Android产品研发中可能会碰到的一个问题:如何在App中保存静态秘钥以及保证其安全性.许多的移动app需要在app端保存一些静态字符串常量,其可能是静态秘钥.第三方appId等. ...
- 引入css的几种方式
使用CSS样式的几种方式 CreateTime--2017年10月11日16:45:26 Author:Marydon a.外部样式 a1.链接式(推荐使用) <link href=&quo ...
- cpuinfo详解
cat /proc/cpuinfo processor: 23:超线程技术的虚拟逻辑核第24个 ###一般看最后一个0...23 表示24线程 vendor_id: GenuineIntel:CP ...
- <转>字符编码笔记:ASCII,Unicode和UTF-8
本文转自:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 今天中午,我突然想搞清楚Unicode和UTF-8之间 ...
- c++课程设计(日历)
今天比较无聊,就随便找了个程序设计来做,下面是源代码,以及效果图...不喜请喷!/*题目1:年历显示. 功能要求: (1) 输入一个年份,输出是在屏幕上显示该年的日历.假定输入的年份在1940-204 ...
- QRCode - 二维码识别与生成
来源:Yi'mouleng(@丶伊眸冷) 链接:http://t.cn/R40WxcM 前言 有关二维码的介绍,我这里不做过多说明, 可以直接去基维百科查看,附上链接QR code(https://e ...
- 设置当前Activity的屏幕亮度
设置当前的Activity的屏幕亮度,而不是设置系统的屏幕亮度,退出当前的Activity后恢复系统的亮度. 直接看代码好了 Java代码 WindowManager.LayoutParams lp ...
- 在 Asp.NET MVC 中使用 SignalR 实现推送功能 [转]
在 Asp.NET MVC 中使用 SignalR 实现推送功能 罗朝辉 ( http://blog.csdn.net/kesalin ) CC许可,转载请注明出处 一,简介 Signal 是微软支持 ...