it-swarm.com.de

Wie bekomme ich UTF-8 zum Laufen in Java webapps?

Ich muss UTF-8 in meiner Java Webapp (Servlets + JSP, kein Framework verwendet) zum Unterstützen von äöå Usw. für regulären finnischen Text und kyrillische Alphabete wie ЦжФ Für Sonderfälle.

Mein Setup ist wie folgt:

  • Entwicklungsumgebung: Windows XP
  • Produktionsumgebung: Debian

Verwendete Datenbank: MySQL 5.x

Benutzer verwenden hauptsächlich Firefox2, aber auch Opera 9.x, FF3, IE7 und Google Chrome) werden verwendet, um auf die Site zuzugreifen.

Wie kann man das erreichen?

362
kosoant

Mich als den FAQ dieser Seite zu beantworten, ermutigt das. Das funktioniert für mich:

Meistens sind Zeichen äåö kein Problem, da der von Browsern und Tomcat/Java für Webapps verwendete Standardzeichensatz latin1 ist, d. H. ISO-8859-1, die diese Zeichen "versteht".

Damit UTF-8 unter Java + Tomcat + Linux/Windows + MySQL funktioniert, ist Folgendes erforderlich:

Tomcat's server.xml konfigurieren

Es muss konfiguriert werden, dass der Connector UTF-8 verwendet, um URL-Parameter (GET-Request) zu codieren:

<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 Schlüsselteil ist URIEncoding = "UTF-8" im obigen Beispiel. Dies stellt sicher, dass Tomcat alle eingehenden GET-Parameter als UTF-8-codiert behandelt. Dies hat zur Folge, dass der Benutzer Folgendes in die Adressleiste des Browsers schreibt:

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

das Zeichen ж wird als UTF-8 behandelt und als (normalerweise vom Browser vor dem Aufrufen des Servers) verschlüsselt % D0% B6.

POST-Anfragen sind davon nicht betroffen.

CharsetFilter

Dann ist es Zeit, die Java webapp zu zwingen, alle Anforderungen und Antworten als UTF-8-codiert 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 UTF-8 eingestellt ist, wenn der Browser die in der Anforderung verwendete Codierung nicht festgelegt hat.

Die andere Sache, die von diesem Filter gemacht wird, ist, die Standardantwortkodierung einzustellen, dh. die Kodierung, in der das zurückgegebene HTML/was auch immer ist. Die Alternative besteht darin, die Antwortcodierung usw. in jedem Controller der Anwendung festzulegen.

Dieser Filter muss dem hinzugefügt werden web.xml oder der Deployment-Deskriptor der Web-App:

 <!--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 Anweisungen zum Erstellen dieses Filters finden Sie unter Tomcat wiki (http://wiki.Apache.org/Tomcat/Tomcat/UTF-8 ).

JSP-Seitencodierung

Fügen Sie in Ihrer web.xml Folgendes hinzu:

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

Alternativ müssten alle JSP-Seiten der Web-App die folgenden Informationen enthalten:

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

Wenn ein Layout mit verschiedenen JSP-Fragmenten verwendet wird, ist dies in erforderlich alle von ihnen.

HTML-Meta-Tags

Die JSP-Seitencodierung weist die JVM an, die Zeichen auf der JSP-Seite in der richtigen Codierung zu verarbeiten. Dann ist es Zeit, dem Browser mitzuteilen, in welcher Codierung sich die HTML-Seite befindet:

Dies geschieht wie folgt am oberen Rand jeder von der Web-App 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 Verwendung einer Datenbank muss definiert werden, dass die Verbindung die UTF-8-Codierung verwendet. Dies geschieht in context.xml oder wo immer die JDBC-Verbindung defiend ist, wie folgt:

      <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 UTF-8-Codierung verwenden. Dies wird erreicht, indem die Datenbank wie folgt erstellt wird:

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

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

   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 Schlüsselteil ist CHARSET = utf8.

MySQL Server Konfiguration

MySQL Serveri muss ebenfalls konfiguriert werden. In der Regel erfolgt dies unter Windows durch Ändern my.ini -Datei und unter Linux durch Konfiguration my.cnf -Datei. In diesen Dateien sollte definiert 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

Für diese muss auch 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 Tomcats server.xml definiert ist, dass GET-Anforderungsparameter in UTF-8 codiert 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 bei latin1 als auch bei UTF-8 gleich codiert werden, wird der String "Petteri" korrekt behandelt.

Das kyrillische Zeichen ж wird in lateinisch1 überhaupt nicht verstanden. Da Tomcat angewiesen wird, Anforderungsparameter als UTF-8 zu behandeln, codiert es dieses Zeichen korrekt als % D0% B6.

Wenn Browser angewiesen werden, die Seiten in UTF-8-Codierung zu lesen (mit Anforderungsheader und HTML-Metatag), codieren mindestens Firefox 2/3 und andere Browser aus diesem Zeitraum das Zeichen selbst als % D0% B6.

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

Aber was ist mit äåö?

Die HTTP-Spezifikation definiert, dass URLs standardmäßig als latin1 codiert werden. Dies führt dazu, dass Firefox2, Firefox3 usw. Folgendes codieren

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

in der verschlüsselten Version

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

In latin1 der Charakter ein ist codiert als % E4. Obwohl die Seite/Anfrage/alles so definiert ist, dass UTF-8 verwendet wird. Die UTF-8-codierte Version von ä ist % C3% A4

Dies hat zur Folge, dass die Webanwendung die Anforderungsparameter von GET-Anforderungen nicht korrekt verarbeiten kann, da einige Zeichen in latin1 und andere in UTF-8 codiert sind. Hinweis: POST Anforderungen funktionieren als Browser, die alle Anforderungsparameter aus Formularen vollständig in UTF-8 codieren, wenn die Seite als UTF-8 definiert ist

Sachen zum Lesen

Ein großes Dankeschön an die Autoren der folgenden Artikel, die Antworten auf mein Problem gegeben haben:

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

Wichtige Notiz

mysql unterstützt das Basic Multilingual Plane mit 3-Byte-UTF-8-Zeichen. Wenn Sie darüber hinausgehen müssen (bestimmte Alphabete erfordern mehr als 3 Byte UTF-8), müssen Sie entweder eine Variante des Spaltentyps VARBINARY verwenden oder die Zeichenfolge utf8mb4 Zeichensatz (benötigt MySQL 5.5.3 oder neuer). Beachten Sie jedoch, dass die Verwendung des Zeichensatzes utf8 In MySQL nicht in allen Fällen funktioniert.

Kater mit Apache

Noch etwas Wenn Sie den Apache + Tomcat + mod_JK-Connector verwenden, müssen Sie außerdem folgende Änderungen vornehmen:

  1. Fügen Sie URIEncoding = "UTF-8" in die Tomcat-Datei server.xml für den 8009-Connector ein. Sie wird vom mod_JK-Connector verwendet. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
  2. Gehen Sie in Ihren Apache-Ordner, d. H. /etc/httpd/conf Und fügen Sie AddDefaultCharset utf-8 In httpd.conf file Ein. Hinweis: Überprüfen Sie zuerst, ob es existiert oder nicht. Wenn vorhanden, können Sie es mit dieser Zeile aktualisieren. Sie können diese Zeile auch unten hinzufügen.
543
kosoant

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

Wenn Sie UTF-8-ing (?) Von Ende zu Ende ausführen, möchten Sie möglicherweise auch sicherstellen, dass Java selbst UTF-8 verwendet. Verwenden Sie -Dfile.encoding = utf-8 als Parameter an die JVM (kann in catalina.bat konfiguriert werden).

12
stian

Um zu kosoants Antwort hinzuzufügen, wenn Sie Spring verwenden, anstatt Ihren eigenen Servlet-Filter zu schreiben, können Sie die Klasse org.springframework.web.filter.CharacterEncodingFilter sie stellen bereit und konfigurieren 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>
11
Raedwald

Ich möchte auch von hier diesen Teil hinzufügen, der mein utf-Problem gelöst hat:

runtime.encoding=<encoding>
2
John

Schöne ausführliche Antwort. Ich wollte nur noch eine Sache hinzufügen, die definitiv anderen helfen wird, die UTF-8-Codierung auf URLs in Aktion zu sehen.

Führen Sie die folgenden Schritte aus, um die UTF-8-Codierung für URLs in Firefox zu aktivieren.

  1. geben Sie "about: config" in die Adressleiste ein.

  2. Verwenden Sie den Filtereingabetyp, um nach der Eigenschaft "network.standard-url.encode-query-utf8" zu suchen.

  3. die obige Eigenschaft ist standardmäßig false. Setzen Sie diese Eigenschaft auf TRUE.
  4. starten Sie den Browser neu.

Die UTF-8-Codierung für URLs funktioniert standardmäßig in IE6/7/8 und Chrome.

1
Jay

Dies ist für die griechische Codierung in MySQL-Tabellen vorgesehen, wenn wir mit Java darauf zugreifen möchten:

Verwenden Sie den folgenden Verbindungsaufbau in Ihrem JBoss-Verbindungspool (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>

Wenn Sie dies nicht in einen JNDI-Verbindungspool einfügen möchten, können Sie es als JDBC-URL konfigurieren, wie in der folgenden Zeile dargestellt:

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

Für mich und Nick, also vergessen wir es nie und verschwenden keine Zeit mehr.

1
Mike Mountrakis

Einige Zeit können Sie das Problem mit dem MySQL Administrator-Assistenten lösen. Im

Startvariablen> Erweitert>

und setze Def. char Set: utf8

Möglicherweise muss diese Konfiguration MySQL neu starten.

0
user3600935

Frühere Antworten haben mit meinem Problem nicht funktioniert. Es war nur in Produktion, mit Tomcat und Apache mod_proxy_ajp. Postkörper verloren nicht ASCII-Zeichen durch? Das Problem bestand schließlich bei JVM defaultCharset (US-ASCII in einer Standardinstallation: Charset dfset = Charset.defaultCharset ();). Daher wurde die Lösung auf einem Tomcat-Server mit einem Modifikator ausgeführt, 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 hinzu und warten Sie einen Tomcat-Neustart.)

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

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

export LANGUAGE = de_DE.UTF-8

0
Rogelio

Konfrontiert das gleiche Problem auf Spring MVC 5 + Tomcat 9 + JSP.
Nach der langen Recherche kam zu einer eleganten Lösung (nein brauchen Filter und nein brauchen Änderungen = in der Tomcat server.xml (ab Version 8.0.0-RC3))

  1. Legen Sie in der WebMvcConfigurer-Implementierung die Standardcodierung für messageSource fest (zum Lesen von Daten aus Nachrichtenquelldateien in der UTF-8-Codierung).

    @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. In der Implementierung von DispatcherServletInitializer @Override die Methode onStartup, und legen Sie darin die Anforderungs- und Ressourcenzeichencodierung fest.

    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. Speichern Sie alle Nachrichtenquellen und zeigen Sie Dateien in UTF-8-Codierung an.

  4. Fügen Sie <% @ page contentType = "text/html; charset = UTF-8"%> oder <% @ page pageEncoding = "UTF-8"%> in jede * .jsp-Datei ein oder füge jsp-config descriptor zu web.xml hinzu

    <?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>
    
0
Andrei Veshtard

Über CharsetFilter in @kosoant Antwort erwähnt ....

Es gibt einen Build in Filter in Tomcat web.xml (befindet sich conf/web.xml). Der Filter heißt setCharacterEncodingFilter und ist standardmäßig kommentiert. Sie können dies kommentieren (Denken Sie daran, das Kommentarzeichen filter-mapping zu )

Es ist auch nicht erforderlich, jsp-config in deinem web.xml (Ich habe es für Tomcat 7+ getestet)

0
Alireza Fattahi

Bei der Anzeige von Unicode-Zeichen aus Nachrichtenpaketen muss der Abschnitt "JSP-Seitencodierung" nicht angewendet werden, um Unicode auf meiner JSP-Seite anzuzeigen. Alles was ich brauche ist der Abschnitt "CharsetFilter".

0
bnguyen82

Ich habe ein ähnliches Problem, aber in Dateinamen einer Datei komprimiere ich mit Apache Commons. Also löste ich es mit diesem Befehl:

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

es funktioniert sehr gut für mich. Hoffe es hilft jemandem;)

0
caarlos0

Ein anderer Punkt, der nicht erwähnt wurde, bezieht sich auf Java= Servlets, die mit Ajax arbeiten. Ich habe Situationen, in denen eine Webseite utf-8-Text vom Benutzer aufnimmt, der diesen an eine JavaScript-Datei sendet, die Fügt es in einen an das Servlet gesendeten URI ein. Das Servlet fragt eine Datenbank ab, erfasst das Ergebnis und gibt es als XML an die JavaScript-Datei zurück, die es formatiert und die formatierte Antwort in die ursprüngliche Webseite einfügt.

In einer Web-App habe ich die Anweisungen eines frühen Ajax-Buches befolgt, um das JavaScript bei der Erstellung der URI einzuschließen. Das Beispiel in dem Buch verwendete die escape () -Methode, die ich (auf die harte Tour) entdeckt habe, ist falsch. Für utf-8 müssen Sie encodeURIComponent () verwenden.

Heutzutage scheinen nur wenige Leute ihr eigenes Ajax zu rollen, aber ich dachte, ich könnte das genauso gut hinzufügen.

0
David