sql >> Database >  >> RDS >> Mysql

Hoe krijg ik UTF-8 werkend in Java-webapps?

Ik beantwoord mezelf omdat de veelgestelde vragen van deze site dit aanmoedigen. Dit werkt voor mij:

Meestal zijn tekens äåö geen probleem, aangezien de standaardtekenset die door browsers en Tomcat/java voor webapps wordt gebruikt, latin1 is, dwz. ISO-8859-1 die deze karakters "begrijpt".

Om UTF-8 te laten werken onder Java+Tomcat+Linux/Windows+Mysql is het volgende vereist:

Tomcat's server.xml configureren

Het is noodzakelijk om te configureren dat de connector UTF-8 gebruikt om url-parameters (GET-verzoek) te coderen:

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

Het belangrijkste onderdeel is URIencoding="UTF-8" in het bovenstaande voorbeeld. Dit garandeert dat Tomcat alle binnenkomende GET-parameters behandelt als UTF-8-gecodeerd. Als resultaat, wanneer de gebruiker het volgende naar de adresbalk van de browser schrijft:

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

het teken ж wordt behandeld als UTF-8 en is gecodeerd tot (meestal door de browser voordat het zelfs maar bij de server is gekomen) als %D0%B6 .

POST-verzoeken worden hierdoor niet beïnvloed.

CharsetFilter

Dan is het tijd om de java-webapp te dwingen alle verzoeken en antwoorden als UTF-8-gecodeerd af te handelen. Dit vereist dat we een karaktersetfilter definiëren zoals het volgende:

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

Dit filter zorgt ervoor dat als de browser de codering die in de aanvraag wordt gebruikt niet heeft ingesteld, deze is ingesteld op UTF-8.

Het andere dat door dit filter wordt gedaan, is het instellen van de standaardresponscodering, dwz. de codering waarin de geretourneerde html/wat dan ook is. Het alternatief is om de responscodering enz. in elke controller van de toepassing in te stellen.

Dit filter moet worden toegevoegd aan de web.xml of de descriptor van de 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>

De instructies voor het maken van dit filter zijn te vinden op de tomcat wiki ( http://wiki.apache.org/tomcat/Tomcat/UTF-8 )

JSP-paginacodering

In uw web.xml , voeg het volgende toe:

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

Als alternatief zouden alle JSP-pagina's van de webapp het volgende bovenaan moeten hebben:

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

Als er een soort layout met verschillende JSP-fragmenten wordt gebruikt, dan is dit nodig in alle van hen.

HTML-metatags

JSP-paginacodering vertelt de JVM om de tekens op de JSP-pagina in de juiste codering te verwerken. Dan is het tijd om de browser te vertellen waarin de html-pagina is gecodeerd:

Dit wordt gedaan met het volgende bovenaan elke xhtml-pagina die door de webapp wordt geproduceerd:

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

Bij gebruik van een db moet worden gedefinieerd dat de verbinding UTF-8-codering gebruikt. Dit gebeurt in context.xml of waar de JDBC-verbinding als volgt wordt verdedigd:

      <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-database en tabellen

De gebruikte database moet UTF-8-codering gebruiken. Dit wordt bereikt door de database te maken met het volgende:

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

Dan moeten alle tabellen ook in UTF-8 staan:

   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;

Het belangrijkste onderdeel is CHARSET=utf8 .

MySQL-serverconfiguratie

MySQL serveri moet ook worden geconfigureerd. Meestal wordt dit in Windows gedaan door my.ini . aan te passen -file en in Linux door my.cnf . te configureren -file.In die bestanden moet worden gedefinieerd dat alle clients die op de server zijn aangesloten, utf8 gebruiken als de standaardtekenset en dat de standaardtekenset die door de server wordt gebruikt ook utf8 is.

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

   [mysql]
   default-character-set=utf8

Mysql-procedures en -functies

Deze moeten ook de tekenset hebben gedefinieerd. Bijvoorbeeld:

   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-verzoeken:latin1 en UTF-8

Als en wanneer in Tomcat's server.xml is gedefinieerd dat GET-verzoekparameters zijn gecodeerd in UTF-8, worden de volgende GET-verzoeken correct afgehandeld:

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

Omdat ASCII-tekens zowel met latin1 als met UTF-8 op dezelfde manier worden gecodeerd, wordt de string "Petteri" correct behandeld.

Het Cyrillische karakter ж wordt in het latijn helemaal niet begrepen. Omdat Tomcat is geïnstrueerd om verzoekparameters als UTF-8 te behandelen, codeert het dat teken correct als %D0%B6 .

Als en wanneer browsers de instructie krijgen om de pagina's te lezen in UTF-8-codering (met verzoekheaders en html-metatag), coderen in ieder geval Firefox 2/3 en andere browsers uit deze periode het teken zelf als %D0% B6 .

Het eindresultaat is dat alle gebruikers met de naam "Petteri" worden gevonden en ook alle gebruikers met de naam "ж" worden gevonden.

Maar hoe zit het met äåö?

HTTP-specificatie definieert dat standaard URL's zijn gecodeerd als latin1. Dit resulteert in firefox2, firefox3 etc. die het volgende codeert

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

naar de gecodeerde versie

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

In latin1 het teken ä is gecodeerd als %E4 . Ook al is de pagina/verzoek/alles gedefinieerd om UTF-8 te gebruiken . De UTF-8-gecodeerde versie van ä is %C3%A4

Het resultaat hiervan is dat het voor de webapp vrijwel onmogelijk is om de verzoekparameters van GET-verzoeken correct af te handelen, aangezien sommige tekens zijn gecodeerd in latin1 en andere in UTF-8.Opmerking:POST-verzoeken werken omdat browsers alle verzoekparameters coderen van formulieren volledig in UTF-8 als de pagina is gedefinieerd als UTF-8

Dingen om te lezen

Hartelijk dank aan de schrijvers van het volgende voor het geven van de antwoorden op mijn probleem:

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

Belangrijke opmerking

ondersteunt het Basic meertalig vliegtuig met behulp van 3-byte UTF-8-tekens. Als je daarbuiten moet gaan (bepaalde alfabetten vereisen meer dan 3 bytes UTF-8), dan moet je ofwel een smaak van VARBINARY gebruiken kolomtype of gebruik de utf8mb4 tekenset (waarvoor MySQL 5.5.3 of hoger vereist is). Houd er rekening mee dat het gebruik van de utf8 tekenset in MySQL werkt niet 100% van de tijd.

Kater met Apache

Nog een ding Als u Apache + Tomcat + mod_JK-connector gebruikt, moet u ook de volgende wijzigingen aanbrengen:

  1. Voeg URIEncoding="UTF-8" toe aan het tomcat server.xml-bestand voor 8009-connector, het wordt gebruikt door mod_JK-connector. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
  2. Ga naar je apache-map, bijv. /etc/httpd/conf en voeg AddDefaultCharset utf-8 . toe in httpd.conf file . Opmerking: Controleer eerst of het bestaat of niet. Indien aanwezig, kunt u deze bijwerken met deze regel. Je kunt deze regel ook onderaan toevoegen.


  1. JDeveloper gebruiken met MySQL Database en Oracle Database op AWS RDS, deel 2

  2. Verticaal schalen PostgreSQL

  3. Trefwoord niet ondersteund:metadata

  4. Beestje? #1146 - Tabel 'xxx.xxxxx' bestaat niet