クマの手も借りたい
馬とテニスとリラックマが好きな IT 系のエンジニアです。
Kotlin

SpringBootのCharacterEncodingFilterで特定のURLパスの文字コードを変更する

Kotlin と Sprint Boot の組み合わせでアプリを作っていて、外部から Shift_JIS(SJIS)の文字コードでリクエストを受け付けないといけないケースが発生したので対応。

以前「SpringBoot(Thymeleaf)でレスポンスの文字コードを指定する」でも書いた通り、レスポンスの文字コードを変更するにはリクエスト単位でマッピング情報の produces で指定可能でした。

あわせて読みたい
SpringBoot(Thymeleaf)でレスポンスの文字コードを指定する通常であればアプリケーションで使用する文字コードは 1 つだと思います。 今の時代なら「UTF-8」でしょうし、古いサイトであれば...

しかしリクエストについては、consumes では思った挙動にならなかったので CharacterEncodingFilter の調整に挑戦してみました。

CharacterEncodingFilterについて

Spring Boot では CharacterEncodingFilter が自動的に設定されていて「UTF-8」の文字コードが設定されます。

よって、UTF-8 の文字コードをアプリ内で扱っている分には設定ファイルなどを気にせず実装ができます。

しかし、今回の要件を満たすにはこのフィルタを調整する以外に方法が思い付きません。

極力、他には影響しないように調整したいところですが、結果的には URL のパスで分岐するしかないのかなぁっと諦めムード。

CharacterEncodingFilterを上書きする方法

いくつか CharacterEncodingFilter を上書きする方法はあるようですが、大きく参考にさせてもらったのは下記のサイトです。
(KotlinではなくてJavaのサンプルですが)

これを参考にして、以下のようなロジックを構成してみました。

import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter
import org.springframework.stereotype.Component
import java.util.regex.Pattern
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

@Component
class HogeCharacterEncodingFilter : OrderedCharacterEncodingFilter() {

    /**
     * SJISの対象URLリスト
     */
    private val targetUrlList = listOf(
        "^/api/hoge/*",
        "^/api/fuga/*"
    )

    override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
        super.setOrder(HIGHEST_PRECEDENCE)
        val pattern = Pattern.compile(targetUrlList.joinToString("|"))
        val 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)
    }
}

参考にしたサイトでは定義はなかったのですが、@Component のアノテーションがないとインジェクションされなかったので付けています。

最後に、 @Bean アノテーションを付けて上記のフィルタクラスを読み込むようにしてみます。

この定義は Kotlin のアプリケーションクラスに追記しました。

@Bean
fun characterEncodingFilter(): CharacterEncodingFilter {
    return HogeCharacterEncodingFilter()
}

まとめ

URL のパスによってうまく文字コードの切り替えができているのを確認していますが、まだ不備があるかもしれないのでテストしながら様子見してみます。

古いシステムを相手にしていると、文字コードが Shift_JIS というケースはまだまだたくさんあります。

大きなシステムほど移行は簡単ではないので、ずっと引きずってしまう傾向にあるのでしょうね。

それにしても、Spring Boot のアノテーション文化にはなかなか慣れないなぁ。

やさしいKotlin入門

プログラミング初心者または Kotlin 初心者向けの入門本。Android 開発ではなく Kotlin の言語を覚えてみたい方にオススメの入門本です。

Java と比較して説明される書籍が多い中、Java や他のプログラム言語を知らない人向けになるので、例えば Java はあまり詳しくないけど PHP や Python は書けるといったパターンとも相性がいいですよ。

created by Rinker
¥2,592
(2018/09/20 12:37:29時点 Amazon調べ-詳細)

あなたにオススメ