سؤال

أحتاج إلى تشغيل UTF-8 في تطبيق الويب Java الخاص بي (servlets + JSP، لا يوجد إطار عمل مستخدم) لدعمه äöå إلخ.للنص الفنلندي العادي والأبجدية السيريلية مثل ЦжФ لحالات خاصة.

الإعداد الخاص بي هو ما يلي:

  • بيئة التطوير:ويندوز إكس بي
  • بيئة الإنتاج:ديبيان

قاعدة البيانات المستخدمة:ماي إس كيو إل 5.x

يستخدم المستخدمون بشكل أساسي Firefox2 ولكن يتم أيضًا استخدام Opera 9.x وFF3 وIE7 وGoogle Chrome للوصول إلى الموقع.

كيفية تحقيق ذلك؟

هل كانت مفيدة؟

المحلول

الإجابة على نفسي لأن الأسئلة الشائعة لهذا الموقع تشجع ذلك.هذا يعمل بالنسبة لي:

في الغالب لا تمثل الأحرف äåö مشكلة لأن مجموعة الأحرف الافتراضية التي تستخدمها المتصفحات و Tomcat/Java لتطبيقات الويب هي latin1 أي.ISO-8859-1 الذي "يفهم" تلك الأحرف.

لكي يعمل UTF-8 ضمن Java+Tomcat+Linux/Windows+Mysql، يتطلب ما يلي:

تكوين خادم Tomcat.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>

تم العثور على تعليمات صنع هذا الفلتر في القط ويكي (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:

يتم ذلك من خلال ما يلي أعلى كل صفحة 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 عن طريق التعديل 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 ;

الحصول على الطلبات:latin1 وUTF-8

إذا تم تعريف معلمات طلب GET في ملف Tomcat server.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" بشكل صحيح.

الحرف السيريلي ž غير مفهوم على الإطلاق باللغة اللاتينية 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/

ملاحظة مهمة

يدعم الطائرة الأساسية متعددة اللغات باستخدام أحرف UTF-8 ذات 3 بايت.إذا كنت بحاجة إلى تجاوز ذلك (تتطلب بعض الحروف الهجائية أكثر من 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-ing(?) من النهاية إلى النهاية، قد ترغب أيضًا في التأكد من أن Java نفسها تستخدم UTF-8.استخدم -Dfile.encoding=utf-8 كمعلمة لـ JVM (يمكن تهيئتها في catalina.bat).

إضافة إلى إجابة كوسوان, ، إذا كنت تستخدم Spring، فبدلاً من كتابة مرشح Servlet الخاص بك، يمكنك استخدام الفصل الدراسي 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 في فايرفوكس.

  1. اكتب "حول: التكوين" في شريط العناوين.

  2. استخدم نوع إدخال المرشح للبحث عن خاصية "network.standard-url.encode-query-utf8".

  3. الخاصية المذكورة أعلاه ستكون خاطئة بشكل افتراضي، قم بتحويلها إلى TRUE.
  4. أعد تشغيل المتصفح.

يعمل ترميز UTF-8 على عناوين URL بشكل افتراضي في IE6/7/8 وchrome.

أواجه مشكلة مماثلة، ولكن في أسماء الملفات، أقوم بضغطها باستخدام مشاعات Apache.لذلك قمت بحل المشكلة باستخدام هذا الأمر:

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

تعمل جيدا بالنسبة إلي.نأمل أن يساعد أي شخص ؛)

بالنسبة لحالتي التي أعرض فيها أحرف Unicode من حزم الرسائل، لا أحتاج إلى تطبيق قسم "ترميز صفحة JSP" لعرض Unicode على صفحة jsp الخاصة بي.كل ما أحتاجه هو قسم "CharsetFilter".

هناك نقطة أخرى لم يتم ذكرها تتعلق بعمل Java Servlets مع Ajax.لدي مواقف تلتقط فيها صفحة الويب نص UTF-8 من المستخدم الذي يرسل هذا إلى ملف JavaScript والذي يتضمنه في URI مرسل إلى Servlet.يستعلم Servlet عن قاعدة بيانات، ويلتقط النتيجة ويعيدها بتنسيق XML إلى ملف JavaScript الذي يقوم بتنسيقها وإدراج الاستجابة المنسقة في صفحة الويب الأصلية.

في أحد تطبيقات الويب، كنت أتبع تعليمات أحد كتب Ajax المبكرة لتغليف JavaScript في إنشاء URI.استخدم المثال الموجود في الكتاب طريقة escape()، والتي اكتشفت (بالطريقة الصعبة) أنها خاطئة.بالنسبة إلى utf-8، يجب عليك استخدام encodeURIComponent().

يبدو أن القليل من الناس يقومون بتدوير أياكس خاصتهم هذه الأيام، لكنني اعتقدت أنني قد أضيف هذا أيضًا.

عن CharsetFilter المذكورة في @ kosoant الإجابة ....

هناك بناء في Filter في القط web.xml (تقع في conf/web.xml).تم تسمية المرشح setCharacterEncodingFilter ويتم التعليق عليه بشكل افتراضي.يمكنك إلغاء التعليق على هذا (يرجى تذكر إلغاء التعليق عليه filter-mapping أيضاً )

ليست هناك حاجة أيضا لتعيين jsp-config في الخاص بك web.xml (لقد قمت باختباره لـ Tomcat 7+)

في بعض الأحيان يمكنك حل المشكلة من خلال معالج MySQL Administrator.في

متغيرات بدء التشغيل > خيارات متقدمة >

وتعيين ديف.مجموعة الأحرف:utf8

ربما يحتاج هذا التكوين إلى إعادة تشغيل MySQL.

الردود السابقة لم تنجح مع مشكلتي.لقد كان قيد الإنتاج فقط، مع Tomcat وApache mod_proxy_ajp.فقد جسم المشاركة أحرف غير ascii بواسطة ؟كانت المشكلة أخيرًا مع JVM defaultCharset (US-ASCII في التثبيت الافتراضي:charset dfset = charset.defaultcharset () ؛) لذلك ، تم تشغيل الحل خادم tomcat مع معدّل لتشغيل 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

تصدير اللغة=en_US.UTF-8

واجهت نفس المشكلة في Spring MVC 5 + Tomcat 9 + JSP.
وبعد بحث طويل توصلت إلى حل أنيق (لا يحتاج المرشحات و لا يحتاج التغييرات في تومكات 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>
    

في حالة تحديدك في تجمع الاتصال (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