يصبح إدخال Unicode الذي تم استرداده عبر مكونات إدخال PrimeFaces تالفًا

StackOverflow https://stackoverflow.com//questions/9634230

سؤال

عندما كنت لا أزال أستخدم PrimeFaces v2.2.1، تمكنت من كتابة إدخال Unicode مثل اللغة الصينية باستخدام مكون إدخال PrimeFaces مثل <p:inputText> و <p:editor>, ، واسترجاع المدخلات في حالة جيدة في طريقة الفول المدارة.

ومع ذلك، بعد أن قمت بالترقية إلى PrimeFaces v3.1.1، أصبحت كل هذه الشخصيات Mojibake أو علامات استفهام.الإدخال اللاتيني فقط هو الذي يكون جيدًا، أما الأحرف الصينية والعربية والعبرية والسيريلية وما إلى ذلك فهي التي تصبح مشوهة.

كيف يحدث هذا وكيف يمكنني حلها؟

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

المحلول

مقدمة

عادةً، سيقوم JSF/Facelets بتعيين ترميز أحرف معلمة الطلب على UTF-8 افتراضيًا بالفعل عند إنشاء/استعادة العرض.ولكن إذا تم طلب أي معلمة طلب قبل تم إنشاء/استعادة العرض، ثم فات الأوان لتعيين ترميز الأحرف المناسب.سيتم تحليل معلمات الطلب مرة واحدة فقط.

فشل ترميز PrimeFaces

سبب الفشل في PrimeFaces 3.x بعد الترقية من 2.x هو الجديد isAjaxRequest() التجاوز في Primefaces' PrimePartialViewContext الذي يتحقق من معلمة الطلب:

@Override
public boolean isAjaxRequest() {
    return getWrapped().isAjaxRequest()
            || FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().containsKey("javax.faces.partial.ajax");
}

بشكل افتراضي، isAjaxRequest() (أحد Mojarra/MyFaces، كما حصل على رمز PrimeFaces أعلاه getWrapped()) يتحقق من رأس الطلب على النحو التالي والذي لا يؤثر على ترميز معلمة الطلب حيث لن يتم تحليل معلمات الطلب عند الحصول على رأس الطلب:

    if (ajaxRequest == null) {
        ajaxRequest = "partial/ajax".equals(ctx.
            getExternalContext().getRequestHeaderMap().get("Faces-Request"));
    }

ومع ذلك، isAjaxRequest() يمكن استدعاؤه بواسطة أي مستمع طور أو مستمع حدث نظام أو بعض مصانع التطبيقات قبل تم إنشاء/استعادة العرض.لذلك، عند استخدام PrimeFaces 3.x، سيتم تحليل معلمات الطلب قبل تم تعيين ترميز الأحرف المناسب ومن ثم استخدم الترميز الافتراضي للخادم والذي يكون عادةً ISO-8859-1.وهذا سوف يفسد كل شيء.

حلول

هناك عدة طرق لإصلاحها:

  1. إستخدم مرشح servlet الذي يحدد ServletRequest#setCharacterEncoding() مع UTF-8.ضبط ترميز الاستجابة بواسطة ServletResponse#setCharacterEncoding() بالمناسبة غير ضروري لأنه لن يتأثر بهذه المشكلة.

    @WebFilter("/*")
    public class CharacterEncodingFilter implements Filter {
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
            request.setCharacterEncoding("UTF-8");
            chain.doFilter(request, response);
        }
    
        // ...
    }
    

    ما عليك سوى أن تأخذ ذلك في الاعتبار HttpServletRequest#setCharacterEncoding() يقوم فقط بتعيين الترميز لمعلمات طلب POST، وليس لمعلمات طلب GET.بالنسبة لمعلمات طلب GET، ستظل بحاجة إلى تكوينها على مستوى الخادم.

    إذا كنت تستخدم مكتبة JSF المساعدة Omnifaces, ، تم توفير هذا الفلتر بالفعل خارج الصندوق، ال CharacterEncodingFilter.فقط قم بتثبيته على النحو التالي في web.xml كإدخال مرشح أول:

    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.omnifaces.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

  2. أعد تكوين الخادم لاستخدام UTF-8 بدلاً من ISO-8859-1 كالتشفير الافتراضي.في حالة Glassfish، سيكون ذلك بمثابة إضافة الإدخال التالي إلى <glassfish-web-app> التابع /WEB-INF/glassfish-web.xml ملف:

    <parameter-encoding default-charset="UTF-8" />
    

    Tomcat لا يدعمها.لديها URIEncoding السمة في <Context> الإدخال، ولكن هذا ينطبق على طلبات GET فقط، وليس على طلبات POST.


  3. قم بالإبلاغ عنه كخطأ إلى PrimeFaces.هل هناك حقًا هل هناك أي سبب مشروع للتحقق من أن طلب HTTP هو طلب ajax عن طريق التحقق من معلمة الطلب بدلاً من رأس الطلب كما تفعل مع JSF القياسي وعلى سبيل المثال jQuery؟الوجوه الأولية core.js جافا سكريبت تفعل ذلك.سيكون من الأفضل لو تم تعيينه كرأس طلب XMLHttpRequest.


الحلول التي لا تعمل

ربما ستعثر على "الحلول" أدناه في مكان ما على الإنترنت أثناء التحقيق في هذه المشكلة.لن تعمل هذه الحلول أبدًا في هذه الحالة المحددة.يتبع الشرح.

  • إعداد برولوج XML:

    <?xml version='1.0' encoding='UTF-8' ?>
    

    هذا يخبر محلل XML فقط باستخدام UTF-8 لفك تشفير مصدر XML قبل إنشاء شجرة XML حوله.محلل XML الذي يستخدمه Facelts فعليًا هو SAX أثناء JSF عرض وقت البناء.هذا الجزء ليس له أي علاقة على الإطلاق بترميز طلب/استجابة HTTP.

  • إعداد علامة تعريف HTML:

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    

    يتم تجاهل علامة تعريف HTML عندما يتم تقديم الصفحة عبر HTTP عبر ملف http(s):// URI.يتم استخدامه فقط عندما يتم حفظ الصفحة بواسطة العميل كملف HTML على نظام القرص المحلي ثم يتم إعادة فتحها بواسطة file:// URI في المتصفح.

  • إعداد نموذج HTML يقبل سمة مجموعة الأحرف:

    <h:form accept-charset="UTF-8">
    

    المتصفحات الحديثة تتجاهل هذا.وهذا له تأثير فقط في متصفح Microsoft Internet Explorer.وحتى ذلك الحين فإنه يفعل ذلك بشكل خاطئ.لا تستخدمه أبدًا.ستستخدم جميع متصفحات الويب الحقيقية بدلاً من ذلك سمة مجموعة الأحرف المحددة في ملف Content-Type رأس الرد.حتى MSIE ستفعل ذلك بالطريقة الصحيحة طالما أنك لم تحدد ملف accept-charset يصف.

  • إعداد وسيطة JVM:

    -Dfile.encoding=UTF-8
    

    يتم استخدام هذا فقط بواسطة Oracle(!) JVM لقراءة ملفات Java المصدرية وتحليلها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top