Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

Java JSP/Servlet

Servlet/JSPで日本語文字が「???」になる問題とFilterの活用について

投稿日:2020年2月24日 更新日:

(0)目次&概説

(1) 事象
(2) 原因
(3) 対処方法1
 (3-1) フィルタクラスの新規作成
 (3-2) フィルタクラスへのコード追加
 (3-3) 疎通確認テスト
(4) 対処方法2
 (4-1) setContentTypeの場所修正
(5) 解説
 (5-1) フィルタクラスとは?
 (5-2) フィルタはどのタイミングで発動する?
 (5-3) フィルタクラスのプログラム概要

(1) 事象

サーブレットの画面にて日本語の文字を表示しようとすると「???」と文字化けしてしまった。

(図101)

目次にもどる

(2) 原因

HttpServretRequestのgetWriterを呼び出す前に「response.setContentType(“text/html; charset=UTF-8”);」で文字コードの指定を行わなかったため、デフォルトの文字コード(ISO-8859-1)になってしまった事が原因です。そのため途中で「charset=UTF-8″」しても、上書きされずデフォルトの文字コードままappendされて文字化けしていました。

(図201)
本来は35行目の「getWriter」の前でcharsetの指定を行う必要がある。

目次にもどる

(3) 対処方法1

対処方法の一つが「フィルタクラス」を追加して、出力時のエンコード処理をする事です。

(3-1) フィルタクラスの新規作成

(3-1-1) Eclipseのメニューから「File」→「New」→「Other」を選択します。

(図311)

(3-1-2) 「New」画面のWizards検索窓に「filter」と入力してフィルタークラスを探し選択します。

(図312)

(3-1-3) Class Name等の情報を設定して「Next」を押下します。

(図313)

(3-1-4) Filter mappingsの条件を設定します

「Filter mappings」でフィルタの適用範囲を指定します。デフォルトのレコードを選択して「Edit」で編集します。適用範囲は次のようにプロジェクト全体を指定したり、部分的に適用したり小回りが利きます。

(図314)

(表)

全体適用
(プロジェクト全体に適用)
(1)ワイルドカード指定でプロジェクト全体に適用されます
/*
部分適用
(プロジェクトの特定箇所に適用)
(1)JSPの場合
構文: /[JSP名].jsp
例: /Test1.jsp

(2)サーブレットの場合
構文: /[アノテーション名]
例: /WebAPI_Test6

目次にもどる

(3-1-5) 実装するフィルタの指定を行います

今回はデフォルトの「javax.servlet.Filter」インターフェイスを実装する設定で進みます。

(図316)

目次にもどる

(3-2) フィルタクラスへのコード追加

フィルタクラスのdoFilterメソッド内の「chain.doFilter」の前にリクエストデータ(サーバから見た受信)の文字コードと、レスポンス(サーバから見た送信)の文字コードを指定します。

request.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");

(図321)

次にTomcatを再起動します。
(図322)

目次にもどる

(3-3) 疎通確認テスト

画面をもう一度開き直すと文字化けが解消している事が確認できます。
(図331)

目次にもどる

(4) 対処方法2

(4-1) setContentTypeの場所修正

フィルタクラスの追加でも勿論対応できますが、よりピンポイントの対処方法としては、単にset

■修正前

response.getWriter().append("Served at: ").append(request.getContextPath());

↓ ■修正後

response.setContentType("text/html;charset=UTF-8");
response.getWriter().append("Served at: ").append(request.getContextPath());

目次にもどる

(5) 解説

(5-1) フィルタクラスとは?

フィルタはServletやJSPが呼び出された時に一緒に呼び出され、フィルタリング等の付随処理を担います。付随処理の例としては、暗号化や認証やログの集計など様々あります。

フィルタクラスの強みは、ServletやJSPの中で明示的に呼び出し必要が無い点です。なので共通ロジックのフィルタを呼び出す行をServletやJSPに書いたりする必要はなく、メンテナンスの負荷が低く済みます。

目次にもどる

(5-2) フィルタはどのタイミングで発動する?

デフォルトでは本来のJSPやサーブレットのURLが呼び出された時に起動しますが(REQUEST)、web.xmlの<filter-mapping>要素等でタイミングを任意に指定する事もできます。

流れとしては次の図のようになります。「①クライアント」からのリクエストが「②トリガー」により検知されWebAPサーバに届き、「③サーブレットコンテナ」にて、今回のテーマである「フィルタ処理」がされ、実行エンジンにより要求ページの解析・処理を行います。

(図521)

  >目次にもどる

(5-3) フィルタクラスのプログラム概要

今回使用したフィルタクラスのサンプルプログラムを紹介します。

package filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

/**
 * Servlet Filter implementation class TestFilter
 */
@WebFilter("/*")
public class TestFilter implements Filter {

    /**
     * Default constructor.
     */
    public TestFilter() {
    }

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");
        // pass the request along the filter chain
        chain.doFilter(request, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {
    }
}

■プログラム解説

行数 処理概要
16行目 “implements Filter”から分かる通り、Filterインターフェイスを実装しています。フィルタに必要なメソッドがFilterインターフェイスに定義されており、これらを実装する事でフィルタを自在に作れます。
注意事項として、インターフェイスを実装する際は例えそのメソッドが不要であっても、空のメソッドとして雛形の記述を行わないとエラーになります(図531)。
例えば、今回の例ではinitメソッドやdestroyメソッドは実装していませんが、定義の記述自体がないとエラーになるので空のメソッドを記述しています。
27行目 (1) メソッドの引数が「ServletRequest」と「ServletResponse」オブジェクトのため、もし「HttpServletRequest」や「HttpServletResponse」型のオブジェクトの機能が必要な場合は型のキャスト等が必要となります。

(2) doFilterメソッドは登録されたフィルタの集まりの中から、次のフィルタを起動します。起動対象が無い場合は本来の要求ページを表示します。

(図531)
インターフェイスに存在するメソッドは空でも記述しないとエラーになる

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-Java, JSP/Servlet

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

Javaのスレッドとは?概念やサンプルプログラムのご紹介

  <目次> (1) Javaのスレッドとは?概念やサンプルプログラムのご紹介  (1-1) Javaのスレッドとは?  (1-2) 方法①:Threadクラス継承の構文  (1-3) 方法 …

JavaScriptのオブジェクト(object)の書き方やメソッドを追加する方法

  <目次> (1) JavaScriptのオブジェクト(object)の書き方やメソッドを追加する方法  (1-1) 構文①:オブジェクト作成  (1-2) 構文②:オブジェクトにアクセス …

JavaのhashCode()で31を掛け算する理由について

<目次> (1) JavaのhashCode()で31を掛け算する理由について  (1-1) ハッシュの計算のソースコード  (1-2) ソースコードに登場する代表的な変数  (1-3) ソースコード …

JavaのMapの種類や特徴について(HashMap/LinkedHashMap/TreeMap)

<目次> (1) JavaのMapの種類や特徴について(HashMap/LinkedHashMap/TreeMap)  (1-1) Mapとは?  (1-2) Mapの種類や特徴   (1-2-1) …

サーブレットとは?その役割やHelloWorldサンプルコードのご紹介

(0)目次&概説 (1) サーブレットの基本  (1-1) サーブレットとは?  (1-2) サーブレットの前身技術との比較  (1-3) サーブレットとJSPの違い  (1-4) サーブレットのHe …

  • English (United States)
  • 日本語
Top