Вопрос

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

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

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

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

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

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

Это было полезно?

Решение

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

В основном символы äåö не являются проблемой, поскольку набор символов по умолчанию, используемый браузерами и 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-запрос это не влияет.

Фильтр символов

Затем пришло время заставить веб-приложение 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/что угодно.Альтернативой является установка кодировки ответа и т. д.в каждом контроллере приложения.

Этот фильтр необходимо добавить в веб.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>

Инструкцию по изготовлению этого фильтра можно найти на сайте кот вики (http://wiki.apache.org/tomcat/Tomcat/UTF-8)

Кодировка страницы JSP

В вашей веб.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-соединение

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

Ключевой частью является СИМВОЛ = utf8.

Конфигурация сервера MySQL

Серверы MySQL также должны быть настроены.Обычно это делается в Windows путем изменения мой.ini -file и в 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 ;

GET-запросы:латиница1 и 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, строка «Петтери» обрабатывается правильно.

Кириллический символ ж вообще не понимается в латинице1.Поскольку Tomcat поручено обрабатывать параметры запроса как UTF-8, он правильно кодирует этот символ как %D0%B6.

Если и когда браузерам будет дано указание читать страницы в кодировке UTF-8 (с заголовками запросов и мета-тегами html), по крайней мере, Firefox 2/3 и другие браузеры этого периода сами кодируют этот символ как %D0%B6.

Конечным результатом является то, что найдены все пользователи с именем «Петтери», а также все пользователи с именем «ж».

А как насчет Арт?

Спецификация 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/

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

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

Томкэт с Апачем

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

Другие советы

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

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

Чтобы добавить в ответ косоанта, если вы используете 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>

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

jdbc:mysql://192.168.10.123:3308/mydatabase?characterEncoding=greek

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

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

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

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

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

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

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

У меня аналогичная проблема, но имена файлов я сжимаю с помощью 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 в коте web.xml (находится в conf/web.xml).Фильтр носит название setCharacterEncodingFilter и комментируется по умолчанию.Вы можете раскомментировать это (пожалуйста, не забудьте раскомментировать это filter-mapping слишком )

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

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

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

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

Возможно, для этой конфигурации потребуется перезапустить MySQL.

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

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

экспортировать LANGUAGE=en_US.UTF-8

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

Если вы указали пул соединений (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");
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top