Tomcat 8起,默认的URIEncoding已经改为UTF-8
有一天,当我调查JBoss(使用Tomcat作为Servlet容器)的查询字符串字符编码指定方法时,我发现Tomcat 8的URIEncoding已经从ISO-8859-1更改为UTF-8。
确实…自从升级到Tomcat 8之后,我觉得即使不明确指定URIEncoding,也不再出现乱码的情况。
既然如此,我会简单地总结一下Tomcat的URI编码。
Tomcat 7以前的URIEncoding
查看Tomcat 7的文档,明确指出使用ISO-8859-1编码。
因此,如果想要以UTF-8解析URI中的请求参数,需要在$TOMCAT_HOME/conf/server.xml中添加以下定义。
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8" /> <!-- ← 追加 -->
Tomcat 8开始的URIEncoding
当查看Tomcat 8的文档时,明确指出了要使用UTF-8编码。
换句话说,没有必要特别做任何事情来采用UTF-8编码。(太棒了)
顺便提一下,Tomcat 7与Servlet规范相同,提供了将编码设置为ISO-8859-1的选项,并且只需在系统属性(-D选项)中指定”org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true”即可。(可能不会使用这个选项……)
Spring Boot内嵌的Tomcat的URIEncoding
如果在Spring Boot上使用内嵌的Tomcat,不管Tomcat的版本如何,URIEncoding的默认值将是UTF-8。
这是因为Spring Boot在配置内嵌的Tomcat时将UTF-8作为默认值指定。
如果想要使用其他字符编码,请在application.yml或application.properties中指定字符编码。
server:
tomcat:
uri-encoding: Windows-31J
使用BodyEncodingForURI属性
Tomcat为指定URI中查询参数的字符编码提供了两种方法,除了URIEncoding属性外,还提供了useBodyEncodingForURI属性。
将此属性设为true后,它会使用由javax.servlet.ServletRequest#setCharacterEncoding(String)指定的字符编码来解码查询参数。如果需要处理多种字符编码,请使用useBodyEncodingForURI属性而不是URIEncoding属性(尽管我认为在同一实例中最好设计为不需要处理多种字符编码)。
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
useBodyEncodingForURI="true" /> <!-- ← 追加 -->
在Spring Boot 1.3.3.RELEASE版本中,很遗憾,无法通过yaml或者properties文件进行配置。在这种情况下,我们可以使用Spring Boot提供的Servlet容器定制机制(EmbeddedServletContainerCustomizer + ConnectorCustomizer)。
@Bean
EmbeddedServletContainerCustomizer containerCustomizer() {
return (containerFactory) -> {
if (containerFactory instanceof TomcatEmbeddedServletContainerFactory) {
TomcatEmbeddedServletContainerFactory tomcatContainerFactory = (TomcatEmbeddedServletContainerFactory) containerFactory;
tomcatContainerFactory.addConnectorCustomizers((connector) -> {
connector.setUseBodyEncodingForURI(true);
});
}
};
}
在Spring中如何使用ServletRequest#setCharacterEncoding(String)的方法。
顺便提一下,在Spring应用中指定字符编码的方法。
在Spring MVC应用程序中指定字符编码。
如果使用Spring MVC,你可以使用Spring Web提供的org.springframework.web.filter.CharacterEncodingFilter来指定字符编码。
- XML based configuration
<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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- Java based configuration
public class SpringMvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
// ...
@Override
protected Filter[] getServletFilters() {
return new Filter[]{new CharacterEncodingFilter("UTF-8")};
}
}
在Spring Boot应用程序中指定字符编码
从Spring Boot 1.2开始,默认情况下会应用CharacterEncodingFilter,并设置为UTF-8。(如果使用UTF-8,不需要进行任何操作)
如果想要使用除UTF-8之外的字符编码,请在application.yml或application.properties中指定字符编码。
spring:
http:
encoding:
charset: Windows-31J
总结
使用最新版的Spring Boot(1.3.3.RELEASE),可以使用嵌入式Tomcat 8版本,并自动应用UTF-8的CharacterEncodingFilter字符编码过滤器,所以如果处理的字符编码是UTF-8,就无需做任何处理就不会出现乱码!!让我们使用Spring Boot来构建应用程序吧!!