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&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
mysql 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:
- Adicione URIEncoding="UTF-8" no arquivo tomcat server.xml para o conector 8009, ele é usado pelo conector mod_JK.
- Vá para sua pasta do apache, ou seja,
/etc/httpd/conf
e adicioneAddDefaultCharset utf-8
emarquivo 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.