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

Hvordan får man UTF-8 til at fungere i Java webapps?

At svare mig selv som ofte stillede spørgsmål på dette websted opmuntrer det. Dette virker for mig:

For det meste tegn äåö er ikke et problem, da standardtegnsættet brugt af browsere og tomcat/java til webapps er latin1 dvs. ISO-8859-1, som "forstår" disse tegn.

For at få UTF-8 til at fungere under Java+Tomcat+Linux/Windows+Mysql kræves følgende:

Konfiguration af Tomcats server.xml

Det er nødvendigt at konfigurere, at connectoren bruger UTF-8 til at kode url-parametre (GET request):

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

Nøgledelen er URIEncoding="UTF-8" i ovenstående eksempel. Dette garanterer, at Tomcat håndterer alle indgående GET-parametre som UTF-8-kodet. Som et resultat, når brugeren skriver følgende til adresselinjen i browseren:

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

tegnet ж håndteres som UTF-8 og er kodet til (normalt af browseren, før det overhovedet kommer til serveren) som %D0%B6 .

POST-anmodning påvirkes ikke af dette.

TegnsætFilter

Så er det tid til at tvinge java-webappen til at håndtere alle anmodninger og svar som UTF-8-kodet. Dette kræver, at vi definerer et tegnsætfilter som følgende:

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

Dette filter sikrer, at hvis browseren ikke har indstillet den kodning, der blev brugt i anmodningen, er den indstillet til UTF-8.

Den anden ting, som dette filter gør, er at indstille standardresponskodningen, dvs. den kodning, hvori den returnerede html/whatever er. Alternativet er at indstille svarkodning osv. i hver controller i applikationen.

Dette filter skal tilføjes til web.xml eller webappens implementeringsbeskrivelse:

 <!--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>

Instruktionerne til at lave dette filter findes på tomcat-wikien ( http://wiki.apache.org/tomcat/Tomcat/UTF-8 )

JSP-sidekodning

I din web.xml , tilføj følgende:

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

Alternativt skal alle JSP-sider i webappen have følgende øverst:

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

Hvis der bruges en form for layout med forskellige JSP-fragmenter, er dette nødvendigt i alle af dem.

HTML-metatags

JSP-sidekodning fortæller JVM at håndtere tegnene på JSP-siden i den korrekte kodning. Så er det tid til at fortælle browseren, hvilken kodning html-siden er i:

Dette gøres med følgende øverst på hver xhtml-side produceret af webappen:

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

Når du bruger en db, skal det defineres, at forbindelsen bruger UTF-8-kodning. Dette gøres i context.xml eller hvor som helst JDBC-forbindelsen er defineret som følger:

      <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 og tabeller

Den brugte database skal bruge UTF-8-kodning. Dette opnås ved at oprette databasen med følgende:

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

Så skal alle tabellerne også være i 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;

Nøgledelen er CHARSET=utf8 .

MySQL-serverkonfiguration

MySQL serveri skal også konfigureres. Dette gøres typisk i Windows ved at ændre my.ini -fil og i Linux ved at konfigurere my.cnf -file.I disse filer skal det defineres, at alle klienter, der er forbundet til serveren, bruger utf8 som standardtegnsæt, og at standardtegnsættet, der bruges af serveren, også er utf8.

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

   [mysql]
   default-character-set=utf8

Mysql-procedurer og -funktioner

Disse skal også have karaktersættet defineret. For eksempel:

   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-anmodninger:latin1 og UTF-8

Hvis og når det er defineret i tomcats server.xml, at GET-anmodningsparametre er kodet i UTF-8, håndteres følgende GET-anmodninger korrekt:

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

Fordi ASCII-tegn er kodet på samme måde både med latin1 og UTF-8, håndteres strengen "Petteri" korrekt.

Det kyrilliske tegn ж forstås slet ikke på latin1. Fordi Tomcat bliver bedt om at håndtere anmodningsparametre som UTF-8, koder den det tegn korrekt som %D0%B6 .

Hvis og når browsere bliver bedt om at læse siderne i UTF-8-kodning (med anmodningsheadere og html-metatag), koder mindst Firefox 2/3 og andre browsere fra denne periode alle tegnet selv som %D0% B6 .

Slutresultatet er, at alle brugere med navnet "Petteri" er fundet, og også alle brugere med navnet "ж" er fundet.

Men hvad med äåö?

HTTP-specifikationen definerer, at URL'er som standard kodes som latin1. Dette resulterer i, at firefox2, firefox3 osv. koder følgende

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

ind i den kodede version

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

På latin1 tegnet ä er kodet som %E4 . Selvom siden/anmodningen/alt er defineret til at bruge UTF-8 . Den UTF-8-kodede version af ä er %C3%A4

Resultatet af dette er, at det er helt umuligt for webappen at håndtere anmodningsparametrene fra GET-anmodninger korrekt, da nogle tegn er kodet i latin1 og andre i UTF-8.Bemærk:POST-anmodninger fungerer, da browsere koder alle anmodningsparametre fra formularer helt i UTF-8, hvis siden er defineret som værende UTF-8

Ting at læse

En meget stor tak til skribenten af ​​følgende for at give svarene på mit problem:

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

Vigtig bemærkning

understøtter Basic Multilingual Plane ved hjælp af 3-byte UTF-8-tegn. Hvis du har brug for at gå uden for det (visse alfabeter kræver mere end 3-bytes UTF-8), så skal du enten bruge en smag af VARBINARY kolonnetype eller brug utf8mb4 tegnsæt (som kræver MySQL 5.5.3 eller nyere). Bare vær opmærksom på, at du bruger utf8 tegnsæt i MySQL virker ikke 100 % af tiden.

Tomcat med Apache

En ting mere Hvis du bruger Apache + Tomcat + mod_JK-stik, skal du også foretage følgende ændringer:

  1. Tilføj URIEncoding="UTF-8" til tomcat server.xml-fil til 8009-stikket, det bruges af mod_JK-stikket.
  2. Gå til din apache-mappe, dvs. /etc/httpd/conf og tilføj AddDefaultCharset utf-8 i httpd.conf-fil . Bemærk: Tjek først, om den eksisterer eller ej. Hvis det findes, kan du opdatere det med denne linje. Du kan også tilføje denne linje nederst.


  1. Alternative Oracle-drivere til .net

  2. Hvordan kan jeg bruge en forespørgsel med pladsholder inde i anførselstegn? (perl / postgresql)

  3. Tilføj en kolonne med en standardværdi til en eksisterende tabel i SQL Server

  4. Regler for implementering af TDD i gammelt projekt