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来构建应用程序吧!!

广告
将在 10 秒后关闭
bannerAds