解决get方法传递URL参数中文乱码问题
2016-05-30 13:33
801 查看
应用一:解决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¶me2=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方法来获取参数,就已经完成了字符编码的转换过程,我们就不需要在每次获取参数时来进行字符编码转换了。
spring转码过滤器,在web.xml文件中配置,
注意:filter是根据filter-mapping节点的顺序来执行的,为了避免其他filter在这个filter之前执行,所以请将这个filter-mapping放到最前面
在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¶me2=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方法来获取参数,就已经完成了字符编码的转换过程,我们就不需要在每次获取参数时来进行字符编码转换了。
spring转码过滤器,在web.xml文件中配置,
注意:filter是根据filter-mapping节点的顺序来执行的,为了避免其他filter在这个filter之前执行,所以请将这个filter-mapping放到最前面
相关文章推荐
- java-模拟tomcat服务器
- i-jetty环境搭配与编译
- 实现单Tomcat多Server配置
- 生产环境下的Tomcat配置
- Linux部署Tomcat服务器
- jenkins------结合maven将svn项目自动部署到tomcat下
- 如何搞定tomcat这只喵~
- tomcat在opensuse下开机自启失败的原因分析及解决方法
- jsp项目中更改tomcat的默认index.jsp访问路径的方法
- Tomcat 多端口 多应用
- tomcat 5.0 + apache 2.0 完全安装步骤详解
- Tomcat安全设置 win2003 下tomcat权限限制
- Jsp和PHP共用80端口整合Apache和Tomcat(访问时无需加端口号)
- Tomcat服务器 安全设置第1/3页
- tomcat 6.0.20在一个机器上安装多个服务的方法
- Tomcat 5.5 数据库连接池配置
- Tomcat内存溢出分析及解决方法
- apache tomcat 一个网站多域名的实现方法
- Tomcat无法加载css和js等静态资源文件的解决思路