Отговарям сам, тъй като често задаваните въпроси на този сайт го насърчават. Това работи за мен:
Предимно символите äåö не са проблем, тъй като наборът от символи по подразбиране, използван от браузърите и tomcat/java за уеб приложения, е latin1 т.е. ISO-8859-1, който "разбира" тези знаци.
За да накарате UTF-8 да работи под Java+Tomcat+Linux/Windows+Mysql изисква следното:
Конфигуриране на server.xml на Tomcat
Необходимо е да конфигурирате, че конекторът използва UTF-8 за кодиране на параметри на url (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"
/>
Ключовата част е URIEncoding="UTF-8" в горния пример. Това гарантира, че Tomcat обработва всички входящи GET параметри като UTF-8 кодирани. В резултат на това, когато потребителят напише следното в адресната лента на браузъра:
https://localhost:8443/ID/Users?action=search&name=*ж*
символът ж се обработва като UTF-8 и се кодира (обикновено от браузъра, преди дори да стигне до сървъра) като %D0%B6 .
POST заявките не са засегнати от това.
CharsetFilter
Тогава е време да принудите java webapp да обработва всички заявки и отговори като UTF-8 кодирани. Това изисква да дефинираме филтър за набор от знаци, както следва:
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() {
}
}
Този филтър гарантира, че ако браузърът не е задал кодирането, използвано в заявката, то е настроено на UTF-8.
Другото нещо, което прави този филтър е да зададе кодирането на отговора по подразбиране, т.е. кодирането, в което е върнатият html/каквото и да е. Алтернативата е да зададете кодиране на отговор и т.н. във всеки контролер на приложението.
Този филтър трябва да бъде добавен към web.xml или дескриптора за внедряване на уеб приложението:
<!--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>
Инструкциите за създаване на този филтър се намират в tomcat wiki ( http://wiki.apache.org/tomcat/Tomcat/UTF-8 )
JSP кодиране на страница
Във вашия web.xml , добавете следното:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
Като алтернатива, всички JSP-страници на уеб приложението ще трябва да имат следното в горната част на тях:
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
Ако се използва някакъв вид оформление с различни JSP-фрагменти, то това е необходимо във всички от тях.
HTML-мета тагове
JSP кодирането на страницата казва на JVM да обработва знаците в JSP страницата в правилното кодиране. След това е време да каже на браузъра в кое кодиране е html страницата:
Това се прави със следното в горната част на всяка xhtml страница, създадена от уеб приложението:
<?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-връзка
Когато използвате db, трябва да се дефинира, че връзката използва UTF-8 кодиране. Това се прави в context.xml или където и да се дефинира JDBC връзката, както следва:
<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"
/>
MySQL база данни и таблици
Използваната база данни трябва да използва UTF-8 кодиране. Това се постига чрез създаване на база данни със следното:
CREATE DATABASE `ID_development`
/*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_swedish_ci */;
След това всички таблици трябва също да са в 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;
Ключовата част е CHARSET=utf8 .
Конфигурация на MySQL сървър
MySQL сървърите също трябва да бъдат конфигурирани. Обикновено това се прави в Windows чрез модифициране на my.ini -file и в Linux, като конфигурирате my.cnf -file. В тези файлове трябва да се дефинира, че всички клиенти, свързани към сървъра, използват utf8 като набор от символи по подразбиране и че наборът от знаци по подразбиране, използван от сървъра, също е utf8.
[client]
port=3306
default-character-set=utf8
[mysql]
default-character-set=utf8
Mysql процедури и функции
Те също трябва да имат дефиниран набор от знаци. Например:
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 заявки:latin1 и UTF-8
Ако и когато в server.xml на tomcat е дефинирано, че параметрите на GET заявка са кодирани в UTF-8, следните GET заявки се обработват правилно:
https://localhost:8443/ID/Users?action=search&name=Petteri
https://localhost:8443/ID/Users?action=search&name=ж
Тъй като ASCII-символите са кодирани по един и същи начин както с latin1, така и с UTF-8, низът „Petteri“ се обработва правилно.
Кирилицата ж изобщо не се разбира на латиница1. Тъй като Tomcat е инструктиран да обработва параметрите на заявката като UTF-8, той кодира този знак правилно като %D0%B6 .
Ако и когато браузърите са инструктирани да четат страниците в UTF-8 кодиране (със заглавки на заявка и html мета-таг), поне Firefox 2/3 и други браузъри от този период всички кодират самите символа като %D0% B6 .
Крайният резултат е, че всички потребители с име "Petteri" са открити, както и всички потребители с името "ж".
Но какво ще кажете за äåö?
HTTP-спецификацията дефинира, че по подразбиране URL адресите са кодирани като latin1. Това води до firefox2, firefox3 и т.н., които кодират следното
https://localhost:8443/ID/Users?action=search&name=*Päivi*
в кодираната версия
https://localhost:8443/ID/Users?action=search&name=*P%E4ivi*
В latin1 знакът ä е кодиран като %E4 . Въпреки че страницата/заявката/всичко е дефинирано да използва UTF-8 . Кодираната в UTF-8 версия на ä е %C3%A4
Резултатът от това е, че е доста невъзможно уеб приложението да обработва правилно параметрите на заявката от GET заявки, тъй като някои знаци са кодирани в latin1, а други в UTF-8.Забележка:POST заявките работят, тъй като браузърите кодират всички параметри на заявката от формуляри изцяло в UTF-8, ако страницата е дефинирана като UTF-8
Неща за четене
Много благодаря на авторите на следното, че дадоха отговорите на моя проблем:
- 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/
Важна забележка
mysql
поддържа Основна многоезична равнина
използвайки 3-байтови UTF-8 символи. Ако трябва да излезете извън това (определени азбуки изискват повече от 3 байта UTF-8), тогава или трябва да използвате VARBINARY
тип колона или използвайте utf8mb4код> набор от символи
(което изисква MySQL 5.5.3 или по-нова версия). Само имайте предвид, че с помощта на utf8
наборът от символи в MySQL няма да работи в 100% от случаите.
Tomcat с Apache
Още нещо Ако използвате Apache + Tomcat + mod_JK конектор, тогава трябва да направите и следните промени:
- Добавете URIEncoding="UTF-8" във файла tomcat server.xml за 8009 конектор, използва се от mod_JK конектор.
- Отидете до вашата папка Apache, т.е.
/etc/httpd/conf
и добаветеAddDefaultCharset utf-8
вhttpd.conf файл
. Забележка: Първо проверете дали съществува или не. Ако има, можете да го актуализирате с този ред. Можете също да добавите този ред в долната част.