sql >> Databasteknik >  >> RDS >> Mysql

Hur får man UTF-8 att fungera i Java webbappar?

Att svara mig själv som den här sidans vanliga frågor uppmuntrar det. Det här fungerar för mig:

Oftast är tecken äåö inget problem då standardteckenuppsättningen som används av webbläsare och tomcat/java för webbappar är latin1 dvs. ISO-8859-1 som "förstår" dessa tecken.

För att få UTF-8 att fungera under Java+Tomcat+Linux/Windows+Mysql krävs följande:

Konfigurera Tomcats server.xml

Det är nödvändigt att konfigurera att anslutaren använder UTF-8 för att koda url-parametrar (GET-begäran):

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

Nyckeldelen är URIEncoding="UTF-8" i exemplet ovan. Detta garanterar att Tomcat hanterar alla inkommande GET-parametrar som UTF-8-kodade. Som ett resultat, när användaren skriver följande till webbläsarens adressfält:

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

Tecknet ж hanteras som UTF-8 och kodas till (vanligtvis av webbläsaren innan ens kommer till servern) som %D0%B6 .

POST-förfrågan påverkas inte av detta.

CharsetFilter

Då är det dags att tvinga Java-webbappen att hantera alla förfrågningar och svar som UTF-8-kodade. Detta kräver att vi definierar ett teckenuppsättningsfilter som följande:

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

Det här filtret ser till att om webbläsaren inte har ställt in kodningen som används i begäran, att den är inställd på UTF-8.

Den andra saken som detta filter gör är att ställa in standardsvarskodningen, dvs. kodningen i vilken den returnerade html/whatever är. Alternativet är att ställa in svarskodning etc. i varje styrenhet i applikationen.

Detta filter måste läggas till i web.xml eller distributionsbeskrivningen för webbappen:

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

Instruktionerna för att göra detta filter finns på tomcat-wikin ( http://wiki.apache.org/tomcat/Tomcat/UTF-8 )

JSP-sidkodning

I din web.xml , lägg till följande:

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

Alternativt skulle alla JSP-sidor i webbappen behöva ha följande överst:

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

Om någon form av layout med olika JSP-fragment används, så behövs detta i alla av dem.

HTML-metataggar

JSP-sidakodning säger åt JVM att hantera tecknen på JSP-sidan med korrekt kodning. Sedan är det dags att tala om för webbläsaren i vilken kodning HTML-sidan är:

Detta görs med följande högst upp på varje xhtml-sida som produceras av webbappen:

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

När du använder en db måste det definieras att anslutningen använder UTF-8-kodning. Detta görs i context.xml eller varhelst JDBC-anslutningen är definierad enligt följande:

      <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-databas och tabeller

Den använda databasen måste använda UTF-8-kodning. Detta uppnås genom att skapa databasen med följande:

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

Sedan måste alla tabeller också vara 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;

Nyckeldelen är CHARSET=utf8 .

MySQL-serverkonfiguration

MySQL serveri måste också konfigureras. Vanligtvis görs detta i Windows genom att ändra my.ini -fil och i Linux genom att konfigurera my.cnf -fil.I dessa filer bör det definieras att alla klienter som är anslutna till servern använder utf8 som standardteckenuppsättning och att standardteckenuppsättningen som används av servern också är utf8.

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

   [mysql]
   default-character-set=utf8

Mysql-procedurer och funktioner

Dessa måste också ha teckenuppsättningen definierad. Till exempel:

   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-förfrågningar:latin1 och UTF-8

Om och när det är definierat i tomcats server.xml att GET-begäransparametrar är kodade i UTF-8, hanteras följande GET-begäranden korrekt:

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

Eftersom ASCII-tecken är kodade på samma sätt både med latin1 och UTF-8, hanteras strängen "Petteri" korrekt.

Det kyrilliska tecknet ж förstås inte alls på latin1. Eftersom Tomcat instrueras att hantera begärandeparametrar som UTF-8 kodar den det tecknet korrekt som %D0%B6 .

Om och när webbläsare instrueras att läsa sidorna i UTF-8-kodning (med förfrågningsrubriker och html-metatagg), kodar åtminstone Firefox 2/3 och andra webbläsare från denna period själva tecknet som %D0% B6 .

Slutresultatet är att alla användare med namnet "Petteri" hittas och även alla användare med namnet "ж" hittas.

Men hur är det med äåö?

HTTP-specifikationen definierar att webbadresser som standard kodas som latin1. Detta resulterar i att firefox2, firefox3 etc. kodar följande

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

in i den kodade versionen

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

På latin1 tecknet ä är kodad som %E4 . Även om sidan/förfrågan/allt är definierad för att använda UTF-8 . Den UTF-8-kodade versionen av ä är %C3%A4

Resultatet av detta är att det är helt omöjligt för webbappen att korrekt hantera förfrågningsparametrarna från GET-förfrågningar, eftersom vissa tecken är kodade i latin1 och andra i UTF-8.Obs:POST-förfrågningar fungerar eftersom webbläsare kodar alla förfrågningsparametrar från formulär helt i UTF-8 om sidan är definierad som UTF-8

Saker att läsa

Ett mycket stort tack till skribenterna av följande för att de gav svaren på mitt 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/

Viktig anmärkning

stöder Basic Multilingual Plane med 3-byte UTF-8-tecken. Om du behöver gå utanför det (vissa alfabet kräver mer än 3-byte UTF-8), måste du antingen använda en smak av VARBINARY kolumntyp eller använd utf8mb4 teckenuppsättning (vilket kräver MySQL 5.5.3 eller senare). Tänk bara på att använda utf8 teckenuppsättning i MySQL fungerar inte 100 % av tiden.

Tomcat med Apache

En sak till Om du använder Apache + Tomcat + mod_JK-kontakt måste du också göra följande ändringar:

  1. Lägg till URIEncoding="UTF-8" i filen tomcat server.xml för 8009-anslutningen, den används av mod_JK-anslutningen.
  2. Gå till din apache-mapp, dvs. /etc/httpd/conf och lägg till AddDefaultCharset utf-8 i httpd.conf-fil . Obs! Kontrollera först att den finns eller inte. Om det finns kan du uppdatera det med den här raden. Du kan också lägga till den här raden längst ner.


  1. Hur återställer man data från en raderad Docker-behållare? Hur återansluter man den till data?

  2. Bli av från en kolumn dubbletter av värden i två kolumner välj

  3. Crow's Foot Notation

  4. En dedikerad lagrad procedur för att få den senaste statusen för databassäkerhetskopiering