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


367

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

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

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

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

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

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


Ответы:


552

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

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

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

Конфигурирование сервера Tomcat server.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=*ж*

символ is обрабатывается как 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 ( 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-соединение

При использовании БД необходимо определить, что соединение использует кодировку 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 -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

Если и когда в 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.

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

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

  • 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/

Важная заметка

поддерживает базовую многоязычную плоскость, используя 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. Гото ваш апач папку т.е. /etc/httpd/confи добавить AddDefaultCharset utf-8в httpd.conf file. Примечание. Сначала проверьте, существует он или нет. Если существует, вы можете обновить его с помощью этой строки. Вы также можете добавить эту строку внизу.

Эти шаги также работают со Struts / tile и базой данных postgres.
Косоант

17
Два комментария: 1) в теги HMTL-meta вы включили декларацию xml. Удалите его, он будет запускать браузеры только в режиме причуд, вы не хотите иметь это. Кроме того, метатеги HTML на самом деле уже неявно выполняются JSP pageEncoding, так что вы даже можете оставить их в стороне. 2) в базе данных и таблицах MySQL вы использовали utf8_swedish_si, это должно было быть utf8_unicode_ci. Вы можете даже оставить сопоставление, CHARACTER SET utf8достаточно.
BalusC

Ни один из документов, к которым я обращался в отношении метатегов HTML и режима причуд (например, ericmeyeroncss.com/bonus/render-mode.html , en.wikipedia.org/wiki/Quirks_mode ), не указывает на то, что наличие <meta http-эквивалента = 'Content -Type 'оказывает влияние на режим рендеринга.
Марсель Стёр

В качестве интересного примечания вы также можете знать, что если у вас есть прослушиватель, который обращается к параметру запроса, вам нужно будет добавить прослушиватель, который устанавливает кодировку вместо фильтра, потому что слушатели выполняются перед фильтрами. Я следовал за всеми шагами, и это все еще не работало из-за этого. Просто подумал, что передам эту информацию, на случай, если у кого-то еще возникнет подобная проблема.
testing123

3
## 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. Примечание: сначала проверьте, существует он или нет. Если существует, вы можете обновить его с помощью этой строки. Вы также можете добавить эту строку внизу.
Виджай Шегокар

14

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

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


Это помогло мне, я сделал все упомянутое, но кодировка JVM была windows-1250, как только я перешел на UTF-8, он работал безупречно.
coding_idiot

2
Где вы добавите это в файл Catalina.bat, пожалуйста?
Ноя

11

Чтобы добавить к ответу 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>

1
Этот фильтр должен быть первым фильтром в web.xml
olyanren


1

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

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


5
Я все еще предпочел бы UTF-8 выше греческого (и преобразовать ваши текущие греческие данные в UTF-8), чтобы ваше приложение было готово к мировому господству.
BalusC

1

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

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

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

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

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

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


1

Предыдущие ответы не работали с моей проблемой. Это было только в производстве, с 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 )

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

export LANGUAGE = en_US.UTF-8


0

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

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

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


0

В моем случае отображения символа Unicode из пакетов сообщений мне не нужно применять раздел «Кодировка страницы JSP» для отображения Unicode на моей странице jsp. Все, что мне нужно, это раздел "CharsetFilter".


0

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

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

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


0

Около CharsetFilter упомянутом в @kosoant ответе ....

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

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


0

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

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

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

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


0

Столкнулся с такой же проблемой на Spring MVC 5 + Tomcat 9 + JSP.
После долгих исследований пришло элегантное решение ( нет необходимости в фильтрах и нет необходимости вносить изменения в Tomcat server.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>

-1

Если вы указали в пуле соединений (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");
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.