Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak sprawić, by UTF-8 działał w aplikacjach internetowych Java?

Odpowiadam sobie, ponieważ często zadawane pytania tej witryny zachęcają do tego. To działa dla mnie:

Przeważnie znaki äåö nie stanowią problemu, ponieważ domyślny zestaw znaków używany przez przeglądarki i tomcat/java dla aplikacji internetowych to latin1. ISO-8859-1, który „rozumie” te znaki.

Aby UTF-8 działał pod Java+Tomcat+Linux/Windows+Mysql, wymagane jest:

Konfigurowanie pliku server.xml Tomcata

Konieczne jest skonfigurowanie, aby łącznik używał UTF-8 do kodowania parametrów adresu URL (żądanie GET):

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

Kluczową częścią jest URIEncoding="UTF-8" w powyższym przykładzie. Gwarantuje to, że Tomcat obsługuje wszystkie przychodzące parametry GET jako zakodowane w UTF-8. W rezultacie, gdy użytkownik napisze w 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ę jeszcze przed dotarciem do serwera) jako %D0%B6 .

Nie ma to wpływu na żądania POST.

Filtr znaków

Następnie nadszedł czas, aby wymusić na aplikacji internetowej java obsługę wszystkich żądań i odpowiedzi w formacie UTF-8. Wymaga to zdefiniowania filtra zestawu znaków, takiego jak:

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 zapewnia, że ​​jeśli przeglądarka nie ustawiła kodowania używanego w żądaniu, jest ono ustawione na UTF-8.

Inną rzeczą, jaką robi ten filtr, jest ustawienie domyślnego kodowania odpowiedzi, tj. kodowanie, w którym zwracany jest html/cokolwiek. Alternatywą jest ustawienie kodowania odpowiedzi itp. w każdym kontrolerze aplikacji.

Ten filtr należy dodać do pliku web.xml lub deskryptor wdrożenia aplikacji internetowej:

 <!--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 można znaleźć na wiki Tomcat ( http://wiki.apache.org/tomcat/Tomcat/UTF-8 )

Kodowanie strony JSP

W swoim web.xml , dodaj następujące:

<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 aplikacji internetowej musiałyby mieć u góry następujące elementy:

 <%@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 we wszystkich z nich.

Metatagi HTML

Kodowanie strony JSP mówi maszynie JVM, aby obsługiwała znaki na stronie JSP we właściwym kodowaniu. Następnie nadszedł czas, aby poinformować przeglądarkę, w którym kodowaniu jest strona html:

Odbywa się to za pomocą następujących elementów u góry każdej strony xhtml tworzonej przez aplikację internetową:

   <?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' />
   ...

Połączenie JDBC

W przypadku korzystania z bazy danych należy określić, że połączenie wykorzystuje kodowanie UTF-8. Odbywa się to w context.xml lub gdziekolwiek połączenie JDBC jest chronione 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 i tabele MySQL

Używana baza danych musi używać kodowania UTF-8. Osiąga się to poprzez utworzenie bazy danych z następującymi elementami:

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

Następnie 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;

Kluczową częścią jest CHARSET=utf8 .

Konfiguracja serwera MySQL

Należy również skonfigurować serwer MySQL. Zwykle odbywa się to w systemie Windows, modyfikując my.ini -file oraz w Linuksie, konfigurując my.cnf -file.W tych plikach należy określić, ż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 ;

Żądania GET:latin1 i UTF-8

Jeśli i kiedy w tomcat server.xml jest zdefiniowane, że parametry żądania GET są zakodowane 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 w latin1 jak i UTF-8, łańcuch "Petteri" jest obsługiwany poprawnie.

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

Jeśli i kiedy przeglądarki zostaną poinstruowane, aby odczytać 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 .

W rezultacie znaleziono wszystkich użytkowników o nazwie „Petteri”, a także wszystkich użytkowników o nazwie „ж”.

A co z äåö?

Specyfikacja HTTP określa, że ​​domyślnie adresy URL są kodowane jako latin1. Powoduje to zakodowanie przez firefox2, firefox3 itp. następujących

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

do wersji zakodowanej

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

W latin1 znak ä jest zakodowany jako %E4 . Mimo że strona/żądanie/wszystko jest zdefiniowane do używania UTF-8 . Zakodowana w UTF-8 wersja ä to %C3%A4

W rezultacie aplikacja internetowa nie jest w stanie poprawnie obsługiwać parametrów żądania z żądań GET, ponieważ niektóre znaki są zakodowane w latin1, a 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 dziękuję autorom następujących tekstów 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

obsługuje Podstawową płaszczyznę wielojęzyczną przy użyciu 3-bajtowych znaków UTF-8. Jeśli chcesz wyjść poza to (niektóre alfabety wymagają więcej niż 3 bajty UTF-8), musisz użyć odmiany VARBINARY typ kolumny lub użyj utf8mb4 zestaw znaków (co wymaga MySQL 5.5.3 lub nowszego). Pamiętaj tylko, że używając utf8 zestaw znaków w MySQL nie będzie działał w 100% przypadków.

Tomcat z Apache

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

  1. Dodaj URIEncoding="UTF-8" do pliku tomcat server.xml dla łącznika 8009, jest on używany przez łącznik mod_JK.
  2. Przejdź do folderu Apache, np. /etc/httpd/conf i dodaj AddDefaultCharset utf-8 w pliku httpd.conf . 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.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak utworzyć bazę danych MySQL za pomocą interfejsu wiersza poleceń (CLI)

  2. Funkcje agregujące MySQL bez klauzuli GROUP BY

  3. Migracja MySQL do PostgreSQL na AWS RDS, część 1

  4. Przykłady REGEXP MySQL

  5. Mytop – przydatne narzędzie do monitorowania wydajności MySQL/MariaDB w systemie Linux