在开发web项目时,我们总会遇到中文乱码问题,此时就需要在代码中对中文进行解码,比较原始的方法是在每个 Servlet 中对单独对中文进行处理,但这样就会产生很多重复的代码。所以我们选择在 Filter 中处理中文编码问题,让每一个请求在到达 Servlet 之前,先在 Filter 中处理编码问题。这里我们分别通过装饰模式和动态代理模式两种方式来进行解决,在处理全局编码的同时,顺便对两种设计模式进行学习。
装饰模式解决全站编码
对目标方法进行重写
public class BufferedEncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(final ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
chain.doFilter(new HttpServletRequestWrapper((HttpServletRequest) req){
@Override
public String getParameter(String name) {
String parameter = req.getParameter(name);
try {
parameter = new String(parameter.getBytes("ISO-8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return parameter;
}
}, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
动态代理模式解决全站编码
对目标方法进行增强
public class ProxyEncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(final ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
chain.doFilter((HttpServletRequest)Proxy.newProxyInstance(
req.getClass().getClassLoader(),
req.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("getParameter".equalsIgnoreCase(method.getName())){
String value = (String) method.invoke(req, args);
value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
return value;
}
return method.invoke(req, args);
}
}),resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
对于 Tomcat8 以前的版本,如果是采用 maven 构建项目,可以在 pom.xml 文件中进行配置,就可以解决 get 请求的中文乱码问题。
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<!-- 增加该项属性,即可解决get请求的中文乱码问题 -->
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
从 Tomcat8 开始,默认编码已经改为 UTF-8 ,所以已经不会出现 GET 请求乱码问题了,只需处理 POST 乱码即可。