40
42

More than 5 years have passed since last update.

Tomcat 8からURIEncodingのデフォルトがUTF-8になっていた

Last updated at Posted at 2016-03-21

先日、JBoss(ServletコンテナとしてTomcatを使っている)のクエリ文字列の文字コードの指定方法を調べていた時に、Tomcat 8のURIEncodingがISO-8859-1からUTF-8に変わっていたことを知りました。
たしかに・・・Tomcat 8にしてからURIEncodingを明示的に指定しなくても文字化けしなくなったような気はしていました。

せっかくなので、TomcatのURIエンコーディングについて簡単にまとめてみます。

Tomcat 7までのURIEncoding

Tomcat 7のドキュメントを見ると、ISO-8859-1と明記されています。
そのため、URI内のリクエストパラメータをUTF-8で解釈したい場合は、$TOMCAT_HOME/conf/server.xmlに以下のような定義を追加する必要がありました。

$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をデフォルト値として指定しているためです。
UTF-8以外の文字コードを使用したい場合は、application.yml or application.propertiesに文字コードを指定してください。

src/main/resources/application.yml
server:
    tomcat:
        uri-encoding: Windows-31J

useBodyEncodingForURI属性

TomcatにはURI内のクエリパラメータの文字コードを指定する方法として、URIEncoding属性とは別にuseBodyEncodingForURI属性を用意しています。
この属性をtrueにすると、javax.servlet.ServletRequest#setCharacterEncoding(String)で指定した文字コードを使用してクエリパラメータをデコードしてくれます。同一インスタンス内で複数の文字コードを扱う必要がある場合は、URIEncoding属性ではなくuseBodyEncodingForURI属性を使うことになると思います。(とはいえ、同一インスタンス内で複数の文字コードを扱わないように設計するのがよいとは思います)

$TOMCAT_HOME/conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           useBodyEncodingForURI="true" /> <!-- ← 追加 -->

では、Spring Bootだとどうやって設定するのでしょうか?
Spring Boot 1.3.3.RELEASEの時点では、残念ながらyaml又はpropertiesファイルで指定する方法はありません。
このような場合は、Spring Bootが提供しているServlet Containerをカスタマイズする仕組み(EmbeddedServletContainerCustomizer + ConnectorCustomizer)を使います。

JavaConfigクラス
@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
src/main/webapp/WEB-INF/web.xml
<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
SpringMvcWebApplicationInitializer.java
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でOKなら何もする必要はありません)
UTF-8以外の文字コードを使用したい場合は、application.yml or application.propertiesに文字コードを指定してください。

src/main/resources/application.yml
spring:
  http:
    encoding:
      charset: Windows-31J

まとめ

最新のSpring Boot(1.3.3.RELEASE)を使えば、組み込みTomcatも8系だし文字コードがUTF-8のCharacterEncodingFilterが自動で適用されるので、扱う文字コードがUTF-8なら何もしなくても文字化けしません!!
Spring Bootを使ってアプリケーションを作りましょう!!

40
42
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
42