Filter+动态代理解决全站编码问题
Filter实现全站编码
https://zhuanlan.zhihu.com/p/65726805
注意:
从Tomcat8开始,默认编码已经改为UTF-8,所以已经不会出现Get请求乱码问题了。
只需处理Post乱码。
我们往常对乱码的处理都放在Servlet的doGet和doPost方法中:
这个案例采用的Tomcat7
但是这样太麻烦了,每写一个Servlet都要处理乱码。于是就想到用Filter处理。我能想到的有两种处理方式:装饰者模式、动态代理。
装饰者模式处理乱码的方案大家可以直接看崔老师的视频:
这里主要讲动态代理方式。
Filter+动态代理解决全站编码问题
对动态代理不熟悉的朋友,可以参考:Java 动态代理作用是什么?
web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.summerframework.web.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--测试Servlet-->
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>org.summerframework.web.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/TestServlet</url-pattern>
</servlet-mapping>
</web-app>
TestServlet
public class TestServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println(username);
response.getWriter().write(username);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println(username);
response.getWriter().write(username);
}
}
CharacterEncodingFilter
public class CharacterEncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
// 【响应编码设置】后面Servlet拿到的Response对象都是已经设置过编码的
res.setContentType("text/html;charset=utf-8");
/*
* 【请求编码设置】思路:
*
* 1.特别注意,这里的request/response类型是ServletRequest/ServletResponse,我们要强转成Http相关的
*
*
* 2.Filter传给后面Servlet的Request对象肯定不能是原先的,不然request.getParameter()还是会乱码
* 这里使用动态代理生成代理对象,所以后面Servlet拿到的其实是代理Request
*
* 3.对于Get、Post请求,解决乱码的方式是不同的,所以代理对象内部必须有针对两者的判断
* */
// 1.强转req/res 【思考一下为什么要加final】
final HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// 2.使用Proxy.newProxyInstance()创建Request代理对象
Object proxyRequest = Proxy.newProxyInstance(
this.getClass().getClassLoader(), /*类加载器*/
req.getClass().getInterfaces(), /*代理对象要和目标对象实现相同接口*/
new InvocationHandler() { /*InvocationHandler,采用匿名内部类的方式*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 由于乱码的根源在于getParameter(),所以我们只盯着这个方法
if (!"getParameter".equalsIgnoreCase(method.getName())) {
return method.invoke(request, args);
}
// 3.判断是Get还是Post
if ("GET".equalsIgnoreCase(request.getMethod())) {
// 按默认编码ISO-8859-1取出
String value = (String) method.invoke(request, args);
// 按IOS-8859-1得到字节,再按UTF-8转成中文
value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
// 返回正确的中文
return value;
} else {
// 目标方法前设置编码
request.setCharacterEncoding("UTF-8");
Object value = method.invoke(request, args);
return value;
}
}
});
//把代理request对象传给Servlet
chain.doFilter((HttpServletRequest) proxyRequest, res);
}
public void init(FilterConfig config) throws ServletException {
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/TestServlet?username=张三">点击发送Get请求</a><br/>
<form action="/TestServlet" method="post">
用户名:<input type="text" name="username" value="李四"/>
<input type="submit" value="提交Post请求">
</form>
</body>
</html>
示意图:
评论已关闭