参考文献:Servlet容器Filter的使用(Filter解决乱码问题实例)、Java Servlet Filter、提交表单时的中文乱码问题、jsp乱码问题的解决
原因:
Tomcat下面总是会把GET/POST过来的reqest.parameters以ISO8859-1来解码,但中文系统下的浏览器的缺省方式是以UTF-8提交发送请求的,而UTF-8、GB2312和iso8859-1的编码方式不一样,故导致取到的表单数据为不能识别的乱码。P.S. jsp页面的开始明确给出的页面的编码格式 :
其中,GB18030代表的是汉字的编码的<%@ page language="java" conntentType="text/html;charset=GB18030" pageEncoding="GB18030"%>
charset是指服务器发送给客户端时的内容编码.
pageEncoding是指JSP文件本身的编码.如果改为'UTF-8'的话,那JSP源文件就不能写汉字了.所以我们在最初设置的JSP本身的编码和服务器发送给客户端的编码都是 GB18030,即中文编码.
注意,客户端发给服务器的内容不显式指定编码方式的话仍为ISO8859-1P.P.S. 元信息
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
表明这个网页的编码是utf-8,需要注意的是这个是网页内容的编码,而不是文件本身的。
解决方法:
- post表单
- 接受参数时进行编码转换
String str = new String(request.getParameter("something").getBytes("ISO-8859-1"),"utf-8");
这样的话,每一个参数都必须这样进行转码。很麻烦。但确实可以拿到汉字。
- 在请求页面上开始处,执行请求的编码代码
request.setCharacterEncoding("UTF-8");
把提交内容的字符集设为UTF-8。
这样的话,接受此参数的页面就不必在转码了。直接使用String str = request.getParameter("something");即可得到汉字参数。但每页都需要执行这句话。
这个方法也就对post提交的有效果,对于get提交和上传文件时的enctype="multipart/form-data"是无效的。稍后下面单独对这个两个的乱码情况再进行说明。
- 为了避免每页都要写request.setCharacterEncoding("UTF-8"), 可以实现Filter接口, 将逻辑处理放入doFilter()方法中
见附录.
- get表单
Tomcat会以get的缺省编码方式iso8859-1对汉字进行编码,编码后追加到url,导致接受页面得到的参数为乱码.
- 使用上例中的第一种方式,对接受到的字符进行解码,再转码。
- Get走的是url提交,而在进入url之前已经进行了iso8859-1的编码处理。要想影响这个编码则需要在 server.xml的Connector节点增加
useBodyEncodingForURI="true"
属性配置,即可控制tomcat对get方式的汉字编码方式,上面这个属性控制get提交也是用request.setCharacterEncoding("UTF-8")所设置的编码格式进行编码。所以自动编码为utf-8,接受页面正常接受就可以了。
P.S. 但我认为真正的编码过程是,tomcat又要根据<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" useBodyEncodingForURI="true" disableUploadTimeout="true" URIEncoding="UTF-8"/>
里面所设置的URIEncoding=”UTF-8”再进行一次编码,但是由于已经编码为utf-8,再编码也不会有变化了。如果是从url获取编码,接受页面则是根据URIEncoding=”UTF-8”来进行解码的。
- 关于上传文件时的乱码解决级其它乱码问题,参考jsp乱码问题的解决
附录:
package com.bjpowernode.drp.util.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* 采用Filter统一处理字符集.
* @author Summer
*
*/
public class CharsetEncodingFilter implements Filter {
//定义成员变量.
private String encoding;
//销毁.
@Override
public void destroy() {
// TODO Auto-generated method stub
}
/**
* 过滤器真正执行的处理功能.
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//System.out.println("CharacterEncodingFilter--begin");
//设置字符集.
request.setCharacterEncoding(encoding);
//拿到链条继续向下调用.
chain.doFilter(request, response);
//返回了.
//System.out.println("CharacterEncodingFilter--end");
}
/**
* 过滤器初始化时候调用.
* 我们在初始化的时候调用
* 从web.xml中读取配置文件 读取encoding数据.
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.encoding = filterConfig.getInitParameter("encoding");
}
}
web.xml
<filter>
<filter-name>CharsetEncodingFilter</filter-name>
<filter-class>com.bjpowernode.drp.util.filter.CharsetEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
<!-- 对哪些起作用,对jsp还是servlet -->
<filter-mapping>
<filter-name>CharsetEncodingFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
<servlet-name>*</servlet-name> <!-- 在这里需要注意的是,在给servlet注册filter环,container首先处理的是url-patterns, --> <!-- 然后才处理servlet-names,所以如果要对filter的执行顺序有要求,那么在此需要注意。 -->
</filter-mapping>