[解決済み] Java の Webapps で UTF-8 を動作させるには?
質問
Java のウェブアプリケーション(サーブレット+JSP、フレームワークは使用しない)で UTF-8 を動作させ、次のことをサポートする必要があります。
äöå
など、通常のフィンランド語のテキストとキリル文字のアルファベットに対応します。
ЦжФ
は、特殊なケースを想定しています。
私の設定は以下の通りです。
- 開発環境 Windows XP
- 本番環境 Debian
使用するデータベース MySQL 5.x
Firefox2を中心に、Opera 9.x、FF3、IE7、Google Chromeでもアクセスされています。
どうすれば実現できるのか?
どのように解決するのですか?
このサイトのFAQにあるように、自分で回答することをお勧めします。これは私のために動作します。
ブラウザやtomcat/javaのデフォルトの文字セットはlatin1、つまりISO-8859-1であり、これらの文字を理解することができます。
Java+Tomcat+Linux/Windows+MysqlでUTF-8を動作させるためには、以下のことが必要です。
Tomcatのserver.xmlの設定
コネクターがurl(GETリクエスト)パラメータのエンコードにUTF-8を使用するように設定する必要があります。
<Connector port="8080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true"
compression="on"
compressionMinSize="128"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/ javascript,application/x-javascript,application/javascript"
URIEncoding="UTF-8"
/>
重要なのは URIEncoding="UTF-8"。 を使用すると、上記の例のようになります。これは、Tomcatが受信するすべてのGETパラメータをUTF-8エンコードとして処理することを保証するものです。 その結果、ユーザがブラウザのアドレス・バーに次のように書き込むと、UTF-8エンコードされたパラメータが返ってきます。
https://localhost:8443/ID/Users?action=search&name=*ж*
の場合、文字 ж は UTF-8 として扱われ、(通常はサーバーに届く前にブラウザによって)次のようにエンコードされます。 %D0%B6 .
POSTリクエストはこの影響を受けません。
チャーセットフィルタ(CharsetFilter
次に、JavaウェブアプリケーションがすべてのリクエストとレスポンスをUTF-8でエンコードして処理するように強制する番です。そのためには、以下のような文字セットフィルタを定義する必要があります。
package fi.foo.filters;
import javax.servlet.*;
import java.io.IOException;
public class CharsetFilter implements Filter {
private String encoding;
public void init(FilterConfig config) throws ServletException {
encoding = config.getInitParameter("requestEncoding");
if (encoding == null) encoding = "UTF-8";
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain next)
throws IOException, ServletException {
// Respect the client-specified character encoding
// (see HTTP specification section 3.4.1)
if (null == request.getCharacterEncoding()) {
request.setCharacterEncoding(encoding);
}
// Set the default response content type and encoding
response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding("UTF-8");
next.doFilter(request, response);
}
public void destroy() {
}
}
このフィルタは、ブラウザがリクエストで使われるエンコーディングを設定していない場合、それがUTF-8に設定されることを確認します。
このフィルタが行うもうひとつのことは、デフォルトのレスポンスエンコーディング、 すなわち、返される html やその他のもののエンコーディングを設定することです。アプリケーションの各コントローラでレスポンスエンコーディングなどを設定することもできます。
このフィルタは web.xml またはウェブアプリのデプロイメントディスクリプタを使用します。
<!--CharsetFilter start-->
<filter>
<filter-name>CharsetFilter</filter-name>
<filter-class>fi.foo.filters.CharsetFilter</filter-class>
<init-param>
<param-name>requestEncoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharsetFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
このフィルタの作り方は tomcat wiki ( http://wiki.apache.org/tomcat/Tomcat/UTF-8 )
JSPページのエンコーディング
あなたの web.xml に、以下を追加してください。
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
あるいは、ウェブアプリケーションのすべてのJSP-pageの先頭に、次のように記述する必要があります。
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
異なるJSP-フラグメントによる何らかのレイアウトが使用されている場合、これは すべて を使用します。
HTML-metaタグ
JSPページのエンコーディングは、JVMにJSPページ内の文字を正しいエンコーディングで処理するように指示します。 次に、htmlページがどのエンコーディングであるかをブラウザに伝えることになります。
これは、ウェブアプリが生成する各xhtmlページの先頭に次のように記述することで実現します。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fi">
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
...
JDBC-コネクション
dbを使用する場合、接続にUTF-8エンコーディングを使用するよう定義する必要があります。これは コンテキスト.xml またはJDBC接続が定義されている場所で、次のようにします。
<Resource name="jdbc/AppDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="20" maxIdle="10" maxWait="10000"
username="foo"
password="bar"
driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/ ID_development?useEncoding=true&characterEncoding=UTF-8"
/>
MySQLデータベースとテーブル
使用するデータベースは、UTF-8エンコードを使用する必要があります。これは、以下のようにデータベースを作成することで実現します。
CREATE DATABASE `ID_development`
/*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_swedish_ci */;
それから、すべてのテーブルもUTF-8である必要があります。
CREATE TABLE `Users` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(30) collate utf8_swedish_ci default NULL
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci ROW_FORMAT=DYNAMIC;
重要なのは CHARSET=utf8 .
MySQLサーバーの設定
MySQL サーバーも設定する必要があります。通常、Windows では、この設定は my.ini -ファイル、Linux では my.cnf -ファイルを作成します。 これらのファイルでは、サーバーに接続するすべてのクライアントがデフォルトの文字セットとしてutf8を使用し、サーバーが使用するデフォルトの文字セットもutf8であることが定義されている必要があります。
[client]
port=3306
default-character-set=utf8
[mysql]
default-character-set=utf8
Mysqlのプロシージャと関数
これらは、文字セットも定義されている必要があります。例えば
DELIMITER $$
DROP FUNCTION IF EXISTS `pathToNode` $$
CREATE FUNCTION `pathToNode` (ryhma_id INT) RETURNS TEXT CHARACTER SET utf8
READS SQL DATA
BEGIN
DECLARE path VARCHAR(255) CHARACTER SET utf8;
SET path = NULL;
...
RETURN path;
END $$
DELIMITER ;
GETリクエスト:latin1およびUTF-8
tomcatのserver.xmlでGETリクエストのパラメータをUTF-8でエンコードするように定義されている場合、以下のGETリクエストは正しく処理されます。
https://localhost:8443/ID/Users?action=search&name=Petteri
https://localhost:8443/ID/Users?action=search&name=ж
ASCII文字はlatin1でもUTF-8でも同じようにエンコードされるため、文字列 "Petteri"は正しく処理されます。
キリル文字のжはlatin1では全く理解されません。Tomcatはリクエスト・パラメータをUTF-8で処理するように指示されているので、この文字を次のように正しくエンコードします。 D0%B6 .
もし、ブラウザがUTF-8エンコーディングでページを読むように指示された場合(リクエストヘッダやhtmlメタタグを含む)、少なくともFirefox 2/3やこの時期の他のブラウザはすべて、この文字そのものを %D0%B6 .
最終的には、名前 "Petteri" を持つすべてのユーザーが見つかり、また名前 "ж" を持つすべてのユーザーも見つかります。
しかし、äåöはどうでしょうか?
HTTP-specificationでは、デフォルトでURLはlatin1としてエンコードされることが定義されています。このため、firefox2、firefox3 などでは、以下のようにエンコードされます。
https://localhost:8443/ID/Users?action=search&name=*Päivi*
をエンコードしたバージョンに
https://localhost:8443/ID/Users?action=search&name=*P%E4ivi*
latin1 では、文字 ä は次のようにエンコードされます。 %E4 . ページ/リクエスト/エブリシングがUTF-8を使用するように定義されているにもかかわらず . äのUTF-8エンコードされたバージョンは %C3%A4
この結果、ある文字はlatin1で、他の文字はUTF-8でエンコードされているため、WebアプリケーションがGETリクエストのリクエストパラメータを正しく処理することは非常に不可能です。 お知らせ POSTリクエストは、ページがUTF-8と定義されている場合、ブラウザがフォームからのすべてのリクエストパラメータを完全にUTF-8でエンコードするため、動作します。
読むべきもの
私の問題を解決してくれた以下の作家の方々に、心から感謝します。
- http://tagunov.tripod.com/i18n/i18n.html
- http://wiki.apache.org/tomcat/Tomcat/UTF-8
- http://java.sun.com/developer/technicalArticles/Intl/HTTPCharset/
- http://dev.mysql.com/doc/refman/5.0/en/charset-syntax.html
- http://cagan327.blogspot.com/2006/05/utf-8-encoding-fix-tomcat-jsp-etc.html
- http://cagan327.blogspot.com/2006/05/utf-8-encoding-fix-for-mysql-tomcat.html
- http://jeppesn.dk/utf-8.html
- http://www.nabble.com/request-parameters-mishandle-utf-8-encoding-td18720039.html
- http://www.utoronto.ca/webdocs/HTMLdocs/NewHTML/iso_table.html
- http://www.utf8-chartable.de/
重要なお知らせ
mysql
がサポートしています。
基本多言語面
3バイトのUTF-8文字を使っています。もし、それ以外の文字が必要な場合(あるアルファベットは3バイト以上のUTF-8を必要とします)には、以下のいずれかのフレーバーを使用する必要があります。
VARBINARY
カラムタイプを使用するか
utf8mb4
文字セット
(MySQL 5.5.3 以降が必要)。ただし
utf8
の文字セットは、MySQLで100%動作するわけではありません。
TomcatとApacheの連携
もう一つ、Apache + Tomcat + mod_JK コネクタを使用している場合、以下の変更も必要です。
-
8009 コネクタの tomcat server.xml ファイルに URIEncoding="UTF-8" を追加します(mod_JK コネクタで使用されます)。
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
-
apacheフォルダに移動します。
/etc/httpd/conf
を追加しAddDefaultCharset utf-8
でhttpd.conf file
. 注 まず、それが存在するかどうかを確認します。存在する場合は、この行で更新することができます。また、この行を最下部に追加することもできます。
関連
-
Error: java.lang.NoClassDefFoundError: クラス XXXX を初期化できませんでした
-
Maven Pluginの実行がライフサイクル設定の対象外であるエラーの解決
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] JavaでNullPointerExceptionを回避する方法
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] JavaでStringをintに変換するにはどうしたらいいですか?
-
[解決済み] Javaで文字列値からenum値を取得する方法
-
[解決済み】Javaではfinallyブロックは必ず実行されるのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
エラー java.util.NoSuchElementException
-
プロジェクトの依存関係を解決できなかった 解決
-
eclipse の実行時に java 仮想マシンが見つからなかった
-
Methodのinvokeメソッド実装のJavaリフレクション
-
xxx:jarのアーティファクトディスクリプタの読み込みに失敗した問題は解決しました。
-
Javaエラーメッセージがenclosingクラスでない
-
org.glassfish.jersey.servlet.ServletContainer
-
起動時にEclipseエラーが発生しました。起動中に内部エラーが発生しました。java.lang.NullPoin: "Javaツーリングの初期化 "中に内部エラーが発生しました。
-
このラインで複数のマーカーを解決する方法
-
コミットには何も追加されないが、未追跡のファイルが存在し、gitで未追跡のファイルに対する完璧な解決策