Zachęcam do udzielania odpowiedzi na często zadawane pytania na tej stronie. To działa dla mnie:
Przeważnie znaki äåö nie stanowią problemu, ponieważ domyślnym zestawem znaków używanym przez przeglądarki i tomcat / java dla aplikacji internetowych jest latin1, tj. ISO-8859-1, która „rozumie” te znaki.
Aby UTF-8 działał pod Javą + Tomcat + Linux / Windows + Mysql wymaga:
Konfigurowanie serwera.xml serwera Tomcat
Konieczne jest skonfigurowanie, aby łącznik używa UTF-8 do kodowania parametrów adresu URL (żądanie 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"
/>
Kluczową częścią jest URIEncoding = "UTF-8" w powyższym przykładzie. To gwarantuje, że Tomcat obsługuje wszystkie przychodzące parametry GET jako kodowane w UTF-8. W rezultacie, gdy użytkownik zapisze w pasku adresu przeglądarki:
https://localhost:8443/ID/Users?action=search&name=*ж*
znak ж jest obsługiwany jako UTF-8 i jest zakodowany (zwykle przez przeglądarkę, zanim nawet dostanie się na serwer) jako % D0% B6 .
Nie ma to wpływu na żądanie POST.
CharsetFilter
Następnie nadszedł czas, aby zmusić aplikację Java do obsługi wszystkich żądań i odpowiedzi w postaci zakodowanej w UTF-8. Wymaga to zdefiniowania filtru zestawu znaków, takiego jak:
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() {
}
}
Filtr ten upewnia się, że jeśli przeglądarka nie ustawiła kodowania użytego w żądaniu, to jest ustawiona na UTF-8.
Inną czynnością wykonaną przez ten filtr jest ustawienie domyślnego kodowania odpowiedzi, tj. kodowanie, w którym zwracany html / cokolwiek jest. Alternatywą jest ustawienie kodowania odpowiedzi itp. W każdym kontrolerze aplikacji.
Ten filtr należy dodać do pliku web.xml lub deskryptora wdrażania aplikacji internetowej:
<!--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>
Instrukcje tworzenia tego filtra można znaleźć na wiki tomcat ( http://wiki.apache.org/tomcat/Tomcat/UTF-8 )
Kodowanie strony JSP
W pliku web.xml dodaj:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
Alternatywnie, wszystkie strony JSP aplikacji internetowej musiałyby mieć na górze następujące elementy:
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
Jeśli używany jest jakiś układ z różnymi fragmentami JSP, jest to potrzebne we wszystkich z nich.
Tagi meta HTML
Kodowanie strony JSP informuje JVM, aby obsługiwał znaki na stronie JSP w prawidłowym kodowaniu. Następnie nadszedł czas, aby poinformować przeglądarkę, w którym kodowaniu jest strona HTML:
Odbywa się to w następujący sposób u góry każdej strony xhtml utworzonej przez aplikację internetową:
<?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' />
...
Połączenie JDBC
Podczas korzystania z bazy danych należy zdefiniować, że połączenie korzysta z kodowania UTF-8. Odbywa się to w pliku context.xml lub wszędzie tam, gdzie połączenie JDBC nie działa, w następujący sposób:
<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"
/>
Baza danych i tabele MySQL
Użyta baza danych musi używać kodowania UTF-8. Osiąga się to poprzez utworzenie bazy danych z następującymi elementami:
CREATE DATABASE `ID_development`
/*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_swedish_ci */;
Następnie wszystkie tabele muszą znajdować się w 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;
Kluczową częścią jest CHARSET = utf8 .
Konfiguracja serwera MySQL
Serwery MySQL również muszą zostać skonfigurowane. Zazwyczaj odbywa się to w Windows modyfikując my.ini -file iw Linux przez skonfigurowanie my.cnf -file. W tych plikach należy zdefiniować, że wszyscy klienci podłączeni do serwera używają utf8 jako domyślnego zestawu znaków oraz że domyślnym zestawem znaków używanym przez serwer jest również utf8.
[client]
port=3306
default-character-set=utf8
[mysql]
default-character-set=utf8
Procedury i funkcje MySQL
Te również muszą mieć zdefiniowany zestaw znaków. Na przykład:
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 ;
Żądania GET: latin1 i UTF-8
Jeśli i kiedy zostanie zdefiniowane w pliku server.xml tomcat, że parametry żądania GET są kodowane w UTF-8, następujące żądania GET są obsługiwane poprawnie:
https://localhost:8443/ID/Users?action=search&name=Petteri
https://localhost:8443/ID/Users?action=search&name=ж
Ponieważ znaki ASCII są kodowane w taki sam sposób zarówno w przypadku latin1, jak i UTF-8, ciąg „Petteri” jest obsługiwany poprawnie.
Cyrylica ж w ogóle nie jest rozumiana w języku łacińskim1. Ponieważ Tomcat jest poinstruowany, aby obsługiwać parametry żądania jako UTF-8, poprawnie koduje ten znak jako % D0% B6 .
Jeśli i kiedy przeglądarki zostaną poinstruowane, aby czytać strony w kodowaniu UTF-8 (z nagłówkami żądań i metatagiem HTML), przynajmniej Firefox 2/3 i inne przeglądarki z tego okresu same kodują znak jako % D0% B6 .
W rezultacie znaleziono wszystkich użytkowników o nazwie „Petteri”, a także wszystkich użytkowników o nazwie „ж”.
Ale co z äåö?
Specyfikacja HTTP określa, że domyślnie adresy URL są kodowane jako latin1. Powoduje to, że firefox2, firefox3 itp. Kodują następujące
https://localhost:8443/ID/Users?action=search&name=*Päivi*
w wersji zakodowanej
https://localhost:8443/ID/Users?action=search&name=*P%E4ivi*
W Latin1 znak ä jest zakodowany jako % E4 . Mimo że strona / żądanie / wszystko jest zdefiniowane do używania UTF-8 . Wersja ä zakodowana w UTF-8 to % C3% A4
Wynikiem tego jest to, że aplikacja internetowa nie może poprawnie obsługiwać parametrów żądań z żądań GET, ponieważ niektóre znaki są kodowane w latin1, a inne w UTF-8.
Uwaga: żądania POST działają, ponieważ przeglądarki kodują wszystkie parametry żądań z formularzy całkowicie w UTF-8, jeśli strona jest zdefiniowana jako UTF-8
Rzeczy do przeczytania
Bardzo dziękuję autorom następujących artykułów za udzielenie odpowiedzi na mój 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/
Ważna uwaga
mysqlobsługuje podstawową płaszczyznę wielojęzyczną przy użyciu 3-bajtowych znaków UTF-8. Jeśli musisz wyjść poza to (niektóre alfabety wymagają więcej niż 3 bajtów UTF-8), musisz użyć smaku VARBINARY
typu kolumny lub utf8mb4
zestawu znaków (który wymaga MySQL 5.5.3 lub nowszego). Pamiętaj tylko, że użycie utf8
zestawu znaków w MySQL nie będzie działać w 100% przypadków.
Tomcat z Apache
Jeszcze jedna rzecz Jeśli używasz łącznika Apache + Tomcat + mod_JK, musisz także wprowadzić następujące zmiany:
- Dodaj URIEncoding = "UTF-8" do pliku tomcat server.xml dla złącza 8009, jest on używany przez złącze mod_JK.
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
- Goto Twój apache folderu tzn
/etc/httpd/conf
i dodać AddDefaultCharset utf-8
w httpd.conf file
. Uwaga: Najpierw sprawdź, czy istnieje, czy nie. Jeśli istnieje, możesz zaktualizować go o tę linię. Możesz dodać tę linię również na dole.