SpringMVC-乱码

乱码!一生之敌!!!

UserController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.lizhi.controller;

import com.lizhi.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/user")
public class UserController {

@PostMapping("/login.do")
public String login(User user, Model model){
model.addAttribute("user",user);
return "index";
}
}

login.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/user/login.do" method="post">
<p>
<input type="text" name="name">
</p>
<p>
<input type="text" name="age">
</p>
<input type="submit" value="提交">
</form>
</body>
</html>

index.jsp

1
2
3
4
5
6
7
8
9
10
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
name:${user.name}
age:${user.age}
</body>
</html>

结果如下:

我们先尝试一下配置一个过滤器,这是第一种方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.lizhi.filter;


import javax.servlet.*;
import java.io.IOException;

public class CharsetFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
}

@Override
public void destroy() {

}
}

记得去web.xml中注册

1
2
3
4
5
6
7
8
<filter>
<filter-name>charsetFilter</filter-name>
<filter-class>com.lizhi.filter.CharsetFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>charsetFilter</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>

我们尝试后发现,没有任何效果,那既然我们写的过滤器不行

那springmvc给我们写了一个专门处理乱码的过滤器,我们来配置一下,这是第二种方案,很稳妥

1
2
3
4
5
6
7
8
9
10
11
12
<filter>
<filter-name>encoding</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>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>

测试后发现,还是乱码!!这时候我们可以去看一下tomcat的config目录下的server.xml,找到connector标签并修改属性

1
2
3
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8" />

发现还是不行,我们去找一个其他大佬自己写的过滤器试一试,这是第三种方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package com.lizhi.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

public class EncodeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//处理response的字符编码
HttpServletResponse resp = (HttpServletResponse) servletResponse;
resp.setContentType("text/html;utf-8");

HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletRequest myreq = new MyRequest(req);
filterChain.doFilter(myreq, resp);
}

@Override
public void destroy() {

}
}
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;

private boolean hasEncode;

public MyRequest(HttpServletRequest request) {
super(request);
this.request = request;
}

@Override
public Map getParameterMap() {
String method = request.getMethod();
if("post".equalsIgnoreCase(method)){
try{
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}else if("get".equalsIgnoreCase(method)){
Map<String,String[]> parameterMap = request.getParameterMap();
if(!hasEncode){
for (String parameterName : parameterMap.keySet()) {
String[] values = parameterMap.get(parameterName);
if(values!=null){
for (int i = 0; i < values.length; i++) {
try{
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();
return parameterMap.get(name);
}
}

结果测试发现,还是不对!其实乱码的问题到这里一般都会解决了,但是为什么还是不行呢?

其实是在注册filter的时候就出错了,接下来看下面的正确配置,大家可以看一下有什么区别,

1
2
3
4
5
6
7
8
<filter>
<filter-name>otherEncodeFilter</filter-name>
<filter-class>com.lizhi.filter.EncodeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>otherEncodeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

有的小伙伴可能在一开始就看出来了,没错,就是<<url-pattern>/*</url-pattern>>这里的拦截路径我们应该使用/*而不是/

两者有什么区别呢?

前者是拦截一切请求,包括jsp

而后者会拦截除了jsp的所有资源

相信吃了这次亏,大家之后就再也不会忘记这个坑了!而且也了解了大部分乱码问题的解决方案!

给作者买杯咖啡吧~~~