Encoding(garbled) problem in SpringMVC tomcat 2016-06-23 07:19
When I use SpringMVC and tomcat to develop the project I often meet garbled problem. In this page I will show you the right way to use them. The most important thing is making the "input" and "output" encoding same.
project structure
└─main
├─java
│ └─com
│ └─henryxi
│ └─tomcat
│ └─garbled
│ SimpleController.java
│ User.java
│
├─resources
│ spring-all.xml
│
└─webapp
│ index.jsp
│
└─WEB-INF
web.xml
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1-b01</version>
</dependency>
</dependencies>
GET method
If your use 'GET' method to make a request, the code of controller like following.
@RequestMapping(value = "/http-get", method = RequestMethod.GET, produces = "text/plain;charset=UTF-8")
@ResponseBody
public String testHttpGet(@RequestParam(value = "name") String name, @RequestParam(value = "address") String address) {
System.out.println("name:" + name + ",address" + address);
User user = new User(name, address);
return user.toString();
}
the request header like following(name=中文乱码&address=地址)
GET /http-get?name=%e4%b8%ad%e6%96%87%e4%b9%b1%e7%a0%81&address=%E5%9C%B0%E5%9D%80 HTTP/1.1
Host: localhost:8081
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: JSESSIONID=501E0A814B786AF3C020B2D45929AD32
the console output like following
name:????????±???,address??°???
Solution1
change tomcat server.xml
like following(add URIEncoding="UTF-8"
) can solve this problem. WHY? (Because parameters of GET
method are in URI).
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8"/>
Solution2
If you don't want change the config of tomcat you can transcode it by yourself.
@RequestMapping(value = "/http-get", method = RequestMethod.GET)
@ResponseBody
public String testHttpGet(@RequestParam(value = "name") String name, @RequestParam(value = "address") String address) {
name = new String(name.getBytes("ISO-8859-1"), "UTF-8");
address = new String(address.getBytes("ISO-8859-1"), "UTF-8");
System.out.println("name:" + name + ",address" + address);
User user = new User(name, address);
return user.toString();
}
POST method
If your use 'POST' method to make a request, the code of controller like following.
@RequestMapping(value = "/http-post-form-urlencoded", method = RequestMethod.POST, produces = "text/plain;charset=UTF-8")
@ResponseBody
public String testHttpPostFormUrlEncode(@ModelAttribute User user) {
System.out.println(user.toString());
return user.toString();
}
The Request Header like following
POST /http-post-form-urlencoded HTTP/1.1
Host: localhost:8081
Connection: keep-alive
Content-Length: 68
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://localhost:8081
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:8081/index.jsp
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: JSESSIONID=EC848DC0F4E4C1C650925DBBE88266F4
Form data
name=%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81&address=%E5%9C%B0%E5%9D%80
the console output
User{name='????????±???', address='??°???'}
Solution1(recommend)
add CharacterEncodingFilter
to you web.xml
file like following.
<filter>
<filter-name>encodingFilter</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>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Solution2
You can also transcode the parameters manually.
@RequestMapping(value = "/http-post-form-urlencoded", method = RequestMethod.POST, produces = "text/plain;charset=UTF-8")
@ResponseBody
public String testHttpPostFormUrlEncode(@ModelAttribute User user) throws UnsupportedEncodingException {
user.setName(new String(user.getName().getBytes("ISO-8859-1"),"UTF-8"));
user.setAddress(new String(user.getAddress().getBytes("ISO-8859-1"),"UTF-8"));
System.out.println(user.toString());
return user.toString();
}