源码角度分析 CharacterEncodingFilter 解决 Post 请求中文乱码问题

源码角度分析 CharacterEncodingFilter 解决 Post 请求中文乱码问题

Post 乱码

Spring MVC 提供 CharacterEncodingFilter 拦截请求处理编码格式问题

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
package org.springframework.web.filter;

public class CharacterEncodingFilter extends OncePerRequestFilter {

private String encoding; // 指定的编码格式

private boolean forceRequestEncoding = false; // 是否设置请求编码格式

private boolean forceResponseEncoding = false; // 是否设置响应编码格式

public CharacterEncodingFilter() {
}

/**
* xml配置:一般只需要设置编码格式即可,默认支持请求编码转换
*/
public CharacterEncodingFilter(String encoding) {
this(encoding, false);
}

/**
* 也可以设置指定编码 and 是否设置请求和响应的编码转换
*/
public CharacterEncodingFilter(String encoding, boolean forceEncoding) {
this(encoding, forceEncoding, forceEncoding);
}

/**
* 设置指定编码 and 单独设置是否进行请求编码转换 或 响应的编码转换
*/
public CharacterEncodingFilter(String encoding, boolean forceRequestEncoding, boolean forceResponseEncoding) {
Assert.hasLength(encoding, "Encoding must not be empty");
this.encoding = encoding;
this.forceRequestEncoding = forceRequestEncoding;
this.forceResponseEncoding = forceResponseEncoding;
}

public void setEncoding(String encoding) {
this.encoding = encoding;
}

public String getEncoding() {
return this.encoding;
}

public void setForceEncoding(boolean forceEncoding) {
this.forceRequestEncoding = forceEncoding;
this.forceResponseEncoding = forceEncoding;
}

public void setForceRequestEncoding(boolean forceRequestEncoding) {
this.forceRequestEncoding = forceRequestEncoding;
}

public boolean isForceRequestEncoding() {
return this.forceRequestEncoding;
}

public void setForceResponseEncoding(boolean forceResponseEncoding) {
this.forceResponseEncoding = forceResponseEncoding;
}

public boolean isForceResponseEncoding() {
return this.forceResponseEncoding;
}

@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {

String encoding = getEncoding();
if (encoding != null) {
// 若 foreceRequestEncoding 参数为 true 则进行请求参数编码转换,没有设置字符编码时默认设置请求字符编码。
if (isForceRequestEncoding() || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(encoding);
}
// 若 foreceResponseEncoding 参数为 true 则进行响应参数编码转换
if (isForceResponseEncoding()) {
response.setCharacterEncoding(encoding);
}
}
filterChain.doFilter(request, response);
}
}

所以我们可以在xml文件中配置加载 CharacterEncodingFilter,通过配置不同的构造器参数决定是否将请求和响应的字符编码转换还是单独设置请求和响应。

注意:字符编码过滤器需要放在最前面。

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
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 必须指定。若只配置一个 encoding 参数,将处理请求的字符编码,不处理响应的字符编码 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 若设置 encoding 和 forceEncoding 参数,请求和响应都处理字符编码 -->
<!-- <init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param> -->
<!-- 分别指定是否处理请求字符编码和响应字符编码 -->
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Get 乱码

若服务器是 tomcat,修改 tomcat 的配置文件 server.xml。在第一个 Connerctor 节点添加 URIEncoding 标签:

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

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×