Java WebアプリケーションでUTF-8を機能させる方法は?


367

äöå通常のフィンランド語のテキストやЦжФ特殊なケースのようなキリル文字のアルファベットなどをサポートするために、Java Webアプリケーション(サーブレット+ JSP、フレームワークを使用しない)でUTF-8を機能させる必要があります。

私のセットアップは次のとおりです:

  • 開発環境:Windows XP
  • 実稼働環境:Debian

使用するデータベース:MySQL 5.x

ユーザーは主にFirefox2を使用していますが、サイトへのアクセスにはOpera 9.x、FF3、IE7、Google Chromeも使用されています。

これを達成する方法は?


回答:


552

このサイトのFAQとして自分に答えることが奨励します。これは私にとってはうまくいきます:

ブラウザやWebアプリケーションのtomcat / javaで使用されるデフォルトの文字セットはlatin1 ieであるため、ほとんどの場合、文字は問題ありません。それらの文字を「理解する」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エンコードとして処理することを保証します。その結果、ユーザーがブラウザのアドレスバーに次のように書き込むと、

 https://localhost:8443/ID/Users?action=search&name=*ж*

文字жはUTF-8として処理され、%D0%B6として(通常、サーバーに到達する前にブラウザーによって)エンコードされます。

POSTリクエストはこれによる影響を受けません。

CharsetFilter

次に、Java Webアプリケーションがすべての要求と応答を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に設定されていることを確認します。

このフィルタによって行われるもう1つのことは、デフォルトの応答エンコーディングを設定することです。返されたhtml /のエンコーディング。別の方法としては、アプリケーションの各コントローラーで応答エンコーディングなどを設定します。

このフィルターは、web.xmlまたはwebappのデプロイメント記述子に追加する必要があります。

 <!--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>

または、WebアプリケーションのすべてのJSPページの上部に次のものが必要です。

 <%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>

異なるJSPフラグメントを含むある種のレイアウトが使用される場合、これはそれらすべてで必要です。

HTMLメタタグ

JSPページのエンコーディングは、JSPページの文字を正しいエンコーディングで処理するようにJVMに指示します。次に、HTMLページのエンコーディングをブラウザに通知します。

これは、webappによって生成された各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接続

データベースを使用する場合、接続がUTF-8エンコーディングを使用することを定義する必要があります。これは、context.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設定することで、-fileをおよびLinuxでのmy.cnf -fileを。これらのファイルでは、サーバーに接続されているすべてのクライアントがデフォルトの文字セットとして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仕様は、デフォルトでは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としてエンコードされます。page / request / everythingはUTF-8を使用するように定義されていますが。äのUTF-8エンコードバージョンは%C3%A4です。

この結果、一部の文字はlatin1でエンコードされ、他の文字はUTF-8でエンコードされるため、webappがGETリクエストからのリクエストパラメーターを正しく処理することは不可能です。 通知:ページがUTF-8として定義されている場合、ブラウザーがフォームからのすべての要求パラメーターを完全にUTF-8でエンコードするため、POST要求は機能します

読むもの

私の問題の答えを提供してくれた次の作家にとても感謝しています:

  • 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/

重要な注意点

は、3バイトのUTF-8文字を使用した基本的な多言語プレーンをサポートしています。それ以外に移動する必要がある場合(特定のアルファベットには3バイトを超えるUTF-8が必要です)、VARBINARY列タイプのフレーバーを使用するか、またはutf8mb4文字セット(MySQL 5.5.3以降が必要)を使用する必要があります。utf8MySQLで文字セットを使用しても、100%動作しないことに注意してください。

Apacheを使用したTomcat

もう1つApache + Tomcat + mod_JKコネクタを使用している場合は、次の変更も行う必要があります。

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

これらの手順は、Struts /タイルとpostgresデータベースでも機能します。
kosoant 2008

17
2つのコメント:1)HMTL-metaタグに、xml宣言を含めました。それを削除してください。それはブラウザを互換モードでトリガーするだけであり、あなたはそれを望んでいません。また、HTMLメタタグは実際にはすでにJSPによって暗黙的に行われているpageEncodingため、そのままにしておくこともできます。2)あなたが使用したMySQLデータベースとテーブルでutf8_swedish_si、これはあったはずutf8_unicode_ciです。照合を省くこともできCHARACTER SET utf8ます。これで十分です。
BalusC、2009

私はHTMLメタタグに関する相談やモード(例えば癖文書のどちらericmeyeroncss.com/bonus/render-mode.htmlen.wikipedia.org/wiki/Quirks_modeを)<META HTTP-当量= 'コンテンツが存在することを示します-Type 'は、レンダリングモードに影響を与えます。
MarcelStör、2010年

興味深い補足として、リクエストパラメータにアクセスするリスナーがある場合、リスナーはフィルターの前に実行されるため、フィルターの代わりに文字セットを設定するリスナーを追加する必要があることにも注意してください。私はすべての手順を実行しましたが、これが原因でまだ機能しませんでした。他の誰かが同様の問題を抱えている場合に備えて、私がこの情報を渡すと思っていました。
testing123

3
## Apacheを使用したTomcat ##もう1つApache + Tomcat + mod_JKコネクタを使用している場合は、次の変更も行う必要があります。1. URIEncoding = "UTF-8"を8009コネクタのtomcat server.xmlファイルに追加します。 mod_JKコネクタによって使用されます。<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/> 2. Apacheフォルダー/etc/httpd/confに移動してAddDefaultCharset utf-8、「httpd.conf」ファイルを追加します。注:最初にそれが存在するかどうかを確認してください。存在する場合は、この行で更新できます。この行を下部に追加することもできます。
Vijay Shegokar、2014年

14

あなた自身の答えでそれをかなりよくまとめたと思います。

エンドツーエンドのUTF-8-ing(?)のプロセスでは、Java自体がUTF-8を使用していることを確認することもできます。-Dfile.encoding = utf-8をJVMのパラメーターとして使用します(catalina.batで構成できます)。


これは私を助け、私は言及したすべてを行いましたが、JVMエンコーディングはWindows-1250でしたが、UTF-8に変更するとすぐに問題なく動作しました。
coding_idiot

2
それをCatalina.batファイルのどこに追加しますか?
ノア

11

kosoantの回答に追加するには、独自のサーブレットフィルターを作成するのではなく、Springを使用している場合、org.springframework.web.filter.CharacterEncodingFilterそれらが提供するクラスを使用して、web.xmlで次のように構成します。

 <filter>
    <filter-name>encoding-filter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
       <param-name>encoding</param-name>
       <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
       <param-name>forceEncoding</param-name>
       <param-value>FALSE</param-value>
    </init-param>
 </filter>
 <filter-mapping>
    <filter-name>encoding-filter</filter-name>
    <url-pattern>/*</url-pattern>
 </filter-mapping>

1
このフィルターは、web.xmlの最初のフィルターである必要があります
olyanren


1

これは、Javaを使用してアクセスしたいMySqlテーブルのギリシャエンコーディング用です。

JBoss接続プール(mysql-ds.xml)で次の接続設定を使用します

<connection-url>jdbc:mysql://192.168.10.123:3308/mydatabase</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>nts</user-name>
<password>xaxaxa!</password>
<connection-property name="useUnicode">true</connection-property>
<connection-property name="characterEncoding">greek</connection-property>

これをJNDI接続プールに入れたくない場合は、次の行に示すように、JDBC URLとして構成できます。

jdbc:mysql://192.168.10.123:3308/mydatabase?characterEncoding=greek

私とニックにとって、私たちはそれを決して忘れず、もう時間を無駄にしています。


5
私はまだギリシャ語よりもUTF-8を好みます(そして現在のギリシャ語のデータをUTF-8に変換します)ので、アプリケーションは世界を支配する準備ができています。
BalusC、2009

1

素敵な詳細な答え。他の人が実際にURLのUTF-8エンコーディングを確認するのに役立つもう1つのことを追加したかっただけです。

以下の手順に従って、FirefoxのURLでUTF-8エンコーディングを有効にします。

  1. アドレスバーに「about:config」と入力します。

  2. フィルター入力タイプを使用して、「network.standard-url.encode-query-utf8」プロパティーを検索します。

  3. 上記のプロパティはデフォルトでfalseになります。TRUEに設定してください。
  4. ブラウザを再起動します。

URLのUTF-8エンコーディングは、IE6 / 7/8およびChromeでデフォルトで機能します。


1

以前の応答は私の問題では機能しませんでした。tomcatとapache mod_proxy_ajpを使用して、本番環境でのみ使用できました。投稿の本文で非ASCII文字が失われましたか?最終的に問題はJVM defaultCharset(デフォルトのインスタレーションのUS-ASCII:Charset dfset = Charset.defaultCharset();)にあったため、解決策は、デフォルト文字セットとしてUTF-8でJVMを実行する修飾子を付けてtomcatサーバーを実行しました。

JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8" 

(この行をcatalina.shに追加して、tomcatを再起動します)

たぶん、Linuxシステム変数も変更する必要があります(永続的な変更のために〜/ .bashrcと〜/ .profileを編集してください。https: //perlgeek.de/en/article/set-up-a-clean-utf8-environmentを参照してください

LC_ALL = en_US.UTF-8をエクスポートします
エクスポートLANG = en_US.UTF-8

LANGUAGE = en_US.UTF-8をエクスポート


0

私は同様の問題を抱えていますが、ファイルのファイル名では、Apache Commonsで圧縮しています。だから、私はこのコマンドでそれを解決しました:

convmv --notest -f cp1252 -t utf8 * -r

それは私にとって非常にうまく機能します。それが誰にも役立つことを願っています;)


0

メッセージバンドルのUnicode文字を表示する場合、JSPページにUnicodeを表示するために「JSPページエンコーディング」セクションを適用する必要はありません。「CharsetFilter」セクションだけが必要です。


0

言及されていないもう1つの点は、Ajaxで動作するJavaサーブレットに関連しています。Webページが、サーブレットから送信されたURIに含まれているJavaScriptファイルに送信したユーザーからのutf-8テキストを取得している状況があります。サーブレットはデータベースをクエリし、結果をキャプチャしてXMLとしてJavaScriptファイルに返します。JavaScriptファイルはそれをフォーマットし、フォーマットされた応答を元のWebページに挿入します。

あるWebアプリでは、URIを構築する際にJavaScriptをラップするための初期のAjaxブックの指示に従っていました。本の例では、(難しい方法で)私が発見したescape()メソッドが間違っています。utf-8の場合は、encodeURIComponent()を使用する必要があります。

最近、自分のAjaxを使用する人はほとんどいないようですが、これを追加した方がいいと思いました。


0

CharsetFilter@kosoant回答で言及されていることについて....

Filtertomcat web.xml(にありますconf/web.xml)にビルドインがあります。フィルターには名前が付けられsetCharacterEncodingFilter、デフォルトでコメント化されています。これをコメント解除できます(コメント解除filter-mappingも忘れないでください)

またjsp-config、あなたに設定する必要はありませんweb.xml(私はTomcat 7+用にテストしています)


0

MySQL Administratorウィザードを使用して問題を解決できる場合があります。に

スタートアップ変数>詳細>

そしてDefを設定します。文字セット:utf8

多分この設定はMySQLを再起動する必要があります。


0

Spring MVC 5 + Tomcat 9 + JSPで同じ問題に直面しました。
長い研究の後、エレガントなソリューション(に来ていない必要性のフィルターなし必要性の変化のTomcatでのserver.xml(8.0.0-RC3版から始まります))

  1. WebMvcConfigurer実装で、messageSourceのデフォルトエンコーディングを設定します(UTF-8エンコーディングでメッセージソースファイルからデータを読み取るため)。

    @Configuration
    @EnableWebMvc
    @ComponentScan("{package.with.components}")
    public class WebApplicationContextConfig implements WebMvcConfigurer {
    
        @Bean
        public MessageSource messageSource() {
            final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    
            messageSource.setBasenames("messages");
            messageSource.setDefaultEncoding("UTF-8");
    
            return messageSource;
        }
    
        /* other beans and methods */
    
    }
  2. DispatcherServletInitializer実装では、onStartupメソッドを@Overrideし、リクエストとリソースの文字エンコーディングを設定します。

    public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
        @Override
        public void onStartup(final ServletContext servletContext) throws ServletException {
    
            // https://wiki.apache.org/tomcat/FAQ/CharacterEncoding
            servletContext.setRequestCharacterEncoding("UTF-8");
            servletContext.setResponseCharacterEncoding("UTF-8");
    
            super.onStartup(servletContext);
        }
    
        /* servlet mappings, root and web application configs, other methods */
    
    }
  3. すべてのメッセージソースとビューファイルをUTF-8エンコーディングで保存します。

  4. 各* .jspファイルに<%@ page contentType = "text / html; charset = UTF-8"%> または <%@ page pageEncoding = "UTF-8"%>を追加する、jsp-config記述子をweb.xmlに追加します

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
     id="WebApp_ID" version="3.0">
        <display-name>AppName</display-name>
    
        <jsp-config>
            <jsp-property-group>
                <url-pattern>*.jsp</url-pattern>
                <page-encoding>UTF-8</page-encoding>
            </jsp-property-group>
        </jsp-config>
    </web-app>

-1

接続プール(mysql-ds.xml)で指定した場合、Javaコードで次のように接続を開くことができます。

DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Connection conn = DriverManager.getConnection(
    "jdbc:mysql://192.168.1.12:3308/mydb?characterEncoding=greek",
    "Myuser", "mypass");
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.