web-dev-qa-db-ja.com

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

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

私の設定は次のとおりです。

  • 開発環境:ウィンドウズXP
  • 生産環境:Debian

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

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

これを達成する方法?

360
kosoant

このサイトのFAQとして自分自身を答えるのはそれを奨励します。これは私のために働く:

ブラウザやTomcat/JavaでWebアプリケーションに使用されるデフォルトの文字セットはlatin1なので、ほとんどの文字は問題ありません。それらの文字を「理解する」ISO-8859-1。

UTF-8をJava + Tomcat + Linux/Windows + Mysqlで動作させるには、以下が必要です。

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に設定されていることを確認します。

このフィルタによって行われる他のことは、デフォルトのレスポンスエンコーディングを設定することです。返されたHTML /に含まれるエンコーディング。代替案は、アプリケーションの各コントローラにレスポンスのエンコードなどを設定することです。

このフィルタは、 web.xml またはWebアプリケーションのデプロイメント記述子

 <!--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ページのエンコーディングをブラウザに指示します。

これは、Webアプリケーションによって生成された各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エンコーディングを使用するように定義する必要があります。これは 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 serveriも設定する必要があります。通常これは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

ブラウザが(リクエストヘッダとhtmlメタタグを含む)UTF-8エンコーディングでページを読むように指示されている場合、少なくとも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では性格 ä としてエンコードされます %E4page/request/everythingがUTF-8を使うように定義されていても。 äのUTF-8エンコードバージョンは %C3%A4

この結果、一部の文字はlatin1でエンコードされ、他の文字はUTF-8でエンコードされるので、WebアプリケーションがGETリクエストからのリクエストパラメータを正しく処理することはまったく不可能です。 Notice: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文字を使用した Basic Multilingual Plane をサポートします。それを避けたい場合(特定のアルファベットが3バイト以上のUTF-8を必要とする場合)、VARBINARYカラムタイプのフレーバーを使用するか、 utf8mb4文字セット ( MySQL 5.5.3以降が必要です。 MySQLでutf8文字セットを使用しても100%の時間ではうまくいかないことに注意してください。

TomcatとApache

もう1つあなたが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を追加してください。 注:最初に存在するかどうかを確認してください。もし存在すれば、この行でそれを更新することができます。この行を下に追加することもできます。
540
kosoant

私はあなたがそれをあなた自身の答えの中で非常にうまくまとめたと思います。

エンドツーエンドのUTF-8-ing(?)の過程では、Java自体がUTF-8を使用していることを確認することをお勧めします。 JVMへのパラメータとして-Dfile.encoding = utf-8を使用します(catalina.batで設定できます)。

12
stian

kosoant's answer を追加するには、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>
11
Raedwald

私はまたから追加したい ここ この部分は私のutf問題を解決しました:

runtime.encoding=<encoding>
2
John

詳細な回答です。 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
Jay

これは、MySqlテーブルにギリシャ語でエンコードするためのものです。Javaを使用してそれらにアクセスする場合は、次のようになります。

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

私とニックにとって、私達はそれを決して忘れず、もう時間を浪費しません.....

1
Mike Mountrakis

いつかMySQL管理者ウィザードを通して問題を解決することができます。に

起動変数>詳細設定>

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

たぶん、この設定はMySQLを再起動する必要があります。

0
user3600935

以前の回答は私の問題ではうまくいきませんでした。 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-)環境

lC_ALL = en_US.UTF-8をエクスポート
export LANG = en_US.UTF-8

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

0
Rogelio

Spring MVC 5 + Tomcat 9 + JSPで同じ問題に直面しました。
長い研究の末、洗練された解決策が生まれました(no need filters and no need changes = 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"%>を追加してくださいまたは web.xmlにjsp-config記述子を追加する

    <?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>
    
0
Andrei Veshtard

@kosoant answer ...に記載されているCharsetFilterについて.

Tomcatのweb.xmlconf/web.xmlにあります)のFilterにビルドがあります。フィルタはsetCharacterEncodingFilterという名前で、デフォルトでコメント化されています。あなたはこれのコメントを外すことができます(そのfilter-mappingもコメントを外すことを忘れないでください)

また、あなたのjsp-configweb.xmlを設定する必要はありません(私はそれをTomcat 7+でテストしました)

0
Alireza Fattahi

メッセージバンドルからUnicode文字を表示する私の場合は、私のjspページにUnicodeを表示するために "JSP page encoding"セクションを適用する必要はありません。必要なのは "CharsetFilter"セクションだけです。

0
bnguyen82

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

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

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

0
caarlos0

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

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

最近自分のAjaxをロールする人はほとんどいませんが、私もこれを追加することを考えました。

0
David