Мне нужно, чтобы UTF-8 работал в моем Java webapp (сервлеты + JSP, без использования фреймворка) для поддержки äöå
и т.д. для обычного финского текста и кириллических алфавитов, таких как ЦжФ
для особых случаев.
Моя настройка такова:
Используемая база данных: MySQL 5.x
Пользователи в основном используют Firefox2, но для доступа к сайту используются Opera 9.x, FF3, IE7 и Google Chrome.
Как это сделать?
Отвечая на вопрос, как часто задаваемые вопросы этого сайта поощряют его. Это работает для меня:
В основном символы äåö не являются проблематичными, поскольку набор символов по умолчанию, используемый браузерами, и tomcat/java для webapps - latin1, т.е. ISO-8859-1, который "понимает" эти символы.
Чтобы получить UTF-8, работающий под Java + Tomcat + Linux/Windows + Mysql, требуется следующее:
Необходимо настроить, чтобы соединитель использовал 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 не влияет на это.
Затем настало время заставить 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/whatever. Альтернативой является установка кодировки ответа и т.д. В каждом контроллере приложения.
Этот фильтр необходимо добавить в web.xml или дескриптор развертывания 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>
Инструкции для создания этого фильтра находятся в tomcat wiki ( http://wiki.apache.org/tomcat/Tomcat/UTF-8)
В web.xml добавьте следующее:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
В качестве альтернативы, все JSP-страницы webapp должны иметь следующее в верхней части:
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
Если используется какой-то макет с различными JSP-фрагментами, то это необходимо в all из них.
Кодирование страницы JSP сообщает JVM обрабатывать символы на странице JSP в правильной кодировке. Затем настало время сообщить vrowser, в котором кодировка html-страницы:
Это делается с помощью следующего в верхней части каждой xhtml-страницы, созданной 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' />
...
При использовании 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"
/>
Используемая база данных должна использовать кодировку 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 serveri. Обычно это делается в Windows путем изменения my.ini -file и в Linux путем настройки my.cnf -file. В этих файлах должно быть определено, что все клиенты, подключенные к серверу, используют utf8 в качестве набора символов по умолчанию и что кодировка по умолчанию, используемая сервером, также является utf8.
[client]
port=3306
default-character-set=utf8
[mysql]
default-character-set=utf8
Они также должны иметь определенный набор символов. Например:
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 ;
Если и когда он определен в tomcat server.xml, параметры запроса GET закодированы в UTF-8, обрабатываются следующие запросы GET:
https://localhost:8443/ID/Users?action=search&name=Petteri
https://localhost:8443/ID/Users?action=search&name=ж
Поскольку символы ASCII кодируются одинаково с латинскими и 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*
В латинском языке символ ä кодируется как % E4. Несмотря на то, что страница/запрос/все определено для использования UTF-8. Закодированная версия UTF-8 ä имеет значение % C3% A4
Результатом этого является то, что webapp не может корректно обрабатывать параметры запроса из запросов GET, поскольку некоторые символы кодируются в latin1 и другие в UTF-8. Примечание: запросы POST работают, поскольку браузеры кодируют все параметры запроса из форм полностью в UTF-8, если страница определена как UTF-8
Очень большое спасибо за авторов следующих за ответы на мои проблемы:
mysql поддерживает Базовая многоязычная плоскость с использованием 3-байтных символов UTF-8. Если вам нужно выйти за пределы этого (для некоторых алфавитов требуется более 3 байтов UTF-8), вам нужно либо использовать атрибут типа столбца VARBINARY
, либо использовать utf8mb4
набор символов (для чего требуется MySQL 5.5.3 или новее). Просто имейте в виду, что использование набора символов utf8
в MySQL не будет работать в течение 100% времени.
Еще одна вещь. Если вы используете соединитель Apache + Tomcat + mod_JK, вам также необходимо выполнить следующие изменения:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
/etc/httpd/conf
и добавьте AddDefaultCharset utf-8
в httpd.conf file
. Примечание.. Сначала убедитесь, что он существует или нет. Если существует, вы можете обновить его с помощью этой строки. Вы также можете добавить эту строку внизу.pageEncoding
, так что вы даже можете оставить это в стороне. 2) в базе данных MySQL и таблицах, которые вы использовали utf8_swedish_si
, это должен был быть utf8_unicode_ci
. Вы можете даже оставить параметры сортировки, достаточно просто использовать CHARACTER SET utf8
.
Я думаю, вы хорошо подвели его в своем собственном ответе.
В процессе UTF-8-ing (?) из конца в конец вы также можете убедиться, что сам java использует UTF-8. Используйте -Dfile.encoding = utf-8 как параметр для JVM (можно настроить в catalina.bat).
Чтобы добавить к ответ kosoant, если вы используете Spring, вместо того, чтобы писать собственный фильтр сервлета, вы можете использовать класс org.springframework.web.filter.CharacterEncodingFilter
, который они предоставляют, настраивая его следующим образом в вашем 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>
Я хочу также добавить из здесь эта часть решила мою проблему с utf:
runtime.encoding=<encoding>
Хороший подробный ответ. просто хотел добавить еще одну вещь, которая определенно поможет другим увидеть кодировку UTF-8 в URL-адресах в действии.
Выполните следующие действия, чтобы включить кодировку UTF-8 в URL-адресах в firefox.
введите "about: config" в адресной строке.
Используйте тип ввода фильтра для поиска свойства "network.standard-url.encode-query-utf8".
Кодировка UTF-8 по URL-адресам работает по умолчанию в IE6/7/8 и хром.
Это для греческого кодирования в таблицах MySql, когда мы хотим получить к ним доступ с помощью Java:
Используйте следующую настройку соединения в пуле соединений 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>
Если вы не хотите помещать это в пул соединений JNDI, вы можете настроить его как JDBC-url, как показано на следующей строке:
jdbc:mysql://192.168.10.123:3308/mydatabase?characterEncoding=greek
Для меня и Ника, поэтому мы никогда не забываем об этом и теряем время.
Некоторое время вы можете решить проблему через мастер администратора MySQL. В
Переменные запускa > Дополнительно >
и установите Def. char Set: utf8
Возможно, этой конфигурации необходимо перезапустить MySQL.
О CharsetFilter
, упомянутом в ответе @kosoant....
В tomcat web.xml
есть место сборки Filter
(находится в conf/web.xml
). Фильтр имеет имя setCharacterEncodingFilter
и прокомментирован по умолчанию. Вы можете раскомментировать это (пожалуйста, не забудьте раскомментировать его filter-mapping
)
Также нет необходимости устанавливать jsp-config
в web.xml
(у меня есть тест для Tomcat 7+)
Еще один момент, о котором не упоминалось, относится к Java Servlets, работающему с Ajax. У меня есть ситуации, когда веб-страница собирает текст utf-8 от пользователя, отправляющего его в файл JavaScript, который включает его в URI, отправленный на Servlet. Servlet запрашивает базу данных, фиксирует результат и возвращает его как XML в файл JavaScript, который форматирует его и вставляет отформатированный ответ на исходную веб-страницу.
В одном веб-приложении я следил за ранними инструкциями по книге Ajax для того, чтобы обернуть JavaScript при построении URI. В примере в книге использовался метод escape(), который я обнаружил (трудный путь) неправильно. Для utf-8 вы должны использовать encodeURIComponent().
Немногие люди, похоже, катят свой Ajax в эти дни, но я думал, что могу добавить это.
В моем случае отображения символа Юникода из пакетов сообщений мне не нужно применять раздел "Копирование страницы JSP", чтобы отображать Unicode на моей странице jsp. Все, что мне нужно, это раздел "CharsetFilter".
У меня есть аналогичная проблема, но в файлах файла я сжимаю с помощью apache. Итак, я решил это с помощью этой команды:
convmv --notest -f cp1252 -t utf8 * -r
он работает очень хорошо для меня. Надеюсь, что это поможет кому угодно;)
Если вы указали в пуле соединений (mysql-ds.xml), в своем Java-коде вы можете открыть соединение следующим образом:
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Connection conn = DriverManager.getConnection(
"jdbc:mysql://192.168.1.12:3308/mydb?characterEncoding=greek",
"Myuser", "mypass");