サーブレットとブラウザ間の文字の入出力には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メソッドで日本語の文字コードを設定します。
1 2 3 4 5 | public class MySecondServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType( "text/html; charset=Windows-31J" ); (以下省略) |
つぎに日本語の入力の場合は、これとは別にHttpServletRequestインタフェースのsetCharacterEncodingメソッドで指定します。
1 | req.setCharacterEncoding( "Windows-31J" ); |
これで入力も正しく処理されるはずなのですが、doPostメソッドは良いのですが、doGetメソッドの場合は文字化けが治りません。
調べたところ、「Tomcat5.xよりFORMのGETメソッドでパラメータを送信した場合、setCharacterEncodingメソッドを無視するようになった。」という情報があり、その解消のためには「(tomcatのconfフォルダー内の)server.xmlファイルの
1 2 3 4 | < Connector port = "8080" protocol = "HTTP/1.1" connectionTimeout = "20000" redirectPort = "8443" useBodyEncodingForURI = "true" /> |
ところが、これだけではdoGetメソッドの文字化けは解消ぜず、文字コードの指定をUTF-8に変更して日本語を正しく入力できるようになりました。
1 2 3 4 5 6 | 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でないと文字化けを起こす、と推定されます。
1 2 3 4 5 6 | 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"); |