it-swarm.dev

Como obter o UTF-8 trabalhando em Java webapps?

Eu preciso fazer o UTF-8 funcionar no meu Java webapp (servlets + JSP, nenhuma estrutura usada) para suportar äöå etc. para textos finlandeses regulares e alfabetos cirílicos como ЦжФ para casos especiais.

Minha configuração é a seguinte:

  • Ambiente de desenvolvimento: Windows XP
  • Ambiente de produção: Debian

Banco de dados usado: MySQL 5.x

Os usuários usam principalmente Firefox2, mas também Opera 9.x, FF3, IE7 e Google Chrome são usados ​​para acessar o site.

Como conseguir isso?

360
kosoant

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

Principalmente os caracteres äåö não são problemáticos, já que o conjunto de caracteres padrão usado pelos navegadores e pelo Tomcat/Java para webapps é latin1 ie. ISO-8859-1 que "entende" esses caracteres.

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

Configurando o server.xml do Tomcat

É necessário configurar que o conector use UTF-8 para codificar 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 chave sendo URIEncoding = "UTF-8" no exemplo acima. Esta quarantees que o Tomcat manipula 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ço do navegador:

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

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

A solicitação POST não é afetada por isso.

CharsetFilter

Então é hora de forçar o webapp Java a manipular todos os pedidos 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 ie. a codificação em que o html retornado/o que quer que seja. A alternativa é definir a codificação de resposta, etc., em cada controlador do aplicativo.

Este filtro deve ser adicionado ao web.xml ou o descritor de implementação da 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 este filtro são encontradas no Tomcat wiki (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>

Como alternativa, todas as páginas JSP do aplicativo da web 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 de JSP for usado, isso é necessário todos deles.

Tags HTML-meta

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 dizer ao navegador no qual a codificação da página html é:

Isso é feito com o seguinte na parte superior de cada página xhtml produzida pela 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 banco de dados, é necessário definir que a conexão usa a codificação UTF-8. Isso é feito em context.xml ou sempre que a conexão JDBC for definida da seguinte maneira:

      <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 do MySQL

O banco de dados usado deve usar a codificação UTF-8. Isso é obtido 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 chave sendo 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 -Arquivo. Nesses arquivos, deve ser definido que todos os clientes conectados ao servidor usem o 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 é definido no server.xml do Tomcat que os parâmetros da 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, tanto com o latin1 quanto com o UTF-8, a string "Petteri" é manipulada corretamente.

O caráter cirílico não é compreendido em latim1. Como o Tomcat é instruído a manipular os parâmetros de solicitação como UTF-8, ele codifica esse caractere corretamente % D0% B6.

Se e quando os navegadores forem 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 quanto a äåö?

A especificação HTTP define que, por padrão, as URLs são codificadas como latin1. Isso resulta em firefox2, firefox3 etc. codificando o seguinte

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

para a versão codificada

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

Em latin1 o personagem uma é codificado como % E4. Mesmo que a página/request/everything esteja definida para usar UTF-8 . A versão codificada em UTF-8 de ä é % C3% A4

O resultado disso é que é praticamente impossível para o webapp lidar com os parâmetros de requisição GET, pois alguns caracteres são codificados em latin1 e outros em UTF-8. Aviso: POST pedidos funcionam como navegadores codificam todos os parâmetros de solicitação de formulários completamente em UTF-8 se a página é definida como sendo UTF-8

Coisas para ler

Um grande obrigado pelos escritores dos seguintes para 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/

Nota importante

mysql suporta o Basic Multilingual Plane usando caracteres UTF-8 de 3 bytes. Se você precisar ir além disso (certos alfabetos requerem mais de 3 bytes de UTF-8), então você precisa usar um tipo de coluna VARBINARY ou usar o utf8mb4 character set (que requer o MySQL 5.5.3 ou posterior). Apenas esteja ciente de que usar o conjunto de caracteres utf8 no MySQL não funcionará 100% do tempo.

Tomcat com Apache

Mais uma coisa Se você estiver usando o conector mod_JK do Apache + Tomcat +, também precisará fazer as seguintes alterações:

  1. Adicione URIEncoding = "UTF-8" ao arquivo server.xml do Tomcat para o conector 8009, ele é usado pelo conector mod_JK. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
  2. Vá para sua pasta Apache, ou seja, /etc/httpd/conf e adicione AddDefaultCharset utf-8 em httpd.conf file. Nota: Primeiro verifique se existe ou não. Se existir, você pode atualizá-lo com esta linha. Você pode adicionar essa linha na parte inferior também.
540
kosoant

Eu acho que você resumiu bem em sua própria resposta.

No processo de UTF-8-ing (?) De ponta a ponta, você também pode querer ter certeza de que Java está usando UTF-8. Use -Dfile.encoding = utf-8 como parâmetro para a JVM (pode ser configurado em catalina.bat).

12
stian

Para adicionar a resposta do kosoant , se você estiver usando o Spring, em vez de escrever seu próprio filtro de Servlet, você pode usar a classe org.springframework.web.filter.CharacterEncodingFilter que eles fornecem, configurando-o da seguinte forma em seu 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

Eu também quero adicionar a partir de aqui esta parte resolveu meu problema utf:

runtime.encoding=<encoding>
2
John

Boa resposta detalhada. só queria adicionar mais uma coisa que definitivamente ajudará outras pessoas a ver a codificação UTF-8 em URLs em ação.

Siga as etapas abaixo para ativar a codificação UTF-8 em URLs no firefox.

  1. digite "about: config" na barra de endereço.

  2. Use o tipo de entrada de filtro para procurar a propriedade "network.standard-url.encode-query-utf8".

  3. a propriedade acima será falsa por padrão, transformar isso em TRUE.
  4. reinicie o navegador.

A codificação UTF-8 em URLs funciona por padrão no IE6/7/8 e no Chrome.

1
Jay

Isto é para codificação grega em tabelas MySql quando queremos acessá-las usando Java:

Use a seguinte configuração de conexão no seu pool de conexões do JBoss (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>

Se você não quiser colocar isso em um pool de conexão JNDI, poderá configurá-lo como um URL JDBC, como mostra a próxima linha:

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

Para mim e Nick, então nunca esquecemos e perdemos mais tempo .....

1
Mike Mountrakis

Algum tempo você pode resolver problemas através do assistente do MySQL Administrator. Em

Variáveis ​​de inicialização> Avançado>

e defina Def. char Conjunto: utf8

Talvez essa configuração precise reiniciar o MySQL.

0
user3600935

Respostas anteriores não funcionaram com o meu problema. Foi apenas em produção, com o Tomcat e o Apache mod_proxy_ajp. Post corpo perdido não ascii chars por? O problema finalmente foi com o defaultCharset da JVM (US-ASCII em uma instalação padrão: Charset dfset = Charset.defaultCharset ();) então, a solução foi executada no servidor Tomcat com um modificador para executar a JVM com UTF-8 como charset padrão:

Java_OPTS="$Java_OPTS -Dfile.encoding=UTF-8" 

(adicione esta linha ao catalina.sh e reinicie o serviço Tomcat)

Talvez você também deva alterar a variável do sistema linux (edit ~/.bashrc e ~/.profile para mudanças permanentes, veja https://perlgeek.de/en/article/set-up-a-clean-utf8- ambiente )

export LC_ALL = en_US.UTF-8
exportar LANG = en_US.UTF-8

exportar LANGUAGE = en_US.UTF-8

0
Rogelio

Enfrentou o mesmo problema no Spring MVC 5 + Tomcat 9 + JSP.
Após a longa pesquisa, chegou-se a uma solução elegante (não need filters e no need changes = no Tomcat server.xml (a partir da versão 8.0.0-RC3))

  1. Na implementação WebMvcConfigurer, defina a codificação padrão para messageSource (para ler dados de arquivos de origem de mensagens na codificação UTF-8.

    @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. Na implementação do DispatcherServletInitializer, @Override o método onStartup e configure a codificação de caracteres de recurso e recurso.

    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. Salve toda a fonte de mensagens e visualize arquivos na codificação UTF-8.

  4. Adicionar <% @ página contentType = "text/html; charset = UTF-8"%> o <% @ page pageEncoding = "UTF-8"%> em cada arquivo * .jsp o adicionar o descritor jsp-config ao web.xml

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

Sobre CharsetFilter mencionado na resposta @kosoant ....

Há um build em Filter no Tomcat web.xml (localizado em conf/web.xml). O filtro é denominado setCharacterEncodingFilter e é comentado por padrão. Você pode descomentar isto (Por favor, lembre-se de descomentar o seu filter-mapping também)

Também não é necessário definir jsp-config no seu web.xml (testei para o Tomcat 7+)

0
Alireza Fattahi

Para o meu caso de exibir caracteres Unicode a partir de pacotes de mensagens, não preciso aplicar a seção "Codificação de páginas JSP" para exibir Unicode na minha página jsp. Tudo que eu preciso é a seção "CharsetFilter".

0
bnguyen82

Eu estou com um problema semelhante, mas, em nomes de arquivos de um arquivo estou compactando com Apache commons. Então resolvi com este comando:

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

funciona muito bem para mim. Espero que ajude alguém;)

0
caarlos0

Um outro ponto que não foi mencionado refere-se a Java Servlets trabalhando com o Ajax. Eu tenho situações em que uma página da web está pegando texto utf-8 do usuário enviando isso para um arquivo JavaScript que o inclui em um URI enviado para o Servlet. O Servlet consulta um banco de dados, captura o resultado e o retorna como XML para o arquivo JavaScript que o formata e insere a resposta formatada na página da Web original.

Em um aplicativo da web, eu estava seguindo as instruções de um livro antigo do Ajax para encapsular o JavaScript na construção do URI. O exemplo no livro usado o método escape (), que eu descobri (da maneira mais difícil) está errado. Para utf-8 você deve usar encodeURIComponent ().

Poucas pessoas parecem rolar seu próprio Ajax nos dias de hoje, mas eu pensei que poderia acrescentar isso também.

0
David