Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como obter o UTF-8 funcionando em aplicativos da web Java?


Responder a mim mesmo como o FAQ deste site encoraja isso. Isso funciona para mim:

Principalmente os caracteres äåö não são problemáticos, pois o conjunto de caracteres padrão usado por navegadores e tomcat/java para webapps é latin1 ie. ISO-8859-1 que "entende" esses caracteres.

Para que o UTF-8 funcione em Java+Tomcat+Linux/Windows+Mysql requer o seguinte:

Configurando o server.xml do Tomcat


É necessário configurar que o conector use UTF-8 para codificar os parâmetros de url (solicitação GET):
<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"
/>

A parte principal é URIEncoding="UTF-8" no exemplo acima. Isso garante que o Tomcat trate todos os parâmetros GET de entrada como codificados em UTF-8. Como resultado, quando o usuário escreve o seguinte na barra de endereços do navegador:
 https://localhost:8443/ID/Users?action=search&name=*ж*

o caractere ж é tratado como UTF-8 e é codificado (geralmente pelo navegador antes mesmo de chegar ao servidor) como %D0%B6 .

As solicitações POST não são afetadas por isso.

Filtro de caracteres


Em seguida, é hora de forçar o webapp java a lidar com todas as solicitações e respostas como codificados em UTF-8. Isso requer que definamos um filtro de conjunto de caracteres como o seguinte:
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() {
    }
}

Esse filtro garante que, se o navegador não tiver definido a codificação usada na solicitação, ela será definida como UTF-8.

A outra coisa feita por este filtro é definir a codificação de resposta padrão, ou seja. a codificação na qual o html/qualquer que seja retornado. A alternativa é definir a codificação de resposta etc. em cada controlador da aplicação.

Este filtro deve ser adicionado ao web.xml ou o descritor de implantação do 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>

As instruções para fazer esse filtro são encontradas no wiki do tomcat ( http://wiki.apache.org/tomcat/Tomcat/UTF-8 )

Codificação de página JSP


Em seu web.xml , adicione o seguinte:
<jsp-config>
    <jsp-property-group>
        <url-pattern>*.jsp</url-pattern>
        <page-encoding>UTF-8</page-encoding>
    </jsp-property-group>
</jsp-config>

Alternativamente, todas as páginas JSP do webapp precisariam ter o seguinte no topo delas:
 <%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>

Se algum tipo de layout com diferentes fragmentos JSP for usado, isso será necessário em todos deles.

metatags HTML


A codificação da página JSP diz à JVM para manipular os caracteres na página JSP na codificação correta. Então é hora de informar ao navegador em qual codificação a página html está:

Isso é feito com o seguinte na parte superior de cada página xhtml produzida pelo webapp:
   <?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' />
   ...

Conexão JDBC


Ao usar um db, deve-se definir que a conexão use a codificação UTF-8. Isso é feito em context.xml ou onde quer que a conexão JDBC seja definida da seguinte forma:
      <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"
    />

Banco de dados e tabelas MySQL


O banco de dados usado deve usar a codificação UTF-8. Isso é feito criando o banco de dados com o seguinte:
   CREATE DATABASE `ID_development` 
   /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_swedish_ci */;

Então, todas as tabelas precisam estar em UTF-8 também:
   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;

A parte principal é CHARSET=utf8 .

Configuração do servidor MySQL


O servidor MySQL também deve ser configurado. Normalmente, isso é feito no Windows modificando my.ini -file e no Linux configurando my.cnf -file.Nesses arquivos deve-se definir que todos os clientes conectados ao servidor usem utf8 como o conjunto de caracteres padrão e que o conjunto de caracteres padrão usado pelo servidor também seja utf8.
   [client]
   port=3306
   default-character-set=utf8

   [mysql]
   default-character-set=utf8

Procedimentos e funções do MySQL


Estes também precisam ter o conjunto de caracteres definido. Por exemplo:
   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 ;

Solicitações GET:latin1 e UTF-8


Se e quando for definido no server.xml do tomcat que os parâmetros de solicitação GET são codificados em UTF-8, as seguintes solicitações GET são tratadas corretamente:
   https://localhost:8443/ID/Users?action=search&name=Petteri
   https://localhost:8443/ID/Users?action=search&name=ж

Como os caracteres ASCII são codificados da mesma maneira com latin1 e UTF-8, a string "Petteri" é tratada corretamente.

O caractere cirílico ж não é entendido em latim1. Como o Tomcat é instruído a lidar com parâmetros de solicitação como UTF-8, ele codifica esse caractere corretamente como %D0%B6 .

Se e quando os navegadores são instruídos a ler as páginas na codificação UTF-8 (com cabeçalhos de solicitação e meta-tag html), pelo menos o Firefox 2/3 e outros navegadores desse período codificam o caractere como %D0% B6 .

O resultado final é que todos os usuários com o nome "Petteri" são encontrados e também todos os usuários com o nome "ж" são encontrados.

Mas e äåö?


A especificação HTTP define que, por padrão, os URLs são codificados como latin1. Isso resulta em firefox2, firefox3 etc. codificando o seguinte
    https://localhost:8443/ID/Users?action=search&name=*Päivi*

na versão codificada
    https://localhost:8443/ID/Users?action=search&name=*P%E4ivi*

Em latin1 o caractere ä está codificado como %E4 . Mesmo que a página/solicitação/tudo esteja definido para usar UTF-8 . A versão codificada em UTF-8 de ä é %C3%A4

O resultado disso é que é quase impossível para o webapp manipular corretamente os parâmetros de solicitação de solicitações GET, pois alguns caracteres são codificados em latin1 e outros em UTF-8.Aviso:solicitações POST funcionam porque os navegadores codificam todos os parâmetros de solicitação de formulários completamente em UTF-8 se a página for definida como UTF-8

Coisas para ler


Um grande obrigado aos escritores do seguinte por dar as respostas para o meu problema:
  • 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/

Observação importante


suporta o Plano multilíngue básico usando caracteres UTF-8 de 3 bytes. Se você precisar sair disso (certos alfabetos exigem mais de 3 bytes de UTF-8), então você precisa usar um tipo de VARBINARY tipo de coluna ou use o utf8mb4 conjunto de caracteres (que requer MySQL 5.5.3 ou posterior). Esteja ciente de que usar o utf8 conjunto de caracteres no MySQL não funcionará 100% do tempo.

Tomcat com Apache


Mais uma coisa Se você estiver usando o conector Apache + Tomcat + mod_JK, também precisará fazer as seguintes alterações:
  1. Adicione URIEncoding="UTF-8" no arquivo tomcat server.xml para o conector 8009, ele é usado pelo conector mod_JK.
  2. Vá para sua pasta do apache, ou seja, /etc/httpd/conf e adicione AddDefaultCharset utf-8 em arquivo httpd.conf . Observação: Primeiro verifique se existe ou não. Se existir você pode atualizá-lo com esta linha. Você também pode adicionar esta linha na parte inferior.