Jak uruchomić UTF-8 W Java webapps?

Muszę uruchomić UTF-8 w mojej Java webapp (servlets + JSP, nie używany framework) do obsługi äöå itp. dla zwykłego fińskiego tekstu i alfabetów cyrylicy, takich jak ЦжФ dla szczególnych przypadków.

Moja konfiguracja jest następująca:

  • środowisko programistyczne: Windows XP
  • środowisko produkcyjne: Debian

Używana baza danych: MySQL 5.x

Użytkownicy używają głównie Firefox2, ale także opery 9.x, FF3, IE7 i Google Chrome są używane do uzyskania dostępu do witryny.

Jak osiągnąć to?

Author: informatik01, 2008-09-26

13 answers

odpowiadając sobie jako FAQ tej strony zachęca do tego. To działa dla mnie:

Większość znaków nie jest problematyczna, ponieważ domyślnym zestawem znaków używanym przez przeglądarki i tomcat / java dla webapps jest latin1 ie. ISO-8859-1, który "rozumie" te znaki.

Aby UTF-8 działał pod Javą + Tomcat+Linux / Windows+Mysql wymaga:

Konfigurowanie serwera Tomcat.xml

Konieczne jest skonfigurowanie, aby złącze używało UTF - 8 to encode url (GET request) parameters:

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

Kluczowa część to URIEncoding= "UTF-8" W powyższym przykładzie. To gwarantuje, że Tomcat obsługuje wszystkie przychodzące parametry GET jako kodowane UTF-8. W rezultacie, gdy użytkownik zapisuje na pasku adresu przeglądarki:

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

Znak ж jest obsługiwany jako UTF-8 i jest kodowany (zwykle przez przeglądarkę, zanim trafi na serwer) jako %d0%B6.

POST request are nie ma to wpływu.

CharsetFilter

Następnie nadszedł czas, aby zmusić Java webapp do obsługi wszystkich żądań i odpowiedzi jako UTF-8 zakodowane. Wymaga to zdefiniowania filtra zestawu znaków w następujący sposób:

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() {
    }
}

Ten filtr upewnia się, że jeśli przeglądarka nie ustawiła kodowania użytego w żądaniu, to jest ustawiona na UTF-8.

Inną rzeczą wykonaną przez ten filtr jest ustawienie domyślnego kodowania odpowiedzi ie. kodowanie, w którym zwrócony html / whatever is. Alternatywą jest Ustawienie kodowania odpowiedzi itp. w każdym kontrolerze aplikacji.

Ten filtr musi być dodany do www.xml lub deskryptor wdrożenia aplikacji 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>

Instrukcje tworzenia tego filtra znajdują się na Tomcat wiki (http://wiki.apache.org/tomcat/Tomcat/UTF-8 )

Kodowanie stron JSP

W Twojej sieci.xml , dodaj "po": {]}

<jsp-config>
    <jsp-property-group>
        <url-pattern>*.jsp</url-pattern>
        <page-encoding>UTF-8</page-encoding>
    </jsp-property-group>
</jsp-config>

Alternatywnie, wszystkie strony JSP webapp musiałby mieć następujące na górze z nich:

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

Jeśli używany jest jakiś układ z różnymi fragmentami JSP, to jest to potrzebne w wszystkich z nich.

HTML - meta tagi

Kodowanie strony JSP mówi JVM, aby obsługiwał znaki na stronie JSP w prawidłowym kodowaniu. Następnie nadszedł czas, aby powiedzieć przeglądarce, w którym kodowaniu jest strona html:

To jest zrobione z poniższym u góry każdej strony XHTML wyprodukowanej przez webapp:

   <?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-connection

Podczas używania db, należy zdefiniować, że połączenie używa kodowania UTF-8. Odbywa się to w kontekście .xml lub gdziekolwiek połączenie JDBC jest defiend w następujący sposób:

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

Baza danych MySQL i tabele

Używana baza danych musi używać kodowania UTF-8. Można to osiągnąć poprzez utworzenie bazy danych o następującej treści:

   CREATE DATABASE `ID_development` 
   /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_swedish_ci */;

Wtedy, wszystkie tabele muszą być również w 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;

Kluczowym elementem jest CHARSET = utf8.

Konfiguracja serwera MySQL

MySQL serveri również musi być skonfigurowany. Zazwyczaj odbywa się to w systemie Windows poprzez modyfikację my.ini - plik i w Linuksie konfigurując my.cnf - plik. W tych plikach powinno być zdefiniowane, że wszyscy klienci podłączeni do serwera używają utf8 jako domyślnego zestawu znaków i że domyślnym zestawem znaków używanym przez serwer jest również utf8.

   [client]
   port=3306
   default-character-set=utf8

   [mysql]
   default-character-set=utf8

Procedury i funkcje Mysql

Te również muszą mieć zdefiniowany zestaw znaków. Na przykład:

   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 requests: latin1 and UTF-8

Jeśli i kiedy jest zdefiniowany w serwerze tomcat.xml, w którym parametry żądania GET są kodowane w UTF-8, następujące żądania GET są obsługiwane poprawnie:

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

Ponieważ znaki ASCII są kodowane w ten sam sposób zarówno z latin1, jak i UTF-8, łańcuch" Petteri " jest obsługiwany prawidłowo.

Cyrylica ж nie jest w ogóle zrozumiana w języku łacińskim1. Ponieważ Tomcat jest poinstruowany, aby obsługiwać parametry żądania jako UTF-8, koduje ten znak poprawnie jako %D0 % B6.

Jeśli i kiedy przeglądarki są poinstruowane, aby czytać strony w kodowaniu UTF-8( z nagłówkami żądań i meta-tagiem html), przynajmniej Firefox 2/3 i inne przeglądarki z tego okresu same kodują znak jako %d0%B6.

Efektem końcowym jest to, że wszystkie znaleziono użytkowników o nazwie "Petteri", a także wszystkich użytkowników o nazwie "ж".

Ale co z äåö?

Http-Specyfikacja definiuje, że domyślnie adresy URL są kodowane jako latin1. Skutkuje to firefox2, firefox3 itp. kodowanie następującej

    https://localhost:8443/ID/Users?action=search&name=*Päivi*

W wersji zakodowanej

    https://localhost:8443/ID/Users?action=search&name=*P%E4ivi*

W języku latin1 znak ä jest zakodowany jako % E4. mimo że strona/request/everything jest zdefiniowana tak, aby używała UTF-8. Kodowanie UTF-8 wersja ä to %C3 % A4

Wynikiem tego jest to, że jest to zupełnie niemożliwe dla webapp do correly obsługi parametrów żądania z żądań GET, ponieważ niektóre znaki są zakodowane w latin1 i inne w UTF-8. Uwaga: żądania POST działają, ponieważ przeglądarki kodują wszystkie parametry żądania z formularzy całkowicie w UTF-8, jeśli strona jest zdefiniowana jako UTF-8

Rzeczy do przeczytania

Bardzo wielkie podziękowania dla autorów poniższych za udzielenie odpowiedzi na mój problem:

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

Ważna Uwaga

Mysql obsługuje podstawową płaszczyznę wielojęzyczną przy użyciu 3-bajtowych znaków UTF-8. Jeśli musisz wyjść poza to (niektóre alfabety wymagają więcej niż 3-bajtów UTF-8), Następnie należy użyć typu kolumny VARBINARY lub użyć utf8mb4 zestaw znaków (który wymaga MySQL 5.5.3 lub nowszego). Pamiętaj tylko, że używanie zestawu znaków utf8 W MySQL nie będzie działać w 100%.

Tomcat z Apache

Jeszcze jedno jeśli używasz łącznika Apache + Tomcat + mod_JK, musisz również wprowadzić następujące zmiany:

  1. Dodaj URIEncoding = "UTF-8" do serwera tomcat.plik xml dla złącza 8009, jest to używany przez złącze mod_JK. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
  2. Pobierz folder apache tj. /etc/httpd/conf i dodaj AddDefaultCharset utf-8 w httpd.conf file. Uwaga: najpierw sprawdź, czy istnieje, czy nie. Jeśli istnieje, możesz go zaktualizować za pomocą tej linii. Możesz dodać tę linię również na dole.
 528
Author: kosoant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-11 16:07:44

Myślę, że całkiem dobrze to podsumowałeś we własnej odpowiedzi.

W procesie UTF-8-ing(?) od końca do końca możesz również chcieć upewnić się, że sama java używa UTF-8. Use-Dfile.encoding = utf-8 jako parametr do JVM (można skonfigurować w catalina.bat).

 12
Author: stian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-27 21:54:08

Aby dodać do odpowiedź kosoanta , Jeśli używasz Springa, zamiast pisać własny filtr serwletów, możesz użyć klasy org.springframework.web.filter.CharacterEncodingFilter, którą dostarczają, konfigurując ją w następujący sposób w Twojej sieci.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>
 9
Author: Raedwald,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:13

To jest dla greckiego kodowania w tabelach MySql, gdy chcemy uzyskać do nich dostęp za pomocą Javy:

Użyj poniższej konfiguracji połączenia w puli połączeń 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>

Jeśli nie chcesz umieszczać tego w puli połączeń JNDI, możesz skonfigurować go jako JDBC-url, jak ilustruje następna linia:

jdbc:mysql://192.168.10.123:3308/mydatabase?characterEncoding=greek
Dla mnie i Nicka, żebyśmy nigdy o tym nie zapomnieli i nie tracili czasu.....
 1
Author: Mike Mountrakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-04 13:52:33

Ładna szczegółowa odpowiedź. chciałem tylko dodać jeszcze jedną rzecz, która na pewno pomoże innym zobaczyć kodowanie UTF-8 na adresach URL w akcji .

Wykonaj poniższe kroki, aby włączyć kodowanie UTF-8 na adresach URL w Firefoksie.

  1. Wpisz "about:config" w pasku adresu.

  2. Użyj typu wejścia filtra, aby wyszukać "sieć.standard-url.właściwość encode-query-utf8".

  3. powyższa właściwość będzie domyślnie false, zmień ją na TRUE.
  4. Uruchom ponownie przeglądarka.

Kodowanie UTF-8 na adresach URL działa domyślnie w IE6 / 7 / 8 i chrome.

 1
Author: Jay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-19 01:30:34

Chcę również dodać z Tutaj ta część rozwiązała mój problem utf:

runtime.encoding=<encoding>
 1
Author: John,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-15 02:19:46

Mam podobny problem, ale w nazwach plików kompresuję za pomocą Apache commons. Więc rozwiązałem to poleceniem:

convmv --notest -f cp1252 -t utf8 * -r
Dla mnie działa bardzo dobrze. Mam nadzieję, że komuś pomoże;)
 0
Author: caarlos0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-20 13:45:30

W moim przypadku wyświetlania znaków Unicode z pakietów wiadomości, nie muszę stosować sekcji "kodowanie stron JSP", aby wyświetlić Unicode na mojej stronie jsp. Potrzebuję tylko sekcji "CharsetFilter".

 0
Author: bnguyen82,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-21 01:59:03

Jeszcze jedna kwestia, o której nie wspomniano, dotyczy serwletów Javy pracujących z Ajaxem. Mam sytuacje, gdy strona internetowa odbiera tekst utf-8 od użytkownika wysyłającego go do pliku JavaScript, który zawiera go w URI wysłanym do Servletu. Servlet odpytuje bazę danych, przechwytuje wynik i zwraca go jako XML do pliku JavaScript, który go formatuje i wstawia sformatowaną odpowiedź do oryginalnej strony internetowej.

W jednej aplikacji internetowej śledziłem wczesną książkę Ajax instrukcje zawijania JavaScript podczas konstruowania URI. Przykład w książce zastosował metodę escape (), którą odkryłem (the hard way) jest błędny. Dla utf - 8 musisz użyć encodeuricomponent ().

Niewiele osób wydaje się w dzisiejszych czasach tworzyć własny Ajax, ale pomyślałem, że równie dobrze mogę to dodać.

 0
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-14 22:30:51

O CharsetFilter wspomnianym w @kosoant odpowiedz ....

W tomcat web.xml (znajduje się w conf/web.xml) znajduje się Wbudowany Moduł Filter. Filtr ma nazwę setCharacterEncodingFilter i jest domyślnie komentowany. Możesz to odkomentować (pamiętaj, aby również odkomentować jego filter-mapping)

Nie ma też potrzeby ustawiania jsp-config w twoim web.xml (mam test na Tomcat 7+)

 0
Author: Alireza Fattahi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-09 05:24:48

Jakiś czas możesz rozwiązać problem za pomocą Kreatora administratora MySQL. In

Zmienne startowe > Zaawansowane >

I ustawić Def. char Set: utf8

Może ten config wymaga restartu MySQL.

 0
Author: user3600935,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-13 18:34:13

Poprzednie odpowiedzi nie zadziałały z moim problemem. Był tylko w produkcji, z tomcat i apache mod_proxy_ajp. Post body lost non ASCII chars by ? Problem w końcu pojawił się z JVM defaultCharset (US-ASCII w domyślnej instalacji: Charset Dfset = Charset.defaultCharset();) tak więc, rozwiązaniem było uruchomienie serwera tomcat z modyfikatorem, aby uruchomić JVM z UTF-8 jako domyślnym zestawem znaków:

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

(Dodaj ten wiersz do catalina.sh i service tomcat restart)

Może Ty też musisz się zmienić zmienna systemu linux (edycja ~/.bashrc i ~/.profil do trwałej zmiany, zobacz https://perlgeek.de/en/article/set-up-a-clean-utf8-environment )

Export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

Export LANGUAGE=en_US.UTF-8

 0
Author: Rogelio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-17 06:18:01

W przypadku, gdy podałeś w puli połączeń (mysql-DS.xml), w kodzie Java można otworzyć połączenie w następujący sposób:

DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Connection conn = DriverManager.getConnection(
    "jdbc:mysql://192.168.1.12:3308/mydb?characterEncoding=greek",
    "Myuser", "mypass");
 -1
Author: Mike Mountrakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-09 12:42:41