Come far funzionare UTF-8 nelle webapp Java?


367

Ho bisogno di far funzionare UTF-8 nella mia webapp Java (servlet + JSP, nessun framework usato) per supportare äöåecc. Per il normale testo finlandese e alfabeti cirillici come ЦжФper casi speciali.

La mia configurazione è la seguente:

  • Ambiente di sviluppo: Windows XP
  • Ambiente di produzione: Debian

Database utilizzato: MySQL 5.x

Gli utenti utilizzano principalmente Firefox2 ma anche Opera 9.x, FF3, IE7 e Google Chrome vengono utilizzati per accedere al sito.

Come raggiungere questo obiettivo?


Risposte:


552

Rispondere a me stesso come le FAQ di questo sito lo incoraggiano. Questo funziona per me:

Per lo più i caratteri äåö non sono problematici in quanto il set di caratteri predefinito utilizzato dai browser e tomcat / java per webapps è latino1, ad esempio. ISO-8859-1 che "comprende" quei personaggi.

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

Configurazione di server.xml di Tomcat

È necessario configurare che il connettore usi UTF-8 per codificare i parametri 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 chiave è URIEncoding = "UTF-8" nell'esempio sopra. Ciò garantisce che Tomcat gestisce tutti i parametri GET in entrata con codifica 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 .

La richiesta POST non è interessata da questo.

CharsetFilter

Quindi è il momento di forzare la webapp java a gestire tutte le richieste e le risposte come codificate UTF-8. Ciò richiede che definiamo 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 si 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 l'html restituito / qualunque sia. L'alternativa è impostare la codifica della risposta ecc. In ciascun controller dell'applicazione.

Questo filtro deve essere aggiunto a web.xml o al 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 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 le seguenti in cima:

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

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

Meta-tag HTML

La codifica della pagina JSP indica a JVM di gestire i caratteri nella pagina JSP nella codifica corretta. Quindi è tempo di dire 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' />
   ...

JDBC-connection

Quando si utilizza un db, è necessario definire che la connessione utilizza la codifica UTF-8. Questo viene fatto in context.xml o ovunque la connessione JDBC sia definita 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 chiave è CHARSET = utf8 .

Configurazione del server MySQL

Anche il server MySQL deve essere configurato. In genere ciò avviene in Windows modificando my.ini -file e in Linux configurando my.cnf -file. In questi file è necessario definire che tutti i client connessi 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. Per 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 ;

Ricevi richieste: latin1 e UTF-8

Se e quando è definito in 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 di richiesta come UTF-8, codifica quel carattere correttamente come % D0% B6 .

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

Il risultato finale è che sono stati 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ò comporta firefox2, firefox3 ecc. Che 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 è definito per usare UTF-8 . La versione codificata UTF-8 di ä è % C3% A4

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

Roba da leggere

Un grande ringraziamento per gli autori di quanto segue per aver dato 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 piano multilingue di base utilizzando caratteri UTF-8 a 3 byte. Se è necessario uscire da questo (alcuni alfabeti richiedono più di 3 byte di UTF-8), è necessario utilizzare un VARBINARYtipo di colonna o utilizzare il utf8mb4set di caratteri (che richiede MySQL 5.5.3 o successivo). Basta essere consapevoli del fatto che l'utilizzo del utf8set di caratteri in MySQL non funzionerà il 100% delle volte.

Tomcat con Apache

Un'altra cosa Se si utilizza il connettore Apache + Tomcat + mod_JK, è necessario eseguire anche 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. Goto vostro apache cartella cioè /etc/httpd/confe aggiungere AddDefaultCharset utf-8in httpd.conf file. Nota: verificare innanzitutto che esista o meno. Se esiste, puoi aggiornarlo con questa riga. Puoi anche aggiungere questa riga in fondo.

Questi passaggi funzionano anche con Struts / tiles e un database postgres.
kosoant,

17
Due commenti: 1) nei tag HMTL-meta hai incluso una dichiarazione xml. Rimuoverlo, attiverebbe solo i browser in modalità stranezze, non vuoi averlo. Inoltre, i meta tag HTML sono in realtà già implicitamente fatti da JSP pageEncoding, quindi potresti anche lasciarlo via. 2) nel database MySQL e nelle tabelle utilizzate utf8_swedish_si, questo avrebbe dovuto essere utf8_unicode_ci. Potresti anche lasciare la collazione, CHARACTER SET utf8basta.
BalusC

Nessuno dei documenti che ho consultato in merito ai metatag HTML e alla modalità Quirks (ad es. Ericmeyeroncss.com/bonus/render-mode.html , en.wikipedia.org/wiki/Quirks_mode ) indica che la presenza di <meta http-equiv = 'Contenuto -Type "ha alcun impatto sulla modalità di rendering.
Marcel Stör,

Come nota a margine interessante potresti anche essere consapevole del fatto che se hai un listener che accede a un parametro di richiesta, dovrai aggiungere un listener che imposta il set di caratteri anziché un filtro perché i listener vengono eseguiti prima dei filtri. Ho seguito tutti i passaggi e ancora non ha funzionato per questo. Ho pensato di passare queste informazioni, nel caso in cui qualcun altro avesse un problema simile.
testing123

3
## Tomcat con Apache ## Un'altra cosa Se si utilizza il connettore Apache + Tomcat + mod_JK, è necessario eseguire anche le seguenti modifiche: 1. Aggiungere 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 cartella apache, ad es. /etc/httpd/confE aggiungi AddDefaultCharset utf-8il file 'httpd.conf'. Nota: verificare prima che esista o meno. Se esiste, puoi aggiornarlo con questa riga. Puoi anche aggiungere questa riga in fondo.
Vijay Shegokar,

14

Penso che tu l'abbia riassunto abbastanza bene nella tua risposta.

Nel processo di UTF-8-ing (?) Da un capo all'altro potresti anche voler assicurarti che Java stesso stia usando UTF-8. Utilizzare -Dfile.encoding = utf-8 come parametro per JVM (può essere configurato in catalina.bat).


Questo mi ha aiutato, ho fatto tutto quanto menzionato, ma la codifica JVM era windows-1250 non appena ho cambiato in UTF-8 ha funzionato perfettamente.
coding_idiot

2
Dove lo aggiungi nel file Catalina.bat, per favore?
Noah,

11

Per aggiungere alla risposta di kosoant , se stai usando Spring, invece di scrivere il tuo filtro Servlet, puoi usare la classe org.springframework.web.filter.CharacterEncodingFilterche forniscono, configurandola come la seguente nel tuo 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
Questo filtro deve essere il primo filtro in web.xml
olyanren

2

Voglio anche aggiungere da qui questa parte ha risolto il mio problema utf:

runtime.encoding=<encoding>

1

Questo è per la codifica greca nelle tabelle MySql quando vogliamo accedervi usando Java:

Utilizzare la seguente configurazione della connessione nel pool di connessioni 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>

Se non si desidera inserirlo in un pool di connessioni JNDI, è possibile configurarlo come un URL JDBC come illustrato nella riga successiva:

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

Per me e Nick, quindi non lo dimentichiamo mai e perdiamo più tempo .....


5
Preferirei ancora UTF-8 rispetto al greco (e convertire i tuoi attuali dati greci in UTF-8) in modo che la tua applicazione sia pronta per il dominio mondiale.
BalusC

1

Bella risposta dettagliata. volevo solo aggiungere un'altra cosa che aiuterà sicuramente gli altri a vedere la codifica UTF-8 sugli URL in azione.

Seguire i passaggi seguenti per abilitare la codifica UTF-8 sugli URL in Firefox.

  1. digitare "about: config" nella barra degli indirizzi.

  2. Utilizzare il tipo di input del filtro per cercare la proprietà "network.standard-url.encode-query-utf8".

  3. la proprietà sopra sarà falsa per impostazione predefinita, impostala su TRUE.
  4. riavvia il browser.

La codifica UTF-8 sugli URL funziona per impostazione predefinita in IE6 / 7/8 e Chrome.


1

Le risposte precedenti non funzionavano con il mio problema. Era solo in produzione, con tomcat e apache mod_proxy_ajp. Post body ha perso i caratteri non ascii di? Il problema era infine con JVM defaultCharset (US-ASCII in un'installazione predefinita: Charset dfset = Charset.defaultCharset ();) quindi, la soluzione è stata eseguita tomcat server con un modificatore per eseguire JVM con UTF-8 come set di caratteri predefinito:

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

(aggiungi questa linea a catalina.sh e riavvia il servizio tomcat)

Forse devi anche cambiare la variabile di sistema di linux (modifica ~ / .bashrc e ~ / .profile per il cambiamento permanente, vedi 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

Ho un problema simile, ma, nei nomi di file di un file, sto comprimendo con i comuni di Apache. Quindi, l'ho risolto con questo comando:

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

funziona molto bene per me. Spero che possa aiutare chiunque;)


0

Nel mio caso di visualizzazione del carattere Unicode dai pacchetti di messaggi, non ho bisogno di applicare la sezione "Codifica pagina JSP" per visualizzare Unicode sulla mia pagina jsp. Tutto ciò di cui ho bisogno è la sezione "CharsetFilter".


0

Un altro punto che non è stato menzionato riguarda i servlet Java che lavorano con Ajax. Ho delle situazioni in cui una pagina web sta raccogliendo il testo utf-8 dall'utente che lo invia a un file JavaScript che lo include in un URI inviato al Servlet. Il servlet interroga un database, acquisisce il risultato e lo restituisce come XML al file JavaScript che lo formatta e inserisce la risposta formattata nella pagina Web originale.

In un'app Web stavo seguendo le prime istruzioni di un libro Ajax per concludere il JavaScript nella costruzione dell'URI. L'esempio nel libro ha usato il metodo escape (), che ho scoperto (nel modo più duro) è sbagliato. Per utf-8 è necessario utilizzare encodeURIComponent ().

Poche persone sembrano lanciare il proprio Ajax in questi giorni, ma ho pensato che avrei potuto anche aggiungere questo.


0

Informazioni su CharsetFiltermenzionate nella risposta di @kosoant ....

C'è un build-in Filterin tomcat web.xml(che si trova in conf/web.xml). Il filtro è denominato setCharacterEncodingFiltered è commentato per impostazione predefinita. Puoi decommentare questo (Ricorda di decommentare filter-mappinganche questo)

Inoltre non è necessario impostare jsp-confignel tuo web.xml(l'ho testato per Tomcat 7+)


0

Qualche volta è possibile risolvere il problema tramite la procedura guidata dell'amministratore di MySQL. In

Variabili di avvio> Avanzate>

e impostare Def. set di caratteri: utf8

Forse questa configurazione deve riavviare MySQL.


0

Di fronte allo stesso problema su Spring MVC 5 + Tomcat 9 + JSP.
Dopo una lunga ricerca, ho trovato una soluzione elegante ( non sono necessari filtri e non sono necessarie modifiche in Tomcat server.xml (a partire dalla versione 8.0.0-RC3))

  1. Nell'implementazione WebMvcConfigurer impostare la codifica predefinita per messageSource (per leggere i dati dai file di origine dei messaggi nella codifica 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. Nell'implementazione DispatcherServletInitializer @ Sovrascrivi il metodo onStartup e imposta la codifica del carattere di richiesta e risorsa in esso.

    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. Salva tutte le fonti dei messaggi e visualizza i file nella codifica UTF-8.

  4. Aggiungi <% @ page contentType = "text / html; charset = UTF-8"%> o <% @ page pageEncoding = "UTF-8"%> in ciascun file * .jsp o aggiungi il descrittore jsp-config a 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

Nel caso in cui sia stato specificato nel pool di connessioni (mysql-ds.xml), nel codice Java è possibile aprire la connessione come segue:

DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Connection conn = DriverManager.getConnection(
    "jdbc:mysql://192.168.1.12:3308/mydb?characterEncoding=greek",
    "Myuser", "mypass");
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.