Как заставить UTF-8 работать в веб-приложениях Java? - PullRequest
360 голосов
/ 26 сентября 2008

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

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

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

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

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

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

Ответы [ 14 ]

539 голосов
/ 26 сентября 2008

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

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

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

Настройка Tomcat's server.xml

Необходимо настроить, чтобы соединитель использовал 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 обрабатывать все запросы и ответы в кодировке 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-страница:

Это делается с помощью следующего в верхней части каждой страницы HTML, созданной веб-приложением:

   <?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&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 путем изменения файла my.ini и в Linux путем настройки файла my.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 ;

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

Если и в 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-символы кодируются одинаково как с помощью 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*

В латинице 1 символ ä кодируется как % E4 . Даже если страница / запрос / все определено для использования UTF-8 . Версия ä в кодировке UTF-8: % C3% A4

В результате этого веб-приложение не может корректно обрабатывать параметры запроса из запросов GET, поскольку некоторые символы кодируются в латинице 1, а другие - в UTF-8. Примечание: запросы POST работают, так как браузеры полностью кодируют все параметры запроса из форм в UTF-8, если страница определена как UTF-8

Материал для чтения

Большое спасибо авторам следующих статей за ответы на мою проблему:

Важное примечание

поддерживает Basic Multilingual Plane с использованием 3-байтовых символов UTF-8. Если вам нужно выйти за пределы этого (некоторые алфавиты требуют более 3 байтов UTF-8), то вам нужно либо использовать аромат типа столбца VARBINARY, либо использовать набор символов utf8mb4 (для этого требуется MySQL 5.5.3 или новее). Просто знайте, что использование набора символов utf8 в MySQL не будет работать 100% времени.

Tomcat с Apache

Еще одна вещь. Если вы используете коннектор Apache + Tomcat + mod_JK, вам также необходимо внести следующие изменения:

  1. Добавьте URIEncoding = "UTF-8" в файл tomcat server.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. Примечание: Сначала проверьте, существует он или нет. Если существует, вы можете обновить его с помощью этой строки. Вы также можете добавить эту строку внизу.
12 голосов
/ 28 сентября 2008

Думаю, вы достаточно хорошо подвели итог в своем ответе.

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

11 голосов
/ 28 января 2014

Чтобы добавить к ответу kooant , если вы используете 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>
2 голосов
/ 13 мая 2010

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

runtime.encoding=<encoding>
1 голос
/ 19 февраля 2010

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

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

  1. введите «about: config» в адресную строку.

  2. Используйте тип ввода фильтра для поиска свойства "network.standard-url.encode-query-utf8".

  3. указанное выше свойство будет иметь значение по умолчанию, установите для этого параметра значение ИСТИНА.
  4. перезагрузите браузер.

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

1 голос
/ 04 декабря 2009

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

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

0 голосов
/ 23 февраля 2019

Столкнулся с той же проблемой на Spring MVC 5 + Tomcat 9 + JSP.
После долгих исследований пришло элегантное решение ( нет нужны фильтры и нет нужны изменения на сервере Tomcat . xml (начиная с версии 8.0.0-RC3))

  1. В реализации WebMvcConfigurer задайте кодировку по умолчанию для messageSource (для чтения данных из исходных файлов сообщений в кодировке UTF-8.

    @Configuration
    @EnableWebMvc
    @ComponentScan("{package.with.components}")
    public class WebApplicationContextConfig implements WebMvcConfigurer {
    
        @Bean
        public MessageSource messageSource() {
            final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    
            messageSource.setBasenames("messages");
            messageSource.setDefaultEncoding("UTF-8");
    
            return messageSource;
        }
    
        /* other beans and methods */
    
    }
    
  2. В реализации DispatcherServletInitializer @Override метод onStartup и установка в нем кодировки символов запроса и ресурса.

    public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
        @Override
        public void onStartup(final ServletContext servletContext) throws ServletException {
    
            // https://wiki.apache.org/tomcat/FAQ/CharacterEncoding
            servletContext.setRequestCharacterEncoding("UTF-8");
            servletContext.setResponseCharacterEncoding("UTF-8");
    
            super.onStartup(servletContext);
        }
    
        /* servlet mappings, root and web application configs, other methods */
    
    }
    
  3. Сохранение всех источников сообщений и просмотр файлов в кодировке UTF-8.

  4. Добавьте <% @ page contentType = "text / html; charset = UTF-8"%> или <% @ page pageEncoding = "UTF-8"%> в каждом *. jsp файл или добавить дескриптор jsp-config в web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
     id="WebApp_ID" version="3.0">
        <display-name>AppName</display-name>
    
        <jsp-config>
            <jsp-property-group>
                <url-pattern>*.jsp</url-pattern>
                <page-encoding>UTF-8</page-encoding>
            </jsp-property-group>
        </jsp-config>
    </web-app>
    
0 голосов
/ 16 апреля 2018

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

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

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

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

export LC_ALL = en_US.UTF-8
экспорт LANG = en_US.UTF-8

export LANGUAGE = en_US.UTF-8

0 голосов
/ 13 июля 2017

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

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

и установите Def. Набор символов: utf8

Может быть, этот конфиг нужно перезапустить MySQL.

0 голосов
/ 09 января 2017

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...