参考《MyEclipse 6 java 开发中文教程》。
一、Tomcat JSP Web 开发中的乱码问题小结
1. 静态页面的乱码问题
文件的编码和浏览器要显示的编码不一致。
1) 检查文件原始的编码, 可以用记事本打开, 然后选择另存为来看;
2) 给当前页面加入一个指令来建议浏览器用指定的编码来显示文件字符内容。
<meta http-equiv="content-type" content="text/html; charset=GBK">
3) 如果系统是英文XP,没装东亚字符集支持, 也会显示乱码。
2. JSP 页面的乱码问题
1) page 指令有个 pageEncoding="GBK" 这个会指定当前页面保存的编码, 如果写成ISO8859-1 就不能保存汉字;
2) page 指令的 contentType="text/html; charset=ISO8859-1" 也会像静态页面一样让浏览器来优先选择一种编码。如果JSP 乱码的话,一般就显示成?,而且不管你给浏览器选什么样的编码,它都不能正确显示
3. 表单提交的乱码问题(Tomcat 特有)
1)POST 的乱码
a. 首先浏览器提交表单的编码是根据表单所在页面来决定的, 而不是根据提交后的JSP 页面的编码来决定的. 把所有的页面的编码都设置成一样的,例如 GBK。
b. 处理方式就是在获取参数之前设置编码:
request.setCharacterEncoding("GBK");
c. 可以用过滤器的方式来解决, Tomcat 已经带了一个现成的:
apache-tomcat-5.5.23/webapps/jsp-examples/WEB-INF/classes/filters/SetCharacterEncodingFilter.java
web.xml
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2) GET 方式的乱码
用 setCharacterEncoding() 不能解决. TOMCAT 的一个BUG, GET 方式传送的表单参数总是用的 ISO8859-1 编码. 我们要把它转成 GBK 方式。
String username = request.getParameter("username");
System.out.println(username);
// 转码, 先取得原始的二进制字节数组
byte[] data = username.getBytes("ISO8859-1");
// 根据新的字符集再构造新的字符串
username = new String(data, "GBK");
小结:
所有的页面(除了最后的 GET 的乱码问题)都用统一的编码(GBK 或者UTF-8), 就不会出现
乱码问题。
二、用过滤器来一次编码彻底解决表单参数的乱码问题
1、目前网上流行是用如下程序:
package filters;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.FilterChain;
import java.io.IOException;
public class TomcatFormFilter implements Filter {
protected FilterConfig filterConfig;
protected String encodingName;
protected boolean enable;
public TomcatFormFilter() {
this.encodingName = "UTF-8";
this.enable = false;
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
loadConfigParams();
}
private void loadConfigParams() {
//encoding
this.encodingName = this.filterConfig.getInitParameter("encoding");
//filter enable flag
String strIgnoreFlag = this.filterConfig.getInitParameter("enable");
if (strIgnoreFlag.equalsIgnoreCase("true")) {
this.enable = true;
} else {
this.enable = false;
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if(this.enable) {
request.setCharacterEncoding(this.encodingName);
}
chain.doFilter(request, response);
}
public void destroy() {
}
}
然后,需要在web.xml中注册过滤器类:
<filter>
<filter-name>TomcatFormFilter</filter-name>
<filter-class>filters.TomcatFormFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
<init-param>
<param-name>enable</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>TomcatFormFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这段程序对静态页面、JSP页面以及表单POST乱码问题能够起到效果。在使用这段代码注意以下几点:
1)在JSP表单中如果未指定提交方式,控制器默认将按POST方式提交。
2)web.xml中,如果我们用<param-value>UTF-8</param-value>代替<param-value>GBK</param-value>,解决中文乱码没有效果。
3)对Tomcat服务器中表单GET方式的中文乱码问题是无能为力的。
为了彻底解决以上所有的中文乱码问题,推荐《MyEclipse 6 java 开发中文教程》一文中的例程如下(web.xml中的内容可参考以上不变):
package filters;
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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class TomcatFormFilter implements Filter {
class Request extends HttpServletRequestWrapper {
public Request(HttpServletRequest request) {
super(request);
}
// 转换由表单读取的数据的内码. 从 ISO 字符转到 GBK.
public String toChi(String input) {
try {
byte[] bytes = input.getBytes("ISO8859-1");
return new String(bytes, "GBK");
} catch (Exception ex) {
}
return null;
}
// Return the HttpServletRequest holded by this object.
private HttpServletRequest getHttpServletRequest() {
return (HttpServletRequest) super.getRequest();
}
// 读取参数 -- 修正了中文问题.
public String getParameter(String name) {
return toChi(getHttpServletRequest().getParameter(name));
}
// 读取参数列表 - 修正了中文问题.
public String[] getParameterValues(String name) {
String values[] = getHttpServletRequest().getParameterValues(name);
if (values != null) {
for (int i = 0; i < values.length; i++) {
values[i] = toChi(values[i]);
}
}
return values;
}
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpreq = (HttpServletRequest) request;
if (httpreq.getMethod().equals("POST")) {
request.setCharacterEncoding("GBK");
} else {
request = new Request(httpreq);
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
}