Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 798|回复: 0

通过HttpServletRequestWrapper消除乱码

[复制链接]

该用户从未签到

发表于 2011-9-19 16:06:04 | 显示全部楼层 |阅读模式
应用一:解决tomcat下中文乱码问题

在tomcat下,我们通常这样来解决中文乱码问题:



过滤器代码:

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中过滤器配置:

<!--将采用的字符编码配置成应用初始化参数而不是过滤器私有的初始化参数是因为在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字段中的参数不起作用,我们通常通过下面的代码来完成编码转换:



String paramValue = request.getParameter("paramName");
paramValue = new String(paramValue.trim().getBytes("ISO-8859-1"), charset);


但是每次进行这样的转换实在是很麻烦,有没有统一的解决方案呢?



解决方案1: 在tomcat_home\conf\server.xml 中的Connector元素中设置URIEncoding属性为合适的字符编码



    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               URIEncoding="UTF-8"
     />


这样做的缺点是,同一个tomcat下的其他应用也将受到影响。而其每次部署时都需要类修改配置也很麻烦。



解决方案2:自定义请求包装器包装请求,将字符编码转换的工作添加到getParameter()方法中



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方法 代码如下:

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方法来获取参数,就已经完成了字符编码的转换过程,我们就不需要在每次获取参数时来进行字符编码转换了。

这是我讲课时的一个例子,不对之处,敬请指教,以免误人子弟啊。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-10 23:14 , Processed in 0.321937 second(s), 39 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表