Mysql
 sql >> Database >  >> RDS >> Mysql

Come far funzionare UTF-8 nelle webapp Java?

Rispondo a me stesso perché le FAQ di questo sito lo incoraggiano. Questo funziona per me:

Per lo più i caratteri äåö non sono un problema poiché il set di caratteri predefinito utilizzato dai browser e tomcat/java per le webapp è latin1 ie. ISO-8859-1 che "capisce" quei caratteri.

Per far funzionare UTF-8 in Java+Tomcat+Linux/Windows+Mysql è necessario quanto segue:

Configurazione del server.xml di Tomcat

È necessario configurare che il connettore utilizzi UTF-8 per codificare i parametri dell'URL (richiesta 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"
/>

La parte fondamentale è URIEncoding="UTF-8" nell'esempio sopra. Ciò garantisce che Tomcat gestisca tutti i parametri GET in entrata come codificati UTF-8. Di conseguenza, quando l'utente scrive quanto segue nella barra degli indirizzi del browser:

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

il carattere Ö è gestito come UTF-8 ed è codificato (di solito dal browser prima ancora di arrivare al server) come %D0%B6 .

Le richieste POST non sono interessate da questo.

Filtro Charset

Quindi è il momento di forzare la webapp java a gestire tutte le richieste e le risposte come codificate UTF-8. Ciò richiede la definizione di un filtro set di caratteri come il seguente:

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

Questo filtro assicura che se il browser non ha impostato la codifica utilizzata nella richiesta, sia impostato su UTF-8.

L'altra cosa fatta da questo filtro è impostare la codifica della risposta predefinita, ad es. la codifica in cui viene restituito html/qualunque cosa sia. L'alternativa è impostare la codifica della risposta ecc. in ogni controller dell'applicazione.

Questo filtro deve essere aggiunto a web.xml o il descrittore di distribuzione della 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>

Le istruzioni per creare questo filtro sono disponibili nel wiki di tomcat ( http://wiki.apache.org/tomcat/Tomcat/UTF-8 )

Codifica della pagina JSP

Nel tuo web.xml , aggiungi quanto segue:

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

In alternativa, tutte le pagine JSP della webapp dovrebbero avere quanto segue in cima:

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

Se viene utilizzato un tipo di layout con diversi frammenti JSP, questo è necessario in tutti di loro.

Meta tag HTML

La codifica della pagina JSP indica alla JVM di gestire i caratteri nella pagina JSP con la codifica corretta. Quindi è il momento di comunicare al browser in quale codifica è la pagina html:

Questo viene fatto con quanto segue nella parte superiore di ogni pagina xhtml prodotta dalla 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' />
   ...

Connessione JDBC

Quando si utilizza un db, è necessario definire che la connessione utilizzi la codifica UTF-8. Questo viene fatto in context.xml o ovunque sia definita la connessione JDBC come segue:

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

Database e tabelle MySQL

Il database utilizzato deve utilizzare la codifica UTF-8. Ciò si ottiene creando il database con quanto segue:

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

Quindi, tutte le tabelle devono essere anche in 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;

La parte fondamentale è CHARSET=utf8 .

Configurazione del server MySQL

Anche MySQL serveri deve essere configurato. In genere questo viene fatto in Windows modificando my.ini -file e in Linux configurando my.cnf -file.In quei file dovrebbe essere definito che tutti i client collegati al server utilizzano utf8 come set di caratteri predefinito e che anche il set di caratteri predefinito utilizzato dal server è utf8.

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

   [mysql]
   default-character-set=utf8

Procedure e funzioni di MySQL

Anche questi devono avere il set di caratteri definito. Ad esempio:

   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 richieste:latin1 e UTF-8

Se e quando è definito nel server.xml di Tomcat che i parametri della richiesta GET sono codificati in UTF-8, le seguenti richieste GET vengono gestite correttamente:

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

Poiché i caratteri ASCII sono codificati allo stesso modo sia con latin1 che con UTF-8, la stringa "Petteri" viene gestita correttamente.

Il carattere cirillico ж non è affatto compreso in latino1. Poiché a Tomcat viene richiesto di gestire i parametri della richiesta come UTF-8, codifica correttamente quel carattere come %D0%B6 .

Se e quando ai browser viene richiesto di leggere le pagine con codifica UTF-8 (con intestazioni di richiesta e meta-tag html), almeno Firefox 2/3 e altri browser di questo periodo codificano tutti il ​​carattere stesso come %D0% B6 .

Il risultato finale è che vengono trovati tutti gli utenti con il nome "Petteri" e anche tutti gli utenti con il nome "ж".

Ma che dire di äåö?

La specifica HTTP definisce che per impostazione predefinita gli URL sono codificati come latin1. Ciò si traduce in firefox2, firefox3 ecc. Codifica quanto segue

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

nella versione codificata

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

In latino1 il carattere ä è codificato come %E4 . Anche se la pagina/richiesta/tutto è definita per utilizzare UTF-8 . La versione codificata UTF-8 di ä è %C3%A4

Il risultato di ciò è che è del tutto impossibile per la webapp gestire correttamente i parametri della richiesta dalle richieste GET poiché alcuni caratteri sono codificati in latin1 e altri in UTF-8.Avviso:le richieste POST funzionano poiché i browser codificano tutti i parametri della richiesta dai moduli completamente in UTF-8 se la pagina è definita come UTF-8

Cose da leggere

Un grande ringraziamento per gli autori di quanto segue per aver fornito le risposte al mio problema:

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

Nota importante

supporta il Aereo multilingue di base utilizzando caratteri UTF-8 a 3 byte. Se hai bisogno di andare al di fuori di questo (alcuni alfabeti richiedono più di 3 byte di UTF-8), allora devi usare una versione di VARBINARY digitare la colonna o utilizzare utf8mb4 set di caratteri (che richiede MySQL 5.5.3 o successivo). Tieni solo presente che usando utf8 il set di caratteri in MySQL non funzionerà il 100% delle volte.

Tomcat con Apache

Un'altra cosa Se stai usando il connettore Apache + Tomcat + mod_JK, devi anche apportare le seguenti modifiche:

  1. Aggiungi URIEncoding="UTF-8" nel file Tomcat server.xml per il connettore 8009, viene utilizzato dal connettore mod_JK. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
  2. Vai alla tua cartella apache, ad esempio /etc/httpd/conf e aggiungi AddDefaultCharset utf-8 in httpd.conf file . Nota: Per prima cosa controlla che esista o meno. Se esiste puoi aggiornarlo con questa riga. Puoi anche aggiungere questa riga in basso.