Как получить UTF-8 работает в Java webapps?

мне нужно, чтобы UTF-8 работал в моем Java webapp (сервлеты + JSP, не используется фреймворк) для поддержки äöå etc. для обычного финского текста и кириллических алфавитов, таких как ЦжФ для особых случаев.

Мои настройки следующие:

  • среда разработки: Windows XP
  • производственная среда: Debian

используемая база данных: MySQL 5.x

пользователи в основном используют Firefox2, но и Opera 9.x, FF3, IE7 и Google Chrome используется для доступа к сайту.

как этого добиться?

13 ответов


отвечая себе, как FAQ этого сайта поощряет его. Это работает для меня:

в основном символы äåö не являются проблемой, поскольку набор символов по умолчанию, используемый браузерами и tomcat / java для webapps, является latin1 ie. ISO-8859-1, который "понимает" эти символы.

чтобы получить UTF-8, работающий под Java + Tomcat + Linux/Windows + Mysql, требуется следующее:

настройка сервера Tomcat.в XML

необходимо настройте, что соединитель использует UTF-8 для кодирования параметров url (GET request):

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

другой вещь, сделанная этим фильтром, - установить кодировку ответа по умолчанию ie. кодировка, в которой возвращается 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>

инструкции по созданию этого фильтра находятся в котяра Вики (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-страницы webapp должны иметь в верхней части следующее:

 <%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>

если используется какой-то макет с разными JSP-фрагментами, то это необходимо в все из них.

в HTML-meta теги

кодировка страницы JSP сообщает JVM обрабатывать символы на странице JSP в правильной кодировке. Тогда пришло время сообщить браузеру, в какой кодировке находится 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' />
   ...

JDBC-соединение

при использовании БД, необходимо определить, что соединение использует кодировку UTF-8. Это делается в контексте.в 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&amp;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 serveri также должен быть настроен. Обычно это делается в Windows путем изменения мой.ini -файл и в Linux по настройке мой.cnf -файл. В этих файлах должно быть определено, что все клиенты, подключенные к серверу, используют 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 ;

вам запросы: latin1 и UTF-8

если и когда он определен на сервере tomcat.xml, которые получают параметры запроса кодируются в 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" обрабатывается правильно.

кириллица ж в латинском языке вообще не понимается. Потому что Tomcat поручено обрабатывать параметры запроса как UTF-8 it кодирует этот символ правильно как %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

результат из этого следует, что для webapp совершенно невозможно корректно обрабатывать параметры запроса из 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 connector тогда вам также необходимо сделать следующие изменения:

  1. добавить URIEncoding= "UTF-8"в сервер tomcat.xml-файл для соединителя 8009, он используется соединителем mod_JK. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
  2. перейти к папке apache, т. е. /etc/httpd/conf и добавить AddDefaultCharset utf-8 на httpd.conf file. Примечание: сначала проверьте, существует он или нет. Если существует, вы можете обновить его с помощью этой строки. Вы также можете добавить эту строку внизу.

Я думаю, вы очень хорошо подытожили это в своем собственном ответе.

в процессе UTF-8-ing(?) из конца в конец вы также можете убедиться, что java сама использует UTF-8. Использовать-Dfile.encoding=utf-8 в качестве параметра для JVM (может быть настроен в catalina.летучая мышь.)


добавить kosoant это, если вы используете Spring, а не пишете свой собственный фильтр сервлетов, вы можете использовать класс org.springframework.web.filter.CharacterEncodingFilter они предоставляют, настраивая его следующим образом в вашем интернете.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>

Это для греческого кодирования в таблицах 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

для меня и Ника, поэтому мы никогда не забываем об этом и больше не тратим время.....


хороший подробный ответ. просто хотел добавить еще одну вещь, которая определенно поможет другим увидеть кодировку UTF-8 на URL-адресах в действии .

выполните следующие действия, чтобы включить кодировку UTF-8 на URL-адресах в firefox.

  1. введите "about: config" в адресной строке.

  2. используйте тип ввода фильтра для поиска " сеть.стандартный URL-адрес.encode-query-utf8 " свойство.

  3. вышеуказанное свойство будет false по умолчанию, поверни это к истине.
  4. перезапустить браузер.

кодировка UTF-8 на URL-адресах работает по умолчанию в IE6/7 / 8 и chrome.


Я хочу также добавить из здесь эта часть решила мою проблему utf:

runtime.encoding=<encoding>

У меня аналогичная проблема, но в именах файлов файла я сжимаю с помощью Apache commons. Итак, я решил это с помощью следующей команды:

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

это работает очень хорошо для меня. Надеюсь, это поможет кому-нибудь;)


для моего случая отображения символа Юникода из пакетов сообщений мне не нужно применять раздел "кодировка страницы JSP" для отображения Юникода на моей странице jsp. Мне нужен раздел "CharsetFilter".


еще один момент, который не был упомянут, относится к Сервлетам Java, работающим с Ajax. У меня есть ситуации, когда веб-страница собирает текст utf-8 от пользователя, отправляющего это в файл JavaScript, который включает его в URI, отправленный сервлету. Сервлет запрашивает базу данных, фиксирует результат и возвращает его в виде XML в файл JavaScript, который форматирует его и вставляет отформатированный ответ в исходную веб-страницу.

в одном веб-приложении я следил за ранней книгой Ajax инструкции по завершению JavaScript при построении URI. В Примере в книге используется метод escape (), который я обнаружил (трудным путем), является неправильным. Для utf-8 необходимо использовать encodeURIComponent ().

в наши дни мало кто катает свой собственный Ajax, но я подумал, что могу добавить это.


о CharsetFilter упоминается в ответе @kosoant ....

есть в Filter в tomcat web.xml (расположенном в conf/web.xml). Фильтр называется setCharacterEncodingFilter и комментируется по умолчанию. Вы можете раскомментировать это ( пожалуйста, не забудьте раскомментировать его filter-mapping тоже )

также нет необходимости набор jsp-config в своем web.xml (у меня есть тест для Tomcat 7+ )


некоторое время вы можете решить проблему с помощью мастера администратора MySQL. В

запуск переменные > "дополнительно">

и установить Def. голец набор:кодировке utf8

возможно, эта конфигурация нуждается в перезапуске MySQL.


предыдущие ответы не работали с моей проблемой. Это было только в производстве, с tomcat и apache mod_proxy_ajp. Тело столба потеряло non ascii chars ? Проблема, наконец, была с JVM defaultCharset (US-ASCII в установке по умолчанию: Charset dfset = Charset.defaultCharset();) Итак, решение было запущено сервером tomcat с модификатором для запуска JVM с UTF-8 в качестве кодировки по умолчанию:

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

(добавьте эту строку в catalina.sh и перезапуск службы tomcat)

может быть, вы также необходимо изменить системную переменную linux (edit~/.и bashrc и ~/.профиль для постоянного изменения, см. https://perlgeek.de/en/article/set-up-a-clean-utf8-environment)

экспорт значение lc_all=язык.UTF-8
экспорт LANG=en_US.UTF-8

экспортировать язык=язык.UTF-8


в случае, если вы указали в пуле соединений (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");