乱码问题是伴随整个web开发项目,任何人都会遇到,所以这里将处理乱码方式详细记录一下。无论是get请求还是post请求都会产生乱码,对于get请求,可以通过修改tomcat配置文件一次性解决,但是post请求不行,具体可以参考如下内容。
一、GET请求的乱码
在tomcat7中在默认配置server.xml下,GET请求会出现乱码,在tomcat8中不会出现乱码。这个地方有一点点区别。
解决tomcat7 GET请求乱码,修改tomcat7中conf/server.xml文件,增加URIEncoding="UTF-8"配置项,具体如下:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8" />
二、原生Servlet处理POST请求乱码
2.1、通过Servlet Request/Response接口
public class HelloServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost....");
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
Integer age = Integer.valueOf(req.getParameter("age"));
req.setAttribute("username", username);
req.setAttribute("password", password);
req.setAttribute("age", age);
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
}
}
2.2、通过Filter过滤器
首先,实现Filter接口
//实现Filter接口
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
其次,配置过滤器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 配置Servlet -->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.example.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置过滤器 -->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.example.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
最后,处理请求,可见是直接获取参数
public class HelloServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
Integer age = Integer.valueOf(req.getParameter("age"));
req.setAttribute("username", username);
req.setAttribute("password", password);
req.setAttribute("age", age);
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
}
}
2.3、通过ServletRequestListener监听器
首先,实现ServletRequestListener接口
public class RequestListenerHandler implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
try {
sre.getServletRequest().setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
其次,在web.xml中注册listener(这里没有过滤器配置)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 配置Servlet -->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.example.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>com.example.listener.RequestListenerHandler</listener-class>
</listener>
</web-app>
最后,Servlet处理
public class HelloServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
Integer age = Integer.valueOf(req.getParameter("age"));
req.setAttribute("username", username);
req.setAttribute("password", password);
req.setAttribute("age", age);
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
}
}
其中前两种比较常见,这里简单说一下第三种,第三种方式不常用,了解即可。
1)第三种方式,主要利用Servlet提供Listener接口,每次创建请求的时候都会被调用,而且Listen接口要早于Filter接口线支持。Servlet执行顺序:监听器,过滤器,Servlet
2)通过listener接口可知,我们没有办法获取到response对象,也就没有办法设置response编码格式,需要在处理的时候单独处理一下
3)对于response乱码,我们需要通常需要设置这两个
resp.setCharacterEncoding("UTF-8"); //告诉Servlet,按照utf-8编码字节流
resp.setContentType("text/html;charset=utf-8"); //告诉浏览器,按照utf-8编码显示
三、SpringMvc处理POST请求乱码
Servlet解决乱码有一个前提:设置编码之前一定要在获取参数之前设置,否则是无效的。例如下面代码对是无效的:
@RequestMapping("/hello")
public String hello(String username, HttpServletRequest request) throws UnsupportedEncodingException {
request.setCharacterEncoding("UTF-8"); //形参username是从request中获取的,此处在设置编码也是无效的,除非删除形参username
String uname = request.getParameter("username");
String password = request.getParameter("password");
Integer age = Integer.valueOf(request.getParameter("age"));
request.setAttribute("username", uname);
request.setAttribute("password", password);
request.setAttribute("age", age);
return "test";
}
这里设置编码是在获取username参数之后,所以不能生效,除非删掉形参username,但是删掉了username之后,就又变成原生的Servlet方式,不能充分发挥SpringMvc能力。
3.1、过滤器Filter
在web.xml中配置SpringMvc提供的过滤器
<filter>
<filter-name>CharacterEncodingFilter</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>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
@RequestMapping("/hello")
public String hello(String username, String password, Integer age, Model model) throws UnsupportedEncodingException {
model.addAttribute("username", username);
model.addAttribute("password", password);
model.addAttribute("age", age);
return "test";
}
3.2、拦截器HandlerInterceptor
拦截器是SpringMvc提供的,并不是Servlet的东西,拦截器与过滤器功能类似,但拦截器功能更强大一些,下面拦截器工作原理:
所以我们实现HandlerInterceptor接口后,也是可以处理乱码问题,具体如下:
public class EncodingInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
在springmvc.xml文件配置一下拦截器,具体如下:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean id="EncodingInterceptor" class="com.example.interceptor.EncodingInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
四、Springboot处理POST请求乱码
后面补充
五、JSON中乱码
六、总结
解决乱码问题根本思想:在获取参数值,之前先设置一下编码,只要符合这个规则通过什么方式解决乱码都是无所谓的,不过通常都是通过过滤器。