サーブレットでの日本語表示・入力

サーブレットとブラウザ間の文字の入出力にはdoGetメソッド、doPostメソッドを使いますが、どのようにこれらを使うか、については多くの情報が検索できますし、書物でも解説されています。
しかし、入出力時の文字コードを適切に設定しないと日本語を扱う場合に文字化けが起こり、情報も少ないため、この解消には苦労をします。
そこで、なぜ文字化けが起こるのかを推測を含め整理します。

まず、HTMLの文字コードは以下の順で処理されます。
1. HTTPヘッダのContent‒Typeのcharsetの値
2. HTML内のMETAタグのContent‒Typeのcharsetの値
しかし、サーブレットコンテナは指定がない限りContent‒Typeのcharsetをデフォルトの文字コードに設定するのでサーブレットの中のmetaタグ指定は無視されます。tomcatの場合デフォルトの文字コードはISO-8859-1(アルファベット)なので日本語は文字が化けることになります。
そこで、文字コードをHTTPヘッダのContent‒Typeで指定する必要があります。

日本語の表示の場合は、データがブラウザに返される前にHttpServletResponseインタフェースのsetContentTypeメソッドで日本語の文字コードを設定します。

public class MySecondServlet extends HttpServlet {
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		resp.setContentType("text/html; charset=Windows-31J");
(以下省略)

つぎに日本語の入力の場合は、これとは別にHttpServletRequestインタフェースのsetCharacterEncodingメソッドで指定します。

		req.setCharacterEncoding("Windows-31J");

これで入力も正しく処理されるはずなのですが、doPostメソッドは良いのですが、doGetメソッドの場合は文字化けが治りません。
調べたところ、「Tomcat5.xよりFORMのGETメソッドでパラメータを送信した場合、setCharacterEncodingメソッドを無視するようになった。」という情報があり、その解消のためには「(tomcatのconfフォルダー内の)server.xmlファイルのタグのuseBodyEncodingForURI属性をtrueに指定する」必要があるとの事で、タグを以下のように修正しました。。

<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
useBodyEncodingForURI="true" />

ところが、これだけではdoGetメソッドの文字化けは解消ぜず、文字コードの指定をUTF-8に変更して日本語を正しく入力できるようになりました。

public void doGet(HttpServletRequest req, HttpServletResponse resp)
		throws ServletException, IOException {
//	req.setCharacterEncoding("Windows-31J");
//	resp.setContentType("text/html; charset=Windows-31J");
	req.setCharacterEncoding("UTF-8");
	resp.setContentType("text/html; charset=UTF-8");

この原因はdoGetメソッドがURLパラメータで情報を受取るため、内部処理が全てUTF-8のサーブレットが情報をWindows-31Jで受取り文字化けを起こしている、のではないかと推測されます。
一方、doPostメソッドの場合には情報はフォームを使って送られるのでメソッドの中でWindows-31JをUTF-8に変換しているため、指定する文字コードがWindows-31Jでないと文字化けを起こす、と推定されます。

public void doPost(HttpServletRequest req, HttpServletResponse resp)
		throws ServletException, IOException {
	req.setCharacterEncoding("Windows-31J");
	resp.setContentType("text/html; charset=Windows-31J");
//	req.setCharacterEncoding("UTF-8");
//	resp.setContentType("text/html; charset=UTF-8");
カテゴリー: JSP_Servlet パーマリンク