375 Stimmen

Wie kann man UTF-8 in Java-Webanwendungen zum Laufen bringen?

Ich muss UTF-8 in meiner Java-Webapp (Servlets + JSP, kein Framework verwendet) arbeiten, um zu unterstützen äöå usw. für normalen finnischen Text und kyrillische Alphabete wie für besondere Fälle.

Ich habe die folgende Konfiguration:

  • Entwicklungsumgebung: Windows XP
  • Produktionsumgebung: Debian

Verwendete Datenbank: MySQL 5.x

Die Nutzer verwenden hauptsächlich Firefox2, aber auch Opera 9.x, FF3, IE7 und Google Chrome werden für den Zugriff auf die Website verwendet.

Wie kann dies erreicht werden?

562voto

kosoant Punkte 11569

Ich antworte mir selbst, da die FAQ dieser Website dazu anregen. Das funktioniert für mich:

Die meisten Zeichen äåö sind unproblematisch, da der von Browsern und Tomcat/Java für Webanwendungen verwendete Standardzeichensatz latin1, d. h. ISO-8859-1 ist, der diese Zeichen "versteht".

Um UTF-8 unter Java+Tomcat+Linux/Windows+Mysql zum Laufen zu bringen, ist Folgendes erforderlich:

Die server.xml von Tomcat konfigurieren

Es muss konfiguriert werden, dass der Konnektor UTF-8 zur Kodierung von url-Parametern (GET-Anfrage) verwendet:

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

Der wichtigste Teil ist URIEncoding="UTF-8" im obigen Beispiel. Damit wird sichergestellt, dass Tomcat alle eingehenden GET-Parameter als UTF-8 kodiert behandelt. Wenn der Benutzer das Folgende in die Adressleiste des Browsers schreibt, hat dies zur Folge, dass

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

wird das Zeichen als UTF-8 behandelt und (in der Regel vom Browser, noch bevor es den Server erreicht) als %D0%B6 .

POST-Anfragen sind hiervon nicht betroffen.

CharsetFilter

Dann ist es an der Zeit, die Java-Webapp zu zwingen, alle Anfragen und Antworten als UTF-8 kodiert zu behandeln. Dazu müssen wir einen Zeichensatzfilter wie den folgenden definieren:

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

Dieser Filter stellt sicher, dass, wenn der Browser die in der Anfrage verwendete Kodierung nicht festgelegt hat, diese auf UTF-8 gesetzt wird.

Außerdem legt dieser Filter die Standardkodierung der Antwort fest, d. h. die Kodierung, in der die zurückgegebene HTML-Datei bzw. das zurückgegebene Dokument vorliegt. Die Alternative ist, die Antwortkodierung usw. in jedem Controller der Anwendung festzulegen.

Dieser Filter muss in der web.xml oder der Bereitstellungsdeskriptor der 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>

Die Anleitung zur Herstellung dieses Filters finden Sie auf der Website tomcat wiki ( http://wiki.apache.org/tomcat/Tomcat/UTF-8 )

JSP-Seitenkodierung

In Ihrem web.xml fügen Sie Folgendes hinzu:

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

Alternativ dazu müssten alle JSP-Seiten der Webapplikation am Anfang Folgendes enthalten

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

Wenn eine Art von Layout mit verschiedenen JSP-Fragmenten verwendet wird, dann wird dies in alle von ihnen.

HTML-Meta-Tags

Die JSP-Seitenkodierung weist die JVM an, die Zeichen in der JSP-Seite in der richtigen Kodierung zu behandeln. Dann ist es an der Zeit, dem Browser mitzuteilen, in welcher Kodierung die HTML-Seite vorliegt:

Dies geschieht mit dem folgenden Text am Anfang jeder von der Webapp erstellten xhtml-Seite:

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

Bei der Verwendung einer Datenbank muss festgelegt werden, dass die Verbindung die Kodierung UTF-8 verwendet. Dies geschieht in kontext.xml oder wo immer die JDBC-Verbindung wie folgt definiert ist:

      <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-Datenbank und -Tabellen

Die verwendete Datenbank muss die Kodierung UTF-8 verwenden. Dies wird durch die Erstellung der Datenbank mit dem folgenden erreicht:

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

Dann müssen alle Tabellen auch in UTF-8 vorliegen:

   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;

Der wichtigste Teil ist CHARSET=utf8 .

Konfiguration des MySQL-Servers

Der MySQL-Serveri muss ebenfalls konfiguriert werden. Normalerweise geschieht dies unter Windows durch Ändern von meine.ini -Datei und unter Linux durch Konfiguration von meine.cnf -Datei. In diesen Dateien sollte festgelegt werden, dass alle mit dem Server verbundenen Clients utf8 als Standardzeichensatz verwenden und dass der vom Server verwendete Standardzeichensatz ebenfalls utf8 ist.

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

   [mysql]
   default-character-set=utf8

Mysql-Prozeduren und -Funktionen

Auch für diese muss der Zeichensatz definiert sein. Zum Beispiel:

   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-Anfragen: latin1 und UTF-8

Wenn in der server.xml von Tomcat definiert ist, dass GET-Anforderungsparameter in UTF-8 kodiert sind, werden die folgenden GET-Anforderungen ordnungsgemäß verarbeitet:

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

Da ASCII-Zeichen sowohl mit latin1 als auch mit UTF-8 auf die gleiche Weise kodiert werden, wird die Zeichenfolge "Petteri" korrekt behandelt.

Das kyrillische Zeichen wird im Lateinischen1 überhaupt nicht verstanden. Da Tomcat angewiesen ist, Anfrageparameter als UTF-8 zu behandeln, kodiert er dieses Zeichen korrekt als %D0%B6 .****


Wenn die Browser angewiesen werden, die Seiten in UTF-8-Kodierung zu lesen (mit Anfragekopfzeilen und html-Meta-Tag), kodieren zumindest Firefox 2/3 und andere Browser aus dieser Zeit das Zeichen selbst als %D0%B6 .

Das Endergebnis ist, dass alle Benutzer mit dem Namen "Petteri" gefunden werden und auch alle Benutzer mit dem Namen "" gefunden werden.

Aber was ist mit äåö?

Die HTTP-Spezifikation legt fest, dass URLs standardmäßig als latin1 kodiert werden. Dies führt dazu, dass firefox2, firefox3 usw. folgendes kodieren

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

in die verschlüsselte Version

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

Im lateinischen1 wird das Zeichen ä wird kodiert als %E4 . Obwohl page/request/everything für die Verwendung von UTF-8 definiert ist . Die UTF-8 kodierte Version von ä ist %C3%A4

Dies hat zur Folge, dass es für die Webanwendung unmöglich ist, die Anfrageparameter von GET-Anfragen korrekt zu verarbeiten, da einige Zeichen in latin1 und andere in UTF-8 kodiert sind. Hinweis: POST-Anfragen funktionieren, da die Browser alle Anfrageparameter von Formularen vollständig in UTF-8 kodieren, wenn die Seite als UTF-8 definiert ist.

Lesenswertes

Ein herzliches Dankeschön an die Verfasser der folgenden Beiträge für die Antworten auf mein Problem:

Wichtiger Hinweis

mysql Basic Multilingual Plane unter Verwendung von 3-Byte-UTF-8-Zeichen. Wenn Sie darüber hinausgehen müssen (bestimmte Alphabete erfordern mehr als 3 Byte UTF-8), dann müssen Sie entweder eine Variante von VARBINARY Spaltentyp oder verwenden Sie die utf8mb4 Zeichensatz (hierfür ist MySQL 5.5.3 oder höher erforderlich). Beachten Sie jedoch, dass die Verwendung der utf8 Zeichensatz in MySQL wird nicht zu 100 % funktionieren.

Tomcat mit Apache

Noch etwas: Wenn Sie Apache + Tomcat + mod_JK Connector verwenden, müssen Sie auch die folgenden Änderungen vornehmen:

  1. Fügen Sie URIEncoding="UTF-8" in die Datei tomcat server.xml für den 8009-Connector ein, da dieser vom mod_JK-Connector verwendet wird. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
  2. Wechseln Sie in den Apache-Ordner, z. B. /etc/httpd/conf und hinzufügen AddDefaultCharset utf-8 sur httpd.conf file . Anmerkung: Prüfen Sie zunächst, ob sie vorhanden ist oder nicht. Wenn sie existiert, können Sie sie mit dieser Zeile aktualisieren. Sie können diese Zeile auch unten anfügen.

14voto

stian Punkte 2854

Ich denke, Sie haben es in Ihrer eigenen Antwort recht gut zusammengefasst.

Beim UTF-8-ing(?) von Ende zu Ende sollten Sie auch sicherstellen, dass Java selbst UTF-8 verwendet. Verwenden Sie -Dfile.encoding=utf-8 als Parameter für die JVM (kann in catalina.bat konfiguriert werden).

12voto

Raedwald Punkte 43209

Zur Ergänzung von kosoant's Antwort Wenn Sie Spring verwenden, können Sie, anstatt einen eigenen Servlet-Filter zu schreiben, die Klasse org.springframework.web.filter.CharacterEncodingFilter die sie zur Verfügung stellen, und konfigurieren Sie es wie folgt in Ihrer 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>

2voto

John Punkte 21

Ich möchte auch hinzufügen, von ici dieser Teil hat mein UTF-Problem gelöst:

runtime.encoding=<encoding>

1voto

Rogelio Triviño Punkte 4963

Die bisherigen Antworten haben bei meinem Problem nicht funktioniert. Es war nur in der Produktion, mit Tomcat und Apache mod_proxy_ajp. Post body verlor nicht ascii Zeichen durch ? Das Problem war schließlich mit JVM defaultCharset (US-ASCII in einer Standard-Installation: Charset dfset = Charset.defaultCharset();) Die Lösung bestand also darin, den Tomcat-Server mit einem Modifikator auszuführen, um die JVM mit UTF-8 als Standardzeichensatz auszuführen:

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

(fügen Sie diese Zeile zu catalina.sh und service tomcat restart hinzu)

Vielleicht müssen Sie auch die Linux-Systemvariable ändern (bearbeiten Sie ~/.bashrc und ~/.profile für eine dauerhafte Änderung, siehe https://perlgeek.de/en/article/set-up-a-clean-utf8-environment )

export LC_ALL=de_US.UTF-8
export LANG=de_US.UTF-8

export LANGUAGE=de_US.UTF-8

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X