日本語の表示とコンテンツタイプについて

5.1 日本語の表示とコンテンツタイプについて

 これまでのサーブレットでは、リクエストの結果として文字を画面に表示していましたが、これは下の図のような流れで行われています。

図 5.1.1: 文字列が画面に表示されるまでの流れ

 文字列は、そのままの状態でブラウザに送られているわけではなく、特定のデータに変換されてブラウザ側に送信されています。

5.1.1 日本語を表示してみよう

 前章までに作成したサーブレットでは、英文字のみを画面に表示しました。これから、日本語を表示するサーブレットを作成していきます。

日本語を表示するプログラム

 Webブラウザで英文字と日本語を表示するプログラムを作成し、表示された結果を確認します。

実行結果

アプリケーション構成

① ソース・フォルダ :web_basic/src/main/java
② パッケージ :ch05
③ 名前 :JapaneseServlet1
④ スーパークラス :jakarta.servlet.http.HttpServlet
⑤ アクセスURL :http://localhost:8080/web_basic/JapaneseServlet1

➢ JapaneseServlet1.java
[html] package ch05; import java.io.IOException; import java.io.PrintWriter; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @WebServlet("/JapaneseServlet1") public class JapaneseServlet1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); out.println("日本語を表示するServlet!"); } } [/html]

解説
 このサーブレットでは、「日本語を表示するservlet!」というメッセージを画面に出力する予定でしたが、日本語の部分が「譌・譛ャ隱槭r陦ィ遉コ縺吶k」と表示されてしまっています。このように、表示させようとした文字が別の文字として表示されてしまうことを「文字化け」と呼びます。今までのプログラムでは英文字しか表示しなかったので特に設定をしませんでしたが、ブラウザに日本語を正常に表示させるためには、「コンテンツタイプ」の設定を行い文字コードの指定をする必要があります。
 サーブレットでは、文字コードが設定されていない場合、デフォルト文字コードの「ISO-8859-1(Latin1)」が設定されているものとして画面の出力が行われます。「ISO-8859-1(Latin1)」は西欧系の言語ですので、日本語に対応していません。その結果、日本語の部分が「譌・譛ャ隱槭r陦ィ遉コ縺吶k」と表示されてしまいます。

図 5.1.2: 文字化けの流れ

5.1.2 コンテンツタイプとは

 コンテンツタイプとは、Webブラウザ側に返すファイルやデータの種類を指定する設定です。
 Webブラウザからのリクエストの結果として返すファイルの種類をコンテンツタイプに設定することで、ファイルの種類をWebブラウザ側が知ることができます。そして、その種類に応じて、画面にそのまま表示したり、ファイルとして保存したり、他のアプリケーションを起動して表示したりと、動きを変えることができるのです。
 コンテンツタイプは、以下の書式でサーブレット内の処理の初めに定義します。

 このコンテンツタイプを設定するsetContentType()メソッドの引数には「MIMEタイプ」と「文字エンコーディング」を指定することができます。

コンテンツタイプの別の書き方

 本テキストではsetContentType()メソッドにMIMEタイプと文字エンコーディングを一緒に指定していますが、別々に記述することも可能です。その場合は、setContentType()メソッドの他に、setCharacterEncoding()メソッドもあわせて記述します。

MIMEタイプ
 MIMEタイプとは、インターネット上でのデータの種類のことを表すもので、主なMIMEタイプには以下通りです。

表 5.1.1

文字エンコーディング
 文字エンコーディングとは、ブラウザに表示する文字のエンコードの種類のことです。
 サーブレットからブラウザに文字列を送る場合、Webサーバでエンコード(符号化)と呼ばれる処理が行われ、データがブラウザに送られます。また、ブラウザではデコード(復号化)と呼ばれる処理を行い画面に表示します。

 ・ エンコード:文字列を指定された文字コードのデータに変換する。
 ・ デコード:文字コードのデータを元の文字列に変換する。

 このエンコードとデコードの処理は次の図のような流れで行われます。

図 5.1.3: エンコードとデコードの流れ

 日本語を扱う場合、指定された文字セットが日本語に対応していないと、デコードの処理で問題が発生し、文字化けの原因となります。
 主な文字エンコーディングには以下のようなものがありますので覚えておきましょう。

表 5.1.2

日本語を正常に表示するプログラム

 このプログラムでは、前項で作成した文字化けを起こすプログラムに、コンテンツタイプを設定します。日本語が正しく表示されることを確認しましょう。

実行結果

アプリケーション構成

① ソース・フォルダ :web_basic/src/main/java
② パッケージ :ch05
③ 名前 :JapaneseServlet2
④ スーパークラス :jakarta.servlet.http.HttpServlet
⑤ アクセスURL :http://localhost:8080/web_basic/JapaneseServlet2

➢ JapaneseServlet2.java
[html] package ch05; import java.io.IOException; import java.io.PrintWriter; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @WebServlet("/JapaneseServlet2") public class JapaneseServlet2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //コンテンツタイプの指定 response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("日本語を表示するServlet!"); } } [/html]

解説
 このサーブレットは「JapaneseServlet1」に18行目の記述を追加したプログラムです。それ以外の処理については全く同じ内容です。
 18行目では、コンテンツタイプの指定を行っています。
   18:response.setContentType("text/html; charset=UTF-8");

 今回のプログラムでは以下のような設定を宣言しています。

 ・ MIMEタイプ:text/html
 ・ 文字エンコーディング:charset=UTF-8

 サーブレットは最終的にHTMLに変換されてブラウザに表示されるため、MIMEタイプは「text/html」となり、文字エンコーディングは日本語に対応した「charset=UTF-8」を設定しています。
 実行結果からもわかるように、コンテンツタイプに日本語に対応した文字エンコーディングを記述したことで、「譌・譛ャ隱槭r陦ィ遉コ縺吶k」と表示されていた日本語部分が正しく表示されるようになりました。
 コンテンツタイプの指定はそのファイル全体の設定となるので、他の処理が行われる前の処理の一番初めに定義するようにしましょう。

5.1.3 Filterの設定

 1つのWebプロジェクトについて、まとめて文字エンコーディングを設定したい場合は、フィルター処理を行うクラスを用意します。

フィルター処理を行うプログラム

 このプログラムでは、プロジェクト全体にコンテンツタイプを設定します。これにより、先程は文字化けしたJapaneseServlet1も文字化けせず、日本語が正しく表示されるようになります。

実行結果

上記のようなフィルター処理を行うクラスの作成手順は、以下の通りとなります。

Step1:フィルターファイルの準備
Step2:フィルターファイルへの記述
Step3:プログラムの実行

アプリケーション構成

 Step1:フィルターファイルの準備

 フィルターとなるJavaファイルは「src/main/java」配下に格納します。今回は先程作った「ch05」フォルダ内に配置します。通常のJavaファイルの作成方法とは少し異なる点がありますので、以下の手順を参考にして、「ProjectFilter.java」ファイルを作成してください。

 ① ブレークポイントを設定するサーブレットを開く
 「web_basic」プロジェクトを右クリック > 新規 > クラス を選択すると作成ウィザードが起動します。このウィザードの起動は通常のJavaクラスの作成と変わりません。

図 5.1.4: 新規Javaクラス作成ウィザードの起動

 ② 新規Javaクラスの作成
 表示された新規Javaクラス作成ウィザードの各項目に、次の①から③の設定を行い、「完了」ボタンを押下します。パッケージ・エクスプローラ内にJavaファイルが増えれば作成成功です。

① パッケージ :ch05
② 名前 :ProjectFilter
③ インターフェース :jakarta.servlet.Filter

 通常のJavaクラスの作成と異なる点は、インターフェースの指定と、main()メソッドの作成の有無です。
 通常のJavaクラスではインターフェースを指定せずデフォルトのままで作成していましたが、フィルターの場合は、インターフェースに「jakarta.servlet.Filter」を指定します。また、サーブレットにはmain()メソッドが必要ないため、メソッド・スタブの選択項目は特に変更しません。

図 5.1.5: ProjectFilter.javaファイルの作成

 これでJavaファイルの作成は完了です。次のStepでは作成したJavaファイルにソースコードを記述します。

 Step2:フィルターファイルへの記述

 ① ソースコードの記述
作成したフィルターファイルの記述を変更していきます。デフォルトでは以下のような記述になっています。

➢ ProjectFilter.java
[html] package ch05; import java.io.IOException; import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; public class ProjectFilter implements Filter { @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { // TODO 自動生成されたメソッド・スタブ } } [/html]

こちらを、以下の内容に修正、書き換えます。

➢ ProjectFilter.java(書き換え後)
[html] package ch05; import java.io.IOException; import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.annotation.WebFilter; @WebFilter("/*") public class ProjectFilter implements Filter { //プロジェクトに適用する文字コード private String encodeCode = "UTF-8"; @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { //レスポンスで表示するデータのエンコード arg1.setContentType("text/html; charset=" + encodeCode); //フィルターを適用して画面表示 arg2.doFilter(arg0, arg1); } } [/html]

解説
 このフィルターファイルでは、プロジェクト全体に適用する文字コードを指定した上で、ユーザが入力したデータやこれから画面表示する文言に適用しています。
 12行目に追記した@WebFilterアノテーションで、作成したフィルターが適用される範囲を指定します。今回は「/*」と書かれているのでプロジェクト全体に適用されますが、@WebServletアノテーションのように特定のURLパターンを記載すれば、そのURLパターンにアクセスする時だけ適用させることもできます。
   12:@WebFilter("/*")

 15行目に追記したフィールド変数で、適用する文字コードを指定しています。
   15:private String encodeCode = "UTF-8";

 21行目では、プログラムが処理した結果を表示する際の文字コードを指定しています。その指定を踏まえて、24行目で後続の処理に進めています。
   21:arg1.setContentType("text/html; charset=" + encodeCode);
   24:arg2.doFilter(arg0, arg1);

 この設定によって、毎回文字コードの記述を書かなくても、文字化けを起こさずに済むようになります。


NEXT>> 5.2 MIMEタイプの違いによる出力の違いを確認しよう