<?xml version="1.0" encoding="EUC-JP"?>

<topic name="ServletRequest / ServletResponse の文字エンコーディング" author="小川 環" date="2002.07.27">
<subsection name="概要">
<p>
i18n タグを実行すると、ServletRequest もしくは ServletResponse の文字エンコーディングが設定されます。
<blockquote>
<table>
<tr>
<th></th>
<th>文字エンコーディングをセットするメソッド</th>
</tr>
<tr>
<td>ServletRequest</td>
<td>setCharacterEncoding()</td>
</tr>
<tr>
<td>ServletResponse</td>
<td>setLocale()</td>
</tr>
</table>
</blockquote>
このことをしっかり把握しておかないと、<b><u>予期せぬ文字化け表示</u></b>を引き起こしてしまうことがあります。
たいへん便利なタグではありますが、使い方には少し注意しないといけません。<br/>
そこで、ServletRequest / ServletResponse の文字エンコーディングの設定処理に関する簡単な表を、以下に示しておきます。
大事なポイントは、i18n タグの実行時に、文字エンコーディングがどのように決定されていくかということです。
<blockquote>
<table width="75%">
<tr>
<th>タグ名称</th>
<th>ServletRequest<br/>文字エンコーディング</th>
<th>ServletResponse<br/>文字エンコーディング</th>
</tr>
<tr>
<td align="center">&lt;fmt:setLocale&gt;</td>
<td align="center"> -- </td>
<td align="center">(2)</td>
</tr>
<tr>
<td align="center">&lt;fmt:bundle&gt;</td>
<td align="center"> -- </td>
<td align="center">(3) or (4)</td>
</tr>
<tr>
<td align="center">&lt;fmt:setBundle&gt;</td>
<td align="center"> -- </td>
<td align="center">(3) or (4)</td>
</tr>
<tr>
<td align="center">&lt;fmt:message&gt;</td>
<td align="center"> -- </td>
<td align="center">(3) or (4)</td>
</tr>
<tr>
<td align="center">&lt;fmt:requestEncoding&gt;</td>
<td align="center">(1)</td>
<td align="center"> -- </td>
</tr>
<tr>
<td align="center">&lt;fmt:timeZone&gt;</td>
<td align="center"> -- </td>
<td align="center"> -- </td>
</tr>
<tr>
<td align="center">&lt;fmt:setTimeZone&gt;</td>
<td align="center"> -- </td>
<td align="center"> -- </td>
</tr>
<tr>
<td align="center">&lt;fmt:formatNumber&gt;</td>
<td align="center"> -- </td>
<td align="center">(3) or (4)</td>
</tr>
<tr>
<td align="center">&lt;fmt:parseNumber&gt;</td>
<td align="center"> -- </td>
<td align="center">(3) or (4)</td>
</tr>
<tr>
<td align="center">&lt;fmt:formatDate&gt;</td>
<td align="center"> -- </td>
<td align="center">(3) or (4)</td>
</tr>
<tr>
<td align="center">&lt;fmt:parseDate&gt;</td>
<td align="center"> -- </td>
<td align="center">(3) or (4)</td>
</tr>
<tr>
<td align="right" colspan="3">
<font size="-1">
&quot;--&quot; = 文字エンコーディングの設定を行わない<br/>
(1) = 指定した文字エンコーディングをセットする<br/>
(2) = 指定した地域に対応する文字エンコーディングをセットする<br/>
(3) = ブラウザの設定地域に対応する文字エンコーディングをセットする<br/>
(4) = &lt;fmt:setLocale&gt;で指定された地域に対応する文字エンコーディングをセットする<br/>
</font>
</td>
</tr>
</table>
<note>
JspWriter オブジェクトに対して、十分なバッファが確保されていることを前提とします。
</note>
<note>
指定した地域に対して ServletResponse に設定される文字エンコーディング名は、<br/>
すべての Servlet コンテナで一定にマッピングされているとは限りません。
</note>
</blockquote>
</p>
</subsection>
<subsection name="文字化け対策１　リソースバンドルをフル活用する">
<p>
<u>ページ中のタイトル、キャプション、メッセージなどは、<b>&lt;fmt:message&gt;</b> タグを使って必ず表示させるようにし、特定の地域でしか取り扱えない文字をハードコーディングすることは基本的に避けましょう。</u><br/><br/>
<subsection name="文字化け表示を誘発してしまうサンプルコード">
<source>
<![CDATA[
<%@ page language="java" pageEncoding="Shift_JIS" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>

<%-- メッセージ・リソースの登録 --%>
<fmt:setBundle basename="sample.Resources" var="message"/>

<html>
<head>
<title>i18n タグのサンプル</title>
</head>
<body>
<h2>メッセージ</h2>
<fmt:message key="sample" bundle="${message}"/>
</body>
</html>
]]></source>
日本語 ( ja, ja-JP, etc. ) 以外の設定地域で要求すると、<br/>タイトル ( &lt;title&gt; ) やキャプション ( &lt;h2&gt; ) のテキストが化けて表示される。
</subsection>
<subsection name="リソースバンドルをフル活用した、模範的なサンプルコード">
<source>
<![CDATA[
<%@ page language="java" pageEncoding="Shift_JIS" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>

<%-- メッセージ・リソースの登録 --%>
<fmt:setBundle basename="sample.Resources" var="message"/>

<html>
<head>
<title><fmt:message key="title" bundle="${message}"/></title>
</head>
<body>
<h2><fmt:message key="caption" bundle="${message}"/></h2>
<fmt:message key="sample" bundle="${message}"/>
</body>
</html>
]]></source>
日本語 ( ja, ja-JP, etc. ) 以外の設定地域で要求しても、<br/>タイトルやキャプションを含めたメッセージ表示の文字化けを確実に防ぐことができる。
</subsection>
また、<b>&lt;fmt:message&gt;</b> に必要な <b>ResouceBundle</b> のカスタマイズにおいては、その表示対象となる地域を明確にしておくことも大切です。
例えば、サーバ内の専用エラーメッセージとクライアントの入力エラーメッセージの定義を、１つのメッセージ・リソースへまとめるようにしないといったことです。
</p>
</subsection>
<subsection name="文字化け対策２　異なる地域同士のコンテンツを１つのJSPページに混在させない">
<p>
<u>１つの JSP ページで、ServletResponse の文字エンコーディングが異なる地域同士のコンテンツを混在させるのは望ましくありません。</u>
そういう意味で、&quot;standard-examples&quot; ( Standard Taglib v1.0 付属の例題アプリケーション ) に含まれる FormatNumber.jsp は模範的なサンプルであると、ちょっと言い難いかもしれません。
<note>
Jakarta Taglibs のほうでも FormatNumber.jsp の問題点を十分把握しており、<br/>
Standard Taglib の次回リリース ( v1.0.1 ) にて、その代わりとなる例題が提供されています。
</note>
</p>
</subsection>
<subsection name="文字化け対策３　&lt;meta&gt;タグを使ってコンテンツ・タイプを設定しない">
<p>
i18n タグの実行時に ServletResponse の文字エンコーディングが Servlet コンテナによって動的に決定されることを考慮すると、下に示す１行を HTML 中に含めることは望ましくありませんので、注意が必要です。<br/>
<pre> <![CDATA[ <meta http-equiv="Content-Type" content="text/html; charset=..."> ]]></pre>
動的なコンテンツにおいては、文字化け対策としてよく用いられている &lt;meta&gt;タグを使ってコンテンツ・タイプを設定することを絶対に避けるべきです。
</p>
</subsection>
</topic>
