get提交 超链接提交 解决中文乱码问题
GET提交:
解决一:
String key = "中文";
key = new String(key.getBytes("ISO8859-1"),"UTF-8");
但是这种不建议使用,
解决二:
可以再Tomcat配置文件server.xml配置
<Connector port="8080" protocol="HTTP/1.1"
maxThreads="150" connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"/>
每次提交都会从这里过滤中文
超链接提交:
可以在jsp中设置:
<a href="?key=<%=
URLEncoding.encode("中文","UTF-8")%>
附加:System.out.println(java.net.URLEncoder.encode("中文", "UTF-8"));
System.out.println(java.net.URLEncoder.encode("%E4%B8%AD%E6%96%87", "UTF-8"));
结果输出:
%E4%B8%AD%E6%96%87
中文
在web.xml配置过滤器
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
和普通过滤器配置没什么区别,就是多了两个初始化参数,两个参数的作用分别是:
encoding----->用来指定一个具体的字符集
forceEncoding------->Spring的早期版本这个参数作用很单一,当request中已经被指定了一个字符集的时候是否再将用endcoding对应的字符集设置到request中去。举个例子来说明,假如说过滤器就像上面那样被配置到web.xml了,当请求被提交之后,过滤器会判断request.getCharacterEncoding()是否为null,如果是null那么就会进行request.setCharacterEncoding("UTF-8")的操作,如果不是null那么过滤器什么也不会做。
不过Spring目前得版本这个类的代码已经被重构了,代码更加“漂亮”了,这个参数的作用也发生了细微的改变。
为了加深印象从源码来分析一下这个参数的变化。
首先,说明 一下CharacterEncodingFilter是继承OncePerRequestFilter抽象类而来的,OncePerRequestFilter实现了doFilter方法:
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
...........
...........
String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
if (request.getAttribute(alreadyFilteredAttributeName) != null || shouldNotFilter(httpRequest)) {
filterChain.doFilter(request, response);
}
else {
request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
try {
doFilterInternal(httpRequest, httpResponse, filterChain);
}
finally {
request.removeAttribute(alreadyFilteredAttributeName);
}
}
}
public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";(在OncePerRequestFilter中定义的常量)
说明:
1. getAlreadyFilteredAttributeName()方法返回的字符串是="我们给filter配置的名字+ALREADY_FILTERED_SUFFIX",所以request请求第一次到达过滤器的时候request.getAttribute(alreadyFilteredAttributeName) 值一定是null ,shouldNotFilter(httpRequest)方法默认实现始终返回false(这个方法也可以在子类中进行扩展);
2. 当request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE)之后就会执行doFilterInternal(httpRequest, httpResponse, filterChain);方法了,doFilterInternal这里是个抽象方法,它是在子类CharacterEncodingFilter中被实现的,实现如下:
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
request.setCharacterEncoding(this.encoding);
if (this.forceEncoding && responseSetCharacterEncodingAvailable) {
response.setCharacterEncoding(this.encoding);
}
}
filterChain.doFilter(request, response);
}
private final static boolean responseSetCharacterEncodingAvailable = ClassUtils.hasMethod(
HttpServletResponse.class, "setCharacterEncoding", new Class[] {String.class});
说明:
1. 静态常量responseSetCharacterEncodingAvailable 是通过反射来判断response是否有setCharacterEncoding方法,返回值应该都是true.
2. this.encoding != null :当encoding初始化参数被指定时条件满足。
3. (this.forceEncoding || request.getCharacterEncoding() == null )==true:当forceEncoding初始化参数设置为true或者request已经被指定了一个字符编码的时候条件满足。
如果没记得错,Spring早期版本这个方法得实现应该是:
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (this.forceEncoding || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(this.encoding);
}
filterChain.doFilter(request, response);
}
参数forceEncoding的作用很明显了吧!以前只是对request字符编码起作用,现在如果将forceEncoding设为true也会影响到response中的字符编码,通常这个是我们不希望的。
总结:
1. OncePerRequestFilter这个抽象过滤器很好的实现了对每个request只执行一次过滤操作,如果有类似的需求可以继承该类并实现doFilterInternal方法来完成。
2. CharacterEncodingFilter类可以通过简单配置来帮我们实现字符集转换的功能。另外多说一句,如果采用Struts2.0的MVC框架我个人感觉中文问题已经不是问题了,可以通过配置struts.i18n.encoding常量来实现统一字符编码。
自己配置一个过滤器了也可以
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.kenshin.base.SysFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>enable</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
package com.kenshin.base;
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 org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
public class SysFilter implements Filter {
protected String sEncodingName;
protected FilterConfig sysFilter;
protected boolean bEnable;
protected Log logger = LogFactory.getLog(SysFilter.class);
public void destroy() {
}
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
// TODO Auto-generated method stub
if (this.bEnable) {
try {
arg0.setCharacterEncoding(this.sEncodingName);
arg1.setContentType("text/html;charset=" + this.sEncodingName);
arg1.setCharacterEncoding(this.sEncodingName);
arg2.doFilter(arg0, arg1);
} catch (Exception e) {
logger.info("出错了");
}
// session.close();
} else {
arg2.doFilter(arg0, arg1);
}
}
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
this.sysFilter = arg0;
this.loadFilterSetting();
}
private void loadFilterSetting() {
this.sEncodingName = this.sysFilter.getInitParameter("encoding");
logger.info("encoding:" + sEncodingName);
String sEnable = this.sysFilter.getInitParameter("enable");
if (sEnable != null && sEnable.equalsIgnoreCase("true")) {
this.bEnable = true;
} else {
this.bEnable = false;
}
}
}