打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
通过HttpServletRequestWrapper(装饰模式的应用)增强HttpServletRequest的功能,过滤GET请求编码
通过HttpServletRequestWrapper(装饰模式的应用)增强HttpServletRequest的功能
博客分类: java
应用服务器TomcatServletSpring浏览器
应用一:解决tomcat下中文乱码问题(先来个简单的)
在tomcat下,我们通常这样来解决中文乱码问题:
过滤器代码:
Java代码 
package filter;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import wrapper.GetHttpServletRequestWrapper;
public class ContentTypeFilter implements Filter {
private String charset = "UTF-8";
private FilterConfig config;
public void destroy() {
System.out.println(config.getFilterName()+"被销毁");
charset = null;
config = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//设置请求响应字符编码
request.setCharacterEncoding(charset);
response.setCharacterEncoding(charset);
HttpServletRequest req = (HttpServletRequest)request;
System.out.println("----请求被"+config.getFilterName()+"过滤");
//执行下一个过滤器(如果有的话,否则执行目标servlet)
chain.doFilter(req, response);
System.out.println("----响应被"+config.getFilterName()+"过滤");
}
public void init(FilterConfig config) throws ServletException {
this.config = config;
String charset = config.getServletContext().getInitParameter("charset");
if( charset != null && charset.trim().length() != 0)
{
this.charset = charset;
}
}
}
web.xml中过滤器配置:
Xml代码 
<!--将采用的字符编码配置成应用初始化参数而不是过滤器私有的初始化参数是因为在JSP和其他地方也可能需要使用-->
<context-param>
<param-name>charset</param-name>
<param-value>UTF-8</param-value>
</context-param>
<filter>
<filter-name>ContentTypeFilter</filter-name>
<filter-class>filter.ContentTypeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ContentTypeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
request.setCharacterEncoding(charset); 必须写在第一次使用request.getParameter()之前,这样才能保证参数是按照已经设置的字符编码来获取。
response.setCharacterEncoding(charset);必须写在PrintWriter out = request.getWriter()之前,这样才能保证out按照已经设置的字符编码来进行字符输出。
通过过滤器,我们可以保证在Servlet或JSP执行之前就设置好了请求和响应的字符编码。
但是这样并不能完全解决中文乱码问题:
对于post请求,无论是“获取参数环节”还是“输出环节"都是没问题的;
对于get请求,"输出环节"没有问题,但是"获取参数环节"依然出现中文乱码,所以在输出时直接将乱码输出了。
原因是post请求和get请求存放参数位置是不同的:
post方式参数存放在请求数据包的消息体中。get方式参数存放在请求数据包的请求行的URI字段中,以?开始以param=value&parame2=value2的形式附加在URI字段之后。而request.setCharacterEncoding(charset); 只对消息体中的数据起作用,对于URI字段中的参数不起作用,我们通常通过下面的代码来完成编码转换:
Java代码 
String paramValue = request.getParameter("paramName");
paramValue = new String(paramValue.trim().getBytes("ISO-8859-1"), charset);
但是每次进行这样的转换实在是很麻烦,有没有统一的解决方案呢?
解决方案1: 在tomcat_home\conf\server.xml 中的Connector元素中设置URIEncoding属性为合适的字符编码
Java代码 
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"
/>
这样做的缺点是,同一个tomcat下的其他应用也将受到影响。而其每次部署时都需要类修改配置也很麻烦。
解决方案2:自定义请求包装器包装请求,将字符编码转换的工作添加到getParameter()方法中
Java代码 
package wrapper;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class GetHttpServletRequestWrapper extends HttpServletRequestWrapper {
private String charset = "UTF-8";
public GetHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
/**
* 获得被装饰对象的引用和采用的字符编码
* @param request
* @param charset
*/
public GetHttpServletRequestWrapper(HttpServletRequest request,
String charset) {
super(request);
this.charset = charset;
}
/**
* 实际上就是调用被包装的请求对象的getParameter方法获得参数,然后再进行编码转换
*/
public String getParameter(String name) {
String value = super.getParameter(name);
value = value == null ? null : convert(value);
return value;
}
public String convert(String target) {
System.out.println("编码转换之前:" + target);
try {
return new String(target.trim().getBytes("ISO-8859-1"), charset);
} catch (UnsupportedEncodingException e) {
return target;
}
}
}
修改过滤器的doFilter方法 代码如下:
Java代码 
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//设置请求响应字符编码
request.setCharacterEncoding(charset);
response.setCharacterEncoding(charset);
//新增加的代码
HttpServletRequest req = (HttpServletRequest)request;
if(req.getMethod().equalsIgnoreCase("get"))
{
req = new GetHttpServletRequestWrapper(req,charset);
}
System.out.println("----请求被"+config.getFilterName()+"过滤");
//传递给目标servlet或jsp的实际上时包装器对象的引用,而不是原始的HttpServletRequest对象
chain.doFilter(req, response);
System.out.println("----响应被"+config.getFilterName()+"过滤");
}
这样一来,在servlet中调用包装器的getParameters方法来获取参数,就已经完成了字符编码的转换过程,我们就不需要在每次获取参数时来进行字符编码转换了。
这是我讲课时的一个例子,不对之处,敬请指教,以免误人子弟啊。
demo.rar (8.6 KB)
描述: 附:源程序
下载次数: 305
分享到:
HttpServletRequestWrapper应用(二):包 ... | 引用 一个穷学生的爱情
2009-10-08 21:44
浏览 734
评论(25)
论坛回复 / 浏览 (25 / 10397)
收藏
相关推荐
评论
25 楼 Zahir 2010-04-18   引用
用动态代理来做就好了,没必要写个wrapper出来
24 楼 舞指如歌 2010-04-18   引用
写的很详细,我以前也遇到同样的问题,POST的用过滤器中setCharacterEncoding解决,但是GET请求里的参数的中文还是有乱码问题,最后是通过修改config文件解决的,这下终于有了一个比较满意的方案了,谢谢。
23 楼 whistler 2009-10-12   引用
gufenglian 写道
经常遇到乱码问题,一直在想为什么post行,get就不行了,现在思路清晰了。感谢楼主,我听说tomcat可以配置成根据页面编码来设置uri。
楼主知道的话,可以讲解一下
可以在Tomcat的配置文件的Connector标签中设置useBodyEncodingForURI属性值为true。在默认情况下,该参数为false(Tomcat4.0中该参数默认为true)
22 楼 gufenglian 2009-10-12   引用
经常遇到乱码问题,一直在想为什么post行,get就不行了,现在思路清晰了。感谢楼主,我听说tomcat可以配置成根据页面编码来设置uri。
楼主知道的话,可以讲解一下
21 楼 love1907 2009-10-12   引用
曾经de迷茫 写道
whistler 写道
zwq4166506 写道
有个缺陷,比如form有个name属性,请求的url也有个name属性,如
Html代码 
<form method="post" action="?name=处理乱码">
<input type="text" name="name"/>
<input type="submit" value="submit"/>
</form>
这样就混乱了,结果出来还是乱码。。。
确实是这样,那么用的时候必须注意这个问题了,不能在post方式提交表单的情况下,在action属性中附加中文参数了,
只能在表单中用隐藏域来代替了,我再想想能不能解决这个问题
感谢zwq4166506兄弟这么仔细帮我找bug
还是对中文处理再传递,有一种办法是使用js代码Js代码 
/url?&param=encodeURI(encodeURI('中文')); //两次编码
然后服务器Java代码 
String param= java.net.URLDecoder.decode(request.getParameter("param") , "UTF-8");
没搞懂为啥要两次,encodeURI()
20 楼 seemoon 2009-10-12   引用
讲解清晰,传业授道解惑,不算误人子弟
19 楼 skzr.org 2009-10-12   引用
zwq4166506 写道
有个缺陷,比如form有个name属性,请求的url也有个name属性,如
Html代码 
<form method="post" action="?name=处理乱码">
<input type="text" name="name"/>
<input type="submit" value="submit"/>
</form>
这样就混乱了,结果出来还是乱码。。。
我局的楼主所说的问题应该是URL支不支持中文或其他语言的问题,也就是说使用浏览器地址栏直接访问带有中文或其他任何非标准字符的资源时出现的乱码:
如果直接通过浏览器地址访问带有中文参数的url(如:http://localhost/web/xx.do?name=中文XX,或者是点击<a href='http://localhost/web/xx.do?name=中文XX'>相当于直接通过浏览器地址栏访问</a>)
这个问题的解决好像只能够通过修改tomcat的server.xml来支持服务器解析非iso8859-1的url,weblogic和webshere是默认支持url的自动编码解析的。
按照楼主的包装或者自己转码的方法,不知道在解析奇数和偶数个数的中文时结果还会不会一致(之前用tomcat5.0的时候出现奇数或偶数个中文不正常)
至于说的server。xml里面配置的uriencode只是说uri支持直接书写中文,不过如果是表单提交的话,他们会自动编码的(无论是post 还是 get方式)!server。xml里面配置的uriencode只是对a标签和直接在浏览器地址栏中书写的url起作用!
18 楼 wangdgsc 2009-10-11   引用
还有楼上说要使用Spring的过滤器的哥们儿,Spring的过滤器我好像只能处理post请求,不能干别的
17 楼 wangdgsc 2009-10-11   引用
我的字符串过滤器都是在Filter中直接处理get和post两种请求,楼主的这种处理方式我也见到别人写过,不过,楼主好像少覆盖了一个方法getParameterMap()直接获得参数集合,呵呵
16 楼 piggy 2009-10-11   引用
目前我为公司写的过滤器就是在spring过滤器的基础上再判断是否为tomcat,如果tomcat就是跟楼主这样的处理。
15 楼 曾经de迷茫 2009-10-11   引用
whistler 写道
zwq4166506 写道
有个缺陷,比如form有个name属性,请求的url也有个name属性,如
Html代码 
<form method="post" action="?name=处理乱码">
<input type="text" name="name"/>
<input type="submit" value="submit"/>
</form>
这样就混乱了,结果出来还是乱码。。。
确实是这样,那么用的时候必须注意这个问题了,不能在post方式提交表单的情况下,在action属性中附加中文参数了,
只能在表单中用隐藏域来代替了,我再想想能不能解决这个问题
感谢zwq4166506兄弟这么仔细帮我找bug
还是对中文处理再传递,有一种办法是使用js代码Js代码 
/url?&param=encodeURI(encodeURI('中文')); //两次编码
然后服务器Java代码 
String param= java.net.URLDecoder.decode(request.getParameter("param") , "UTF-8");
14 楼 whistler 2009-10-10   引用
zwq4166506 写道
有个缺陷,比如form有个name属性,请求的url也有个name属性,如
Html代码 
<form method="post" action="?name=处理乱码">
<input type="text" name="name"/>
<input type="submit" value="submit"/>
</form>
这样就混乱了,结果出来还是乱码。。。
确实是这样,那么用的时候必须注意这个问题了,不能在post方式提交表单的情况下,在action属性中附加中文参数了,
只能在表单中用隐藏域来代替了,我再想想能不能解决这个问题
感谢zwq4166506兄弟这么仔细帮我找bug
13 楼 whistler 2009-10-10   引用
alex09 写道
Java代码 
public void destroy() {
charset = null;
config = null;
System.out.println(config.getFilterName()+"被销毁");
}
直接就爆掉的代码啊
汗,哈哈,谢谢,太马虎大意了,文章中已经修改了,但是上传文件中的还没修改,麻烦下载了的兄弟们自己修改了。
再次感谢,不然不知道丢人到啥时候了
12 楼 alex09 2009-10-10   引用
Java代码 
public void destroy() {
charset = null;
config = null;
System.out.println(config.getFilterName()+"被销毁");
}
直接就爆掉的代码啊
11 楼 zwq4166506 2009-10-10   引用
有个缺陷,比如form有个name属性,请求的url也有个name属性,如
Html代码 
<form method="post" action="?name=处理乱码">
<input type="text" name="name"/>
<input type="submit" value="submit"/>
</form>
这样就混乱了,结果出来还是乱码。。。
10 楼 yangtao309 2009-10-10   引用
多谢楼主提醒,
原来楼主想说的是 处理get方式提交的乱码问题
没看太仔细 呵呵~~
对于一般的表单提交都会选择post的吧
9 楼 whistler 2009-10-10   引用
<div class="quote_title">yangtao309 写道</div>
<div class="quote_div">中文过滤器 知道怎么自己写就够了<br>要用还是直接用spring自带的比较好<br><pre name="code" class="java"> &lt;!-- 著名 Character Encoding filter --&gt;
&lt;filter&gt;
&lt;filter-name&gt;encodingFilter&lt;/filter-name&gt;
&lt;filter-class&gt;org.springframework.web.filter.CharacterEncodingFilter&lt;/filter-class&gt;
&lt;init-param&gt;
&lt;param-name&gt;encoding&lt;/param-name&gt;
&lt;param-value&gt;UTF-8&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;/filter&gt;
</pre>
</div>
<p><br><br>我发现我的文章没有突出主题,上来说过滤器的内容可能比较多了,我是主体内容如题,是说HttpServletRequestWrapper的应用的。</p>
<p>通过查看org.springframework.web.filter.CharacterEncodingFilter源代码,它也和我前面没有使用HttpServletRequestWrapper包装get方式请求处理乱码的过滤器基本一样啊,只是request.setCharacterEncoding(this.encoding); response.setCharacterEncoding(this.encoding);,在tomcat下是解决不了get请求获取参数中文乱码问题的。</p>
<p>请看org.springframework.web.filter.CharacterEncodingFilter源代码片段:</p>
<p> </p>
<pre name="code" class="java">protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (this.encoding != null &amp;&amp; (this.forceEncoding || request.getCharacterEncoding() == null)) {
request.setCharacterEncoding(this.encoding);
if (this.forceEncoding &amp;&amp; responseSetCharacterEncodingAvailable) {
response.setCharacterEncoding(this.encoding);
}
}
filterChain.doFilter(request, response);
}
</pre>
8 楼 yangtao309 2009-10-10   引用
中文过滤器 知道怎么自己写就够了
要用还是直接用spring自带的比较好
Java代码 
<!-- 著名 Character Encoding filter -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
7 楼 whaosoft 2009-10-09   引用
lz 很谦虚 讲的很全 呵呵 除非在项目中 一般在论坛系列的地方我才懒的说那么细 支持lz
6 楼 whistler 2009-10-09   引用
hbcui1984 写道
个人感觉还是直接修改tomcat配置文件方便,毕竟部署项目时,一般一个tomcat下只有一个应用
恩,这个得看项目的情况了
如果项目作为产品的话,需要为每个客户部署,每次都需要修改配置,比较麻烦
如果部署好之后,有可能会在以后进行迁移,比如一开始是租的空间(修改配置也很麻烦,得委托客服修改),后来自己买了服务器,那么很有可能会遗忘配置的事情,造成麻烦
个人认为尽可能的在应用内部将问题扼杀是一劳永逸的事情。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
JSP页面编码问题分析
JSP+ MySQL中文乱码问题post提交乱码解决方案
Tomcat关于encoding编码的默认设置以及乱码产生的原因
java web开发过程中的编码问题完全解决方案
深度揭秘乱码问题背后的原因及解决方式
JSP HTML JAVASCRIPT 中文乱码 解决方案 大全
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服