Frage

Als ich noch PrimeFaces v2.2.1 verwendete, konnte ich Unicode-Eingaben wie Chinesisch mit einer PrimeFaces-Eingabekomponente wie z. B. eingeben <p:inputText> Und <p:editor>, und rufen Sie die Eingabe in gutem Zustand in der Managed-Bean-Methode ab.

Nachdem ich jedoch auf PrimeFaces v3.1.1 aktualisiert habe, werden alle diese Zeichen zu Mojibake oder Fragezeichen.Nur lateinische Eingaben sind in Ordnung, es sind die chinesischen, arabischen, hebräischen, kyrillischen usw. Zeichen, die fehlerhaft formatiert werden.

Wie wird das verursacht und wie kann ich es lösen?

War es hilfreich?

Lösung

Einführung

Normalerweise stellt JSF/Facelets die Zeichenkodierung des Anforderungsparameters bereits beim Erstellen/Wiederherstellen der Ansicht standardmäßig auf UTF-8 ein.Wenn jedoch ein Anforderungsparameter angefordert wird Vor Wenn die Ansicht erstellt/wiederhergestellt wurde, ist es zu spät, die richtige Zeichenkodierung festzulegen.Die Anfrageparameter werden nämlich nur einmal geparst.

PrimeFaces-Kodierung schlägt fehl

Dass es in PrimeFaces 3.x nach dem Upgrade von 2.x fehlschlug, liegt an der neuen isAjaxRequest() Überschreiben in PrimeFaces' PrimePartialViewContext welches einen Anfrageparameter prüft:

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

Standardmäßig ist die isAjaxRequest() (der von Mojarra/MyFaces, wie der obige PrimeFaces-Code von erhalten hat getWrapped()) prüft den Anforderungsheader wie folgt, was sich nicht auf die Kodierung der Anforderungsparameter auswirkt, da Anforderungsparameter nicht analysiert werden, wenn ein Anforderungsheader abgerufen wird:

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

Allerdings ist die isAjaxRequest() kann von jedem Phasen-Listener oder Systemereignis-Listener oder einer Anwendungsfabrik aufgerufen werden Vor Die Ansicht wurde erstellt/wiederhergestellt.Wenn Sie also PrimeFaces 3.x verwenden, werden die Anforderungsparameter analysiert Vor Die richtige Zeichenkodierung ist eingestellt und es wird daher die Standardkodierung des Servers verwendet, die normalerweise ISO-8859-1 ist.Das wird alles durcheinander bringen.

Lösungen

Es gibt mehrere Möglichkeiten, das Problem zu beheben:

  1. Benutze einen Servlet-Filter was setzt ServletRequest#setCharacterEncoding() mit UTF-8.Festlegen der Antwortkodierung durch ServletResponse#setCharacterEncoding() ist übrigens unnötig, da es von diesem Problem nicht betroffen ist.

    @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);
        }
    
        // ...
    }
    

    Das müssen Sie nur berücksichtigen HttpServletRequest#setCharacterEncoding() Legt nur die Kodierung für POST-Anfrageparameter fest, nicht für GET-Anfrageparameter.Für GET-Anforderungsparameter müssen Sie diese noch auf Serverebene konfigurieren.

    Wenn Sie zufällig die JSF-Dienstprogrammbibliothek verwenden OmniFaces, ein solcher Filter ist bereits im Lieferumfang enthalten, Die CharacterEncodingFilter.Installieren Sie es einfach wie unten beschrieben web.xml als erster Filtereintrag:

    <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. Konfigurieren Sie den Server neu, um UTF-8 anstelle von ISO-8859-1 als Standardkodierung zu verwenden.Im Fall von Glassfish wäre das eine Frage des Hinzufügens des folgenden Eintrags <glassfish-web-app> des /WEB-INF/glassfish-web.xml Datei:

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

    Tomcat unterstützt es nicht.Es hat das URIEncoding Attribut in <Context> Eintrag, dies gilt jedoch nur für GET-Anfragen, nicht für POST-Anfragen.


  3. Melden Sie es als Fehler an PrimeFaces.Ist da Wirklich Gibt es einen legitimen Grund, zu überprüfen, ob es sich bei der HTTP-Anforderung um eine Ajax-Anfrage handelt, indem ein Anforderungsparameter anstelle eines Anforderungsheaders überprüft wird, wie Sie es für Standard-JSF und beispielsweise jQuery tun würden?Die PrimeFaces' core.js JavaScript macht das.Es wäre besser, wenn es als Anforderungsheader festgelegt wäre XMLHttpRequest.


Lösungen, die NICHT funktionieren

Vielleicht stoßen Sie bei der Untersuchung dieses Problems irgendwo im Internet auf die unten aufgeführten „Lösungen“.Diese Lösungen werden in diesem speziellen Fall niemals funktionieren.Erklärung folgt.

  • XML-Prolog einstellen:

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

    Dies weist den XML-Parser lediglich an, UTF-8 zum Dekodieren der XML-Quelle zu verwenden, bevor er den XML-Baum darum herum erstellt.Der von Facelts tatsächlich verwendete XML-Parser ist SAX während JSF Bauzeit anzeigen.Dieser Teil hat überhaupt nichts mit der HTTP-Anfrage-/Antwortkodierung zu tun.

  • HTML-Meta-Tag festlegen:

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

    Das HTML-Meta-Tag wird ignoriert, wenn die Seite über HTTP über a bereitgestellt wird http(s):// URI.Es wird nur verwendet, wenn die Seite vom Client als HTML-Datei auf der lokalen Festplatte des Systems gespeichert und dann von einem erneut geöffnet wird file:// URI im Browser.

  • Festlegen des Attributs „Zeichensatz akzeptieren“ für HTML-Formulare:

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

    Moderne Browser ignorieren dies.Dies hat nur Auswirkungen im Browser Microsoft Internet Explorer.Selbst dann macht es es falsch.Benutzen Sie es niemals.Alle echten Webbrowser verwenden stattdessen das im angegebene Zeichensatzattribut Content-Type Header der Antwort.Sogar MSIE wird es richtig machen, solange Sie das nicht angeben accept-charset Attribut.

  • JVM-Argument festlegen:

    -Dfile.encoding=UTF-8
    

    Dies wird nur von der Oracle(!) JVM verwendet, um die Java-Quelldateien zu lesen und zu analysieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top