使用过滤器Filter解决乱码问题
在之前编写servlet时,需要在每个servlet中声明编码,这种方式比较繁琐,下面使用Filter解决该问题。
首先搞个Servlet 做登录后台:
package filter;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class login extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("用户名:" + request.getParameter("user"));
System.out.println("密码:" + request.getParameter("pass"));
}
}
我们会发现打印的user是乱码【中文】,所以如果有100个Servlet 我们就要配 100 个 编码? 繁琐! 接下来监视器搞定:
web.xml 配置过滤器全部都网站都过滤:【/*】
<filter>
<filter-name>filter_test</filter-name>
<filter-class>filter.filter_test</filter-class>
</filter>
<filter-mapping>
<filter-name>filter_test</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
filter.java: 【过滤器】
package filter;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class filter_test implements Filter {
public void destroy() {
System.out.println("过滤器已销毁×");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
/*
* 这种方法只能解决post请求的来回乱码
* 因为get请求的编码他会放在tomcat的一个Map中【默认是isoxxx编码】,我们只需要去配置tomcat的编码即可解决get的
* */
//设置post请求的编码
request.setCharacterEncoding("utf-8");
//设置响应编码
response.setContentType("text/html;charset=utf-8");
chain.doFilter(request, response); //这句话很重要的啊 没这句话相当于用户的请求被拦截了
}
public void init(FilterConfig fConfig) throws ServletException {
System.out.println("过滤器已创建√");
}
}
所以 两行代码搞定所有的 post请求的乱码了 Get 为什么不会乱码 和 乱码怎么解决前面已经说的很清楚 配置一下即可,当然你不配置也可以 但很繁琐! 这里不介绍了。
其次千万主义
chain.doFilter(request, response);
这个 没这个相当于被拦截了请求哦
你要真的有杠精 那么你就:【超繁琐】
同时解决get和post乱码问题
上面的代码中只能解决post方式的乱码问题,然而对于get方式依然不起作用。
下面我们再来分析一下乱码产生的原因:当浏览器将包含有中文(例如 UTF-8 编码)参数的请求(无论是 GET 还是 POST 请求),以字节序列的形式发送到服务器后,服务器会按照其默认的字符编码ISO8859-1 进行解码,并将解码后的字符存放到 ParameterMap 中。此时的 ParameterMap 中存放的字符其实已经是乱码了,因为将 UTF-8 的字符序列解码为ISO8859-1 的字符,当然会出现乱码。要从根本上解决这个乱码问题,我们可以将ParameterMap中的参数重新按照UTF-8进行编码,这样Servlet 再从 ParameterMap 中读取参数,就不会出现乱码了。
不过向 ParameterMap 中存放数据是由服务器自动完成的,“向 ParameterMap中存放数据”这个时间点程序员无法捕获。我们的解决方案思路是,自定义一个HttpServletRequest 类型,该类型是HttpServletRequest 的一个装饰者。让这个装饰者重写HttpServletRequest 中请求参数相关方法。例如,重写 getParameterMap()方法,在该方法中定义一个 Map,并将原始 ParameterMap 中存放的乱码问题解决后,将数据存放到这个新的Map 中。然后,再重写其它参数相关方法,让这些方法获取请求参数,直接从这个新的 Map中获取。这样乱码问题就得以解决。也就是说,将来整个应用中所有的请求对象将使用我们自定义的这个请求的装饰者。这个替换工作可以通过过滤器完成,即所有请求到达应用后,首先经过这个过滤器,将HttpServletRequest 请求替换为装饰者。
修改上面代码中的Filter中添加代码如下:
// 自定义request对象
class MyRequest extends HttpServletRequestWrapper { private HttpServletRequest request; private boolean hasEncode; public MyRequest(HttpServletRequest request) { super(request);// super必须写 this.request = request; } // 对需要增强方法 进行覆盖 @Override public Map getParameterMap() { // 先获得请求方式 String method = request.getMethod(); if (method.equalsIgnoreCase("post")) { // post请求 try { // 处理post乱码 request.setCharacterEncoding("utf-8"); return request.getParameterMap(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } else if (method.equalsIgnoreCase("get")) { // get请求 Map<String, String[]> parameterMap = request.getParameterMap(); if (!hasEncode) { // 确保get手动编码逻辑只运行一次 for (String parameterName : parameterMap.keySet()) { String[] values = parameterMap.get(parameterName); if (values != null) { for (int i = 0; i < values.length; i++) { try { // 处理get乱码 values[i] = new String(values[i] .getBytes("ISO-8859-1"), "utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } } hasEncode = true; } return parameterMap; } return super.getParameterMap(); } @Override public String getParameter(String name) { Map<String, String[]> parameterMap = getParameterMap(); String[] values = parameterMap.get(name); if (values == null) { return null; } return values[0]; // 取回参数的第一个值 } @Override public String[] getParameterValues(String name) { Map<String, String[]> parameterMap = getParameterMap(); String[] values = parameterMap.get(name); return values; } }