1. ホーム
  2. java

[解決済み] Java の Webapps で UTF-8 を動作させるには?

2022-03-14 01:45:30

質問

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&amp;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 コネクタを使用している場合、以下の変更も必要です。

  1. 8009 コネクタの tomcat server.xml ファイルに URIEncoding="UTF-8" を追加します(mod_JK コネクタで使用されます)。 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
  2. apacheフォルダに移動します。 /etc/httpd/conf を追加し AddDefaultCharset utf-8httpd.conf file . まず、それが存在するかどうかを確認します。存在する場合は、この行で更新することができます。また、この行を最下部に追加することもできます。