使用过滤器解决中文乱码问题
一:常规方法
(1)Post提交方式
1.第一种用法:
使用xml配置文件
//配置文件,在web.xml中写入如下代码
<filter>
<filter-name>MyFilterConfig</filter-name>
<filter-class>com.zzz.MyFilterConfig</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
//在Servlet中写入如下代码
request.setCharacterEncoding(this.getServletContext().getInitParameter("charset"));
2.第二种用法
直接在Servlet中写入
request.setCharacterEncoding("utf-8");
分析:第一种用法的好处是,后期如果要修改编码方式,可以直接修改xml配置文件即可,不需要修改其他代码。
但以上两种用法都只能解决Post提交方式乱码问题,如果是Get方式需进行如下方式解决。
(2)Get提交方式
String name = request.getParameter("name");
name= new String(name.getBytes("ISO-8859-1"),"utf-8");
分析:上述方式虽然也能解决乱码问题,但需要针对不同的提交方式使用不同的解决方法。
二、优化方法
思路:
使用一个过滤器,在请求到达servlet之前,先对request对象设置编码
要求所有的请求都要进行设置编码,因此所有的request都要拦截,具体操作方法如下:
1.配置xml文件
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.yyy.product.web.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>//表示对所有请求都进行过滤
</filter-mapping>
2.过滤器代码:
public class EncodingFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 处理请求乱码
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
HttpServletRequest myRequest = new MyRequest(httpServletRequest);
// 处理响应乱码
System.out.println("过滤器拦截");
response.setContentType("text/html;charset=utf-8");
chain.doFilter(myRequest, httpServletResponse);
System.out.println("过滤器放行");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
3.自定义增强类,即/自定义request对象(MyRequest)
// 自定义request对象
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
private boolean hasEncode;
public MyRequest(HttpServletRequest request) {
super(request);// super必须写
this.request = request;
}
// 对需要增强方法 进行覆盖
@Override
public Map<String, String[]> getParameterMap() {
// 先获得请求方式
System.out.println("开始转码");
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;
}
}
三、实际使用中遇到的问题
虽然方式二能很好的解决Get和Post方式提交的表单,但对于属性enctype="multipart/form-data"这一种表单会存在以下问题:
偶然一次使用中发现,使用FileItem.getName()方法不会出现乱码,但使用FileItem.getString()方法获取普通表单的中文内容时依然会存在乱码问题
解决方法:
if("category".equals(fileItem.getFieldName())) {
product.setCategory(new String(fileItem.getString().getBytes("ISO-8859-1"),"UTF-8"));
}
或者
if("name".equals(fileItem.getFieldName())) {
product.setName(fileItem.getString("UTF-8"));
}