kikki's tech note

技術ブログです。UnityやSpine、MS製品など技術色々について解説しています。

Spring BootでUTF-8でない文字コードを受け付けるためには

本章では、SpringBootの環境でUTF-8以外の文字コードをコントローラーが受け付けるための方法について共有します。

はじめに

Spring Bootでは、デフォルトの文字コード*1が「UTF-8」となっています。
Appendix A. Common application properties
上記の設定は、自サイトでの使用において、問題となりません。一方で、外部サービスからのリクエストを受け付ける場合に、文字コードを変更の必要があるケースがあります。
そこで自サイトで、「UTF-8」を使用しながら、外部サービスからのリクエストで別の文字コードを受付けられる方法について考えてみました。

手法

SpingBootでは、コントローラーの引数で受け取ったリクエストデータが既に「UTF-8」でエンコードされています。そのため、コントローラーに渡る前に、エンコードの設定を変更する必要があります。
そこで今回、「OrderedCharacterEncodingFilter」を継承したフィルタを作成し、Spring DIコンテナにbeanとして登録する方法で解決してみます。

ソース

本節では、サンプルとして「Shift-JIS」で文字コードを受け付ける場合の方法について、以下に示します。
[SJISCharacterEncodingFilter.java]

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.boot.context.web.OrderedCharacterEncodingFilter;

/**
 * Shift-JISを受け付けるためのフィルタ
 */
public class SJISCharacterEncodingFilter
        extends OrderedCharacterEncodingFilter {

    /**
     * @see org.springframework.web.filter.CharacterEncodingFilter#doFilterInternal(javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain)
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        super.setOrder(HIGHEST_PRECEDENCE);
        Pattern pattern = Pattern.compile("^/api/get/.*$");
        Matcher matcher = pattern.matcher(request.getRequestURI());
        if (matcher.find()) {
            super.setEncoding("Shift_JIS");
        } else {
            super.setEncoding("UTF-8");
        }
        super.setForceEncoding(true);
        super.doFilterInternal(request, response, filterChain);
    }

}

ここで重要なこととして、デフォルで用意されているエンコード設定より、優先度が高いことを示す必要があります。そのため、「Order」を「HIGHEST_PRECEDENCE」に設定しています。

そして上記フィルタを既存の設定から上書き設定をしましょう。

    @Bean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new SJISCharacterEncodingFilter();
        return filter;
    }

筆休め

文字コードをサービス内、一つだけの対応は極めて簡単でしたが、複数の文字コードを使い分ける場合の対応が大変でした。レガシーなサービスを利用する場合等に参考としてみてください。

以上、「Spring BootでUTF-8でない文字コードを受け付けるためには」でした。

*1:システム内部のデフォルト文字コードはISO-8859-1

※無断転載禁止 Copyright (C) 2015 kikkisnrdec All Rights Reserved.