Question

Lorsque j'utilisais encore PrimeFaces v2.2.1, j'étais capable de saisir une entrée Unicode telle que le chinois avec un composant d'entrée PrimeFaces tel que <p:inputText> et <p:editor>, et récupérez l'entrée en bon état dans la méthode du bean géré.

Cependant, après la mise à niveau vers PrimeFaces v3.1.1, tous ces personnages deviennent des Mojibake ou des points d'interrogation.Seule la saisie latine fonctionne correctement, ce sont les caractères chinois, arabes, hébreux, cyrilliques, etc. qui deviennent mal formés.

Comment est-ce dû et comment puis-je le résoudre ?

Était-ce utile?

La solution

Introduction

Normalement, JSF/Facelets définira le codage des caractères du paramètre de demande sur UTF-8 par défaut dès la création/restauration de la vue.Mais si un paramètre de requête est demandé avant la vue a été créée/restaurée, il est alors trop tard pour définir le codage de caractères approprié.Les paramètres de la requête ne seront analysés qu'une seule fois.

Échec de l'encodage PrimeFaces

L'échec de PrimeFaces 3.x après la mise à niveau à partir de 2.x est dû au nouveau isAjaxRequest() remplacer dans PrimeFaces PrimePartialViewContext qui vérifie un paramètre de requête :

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

Par défaut, le isAjaxRequest() (celui de Mojarra/MyFaces, comme le code PrimeFaces ci-dessus a obtenu par getWrapped()) vérifie l'en-tête de la requête comme suit, ce qui n'affecte pas le codage des paramètres de la requête, car les paramètres de la requête ne seront pas analysés lorsqu'un en-tête de requête est obtenu :

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

Cependant, le isAjaxRequest() peut être appelé par n'importe quel écouteur de phase ou d'événement système ou une fabrique d'applications avant la vue a été créée/restaurée.Ainsi, lorsque vous utilisez PrimeFaces 3.x, les paramètres de la requête seront analysés avant le codage de caractères approprié a été défini et utilise donc le codage par défaut du serveur qui est généralement ISO-8859-1.Cela va tout gâcher.

Solutions

Il existe plusieurs façons de résoudre ce problème :

  1. Utiliser un filtre de servlets qui définit ServletRequest#setCharacterEncoding() avec UTF-8.Définition du codage de la réponse par ServletResponse#setCharacterEncoding() est d'ailleurs inutile car il ne sera pas affecté par ce problème.

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

    Il suffit de prendre en compte que HttpServletRequest#setCharacterEncoding() définit uniquement le codage des paramètres de requête POST, pas pour les paramètres de requête GET.Pour les paramètres de requête GET, vous devrez toujours le configurer au niveau du serveur.

    Si vous utilisez la bibliothèque d'utilitaires JSF OmniFaces, un tel filtre est déjà fourni, le CharacterEncodingFilter.Installez-le simplement comme ci-dessous dans web.xml comme première entrée de filtre :

    <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. Reconfigurez le serveur pour utiliser UTF-8 au lieu d'ISO-8859-1 comme codage par défaut.Dans le cas de Glassfish, il s'agirait d'ajouter l'entrée suivante à <glassfish-web-app> de la /WEB-INF/glassfish-web.xml déposer:

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

    Tomcat ne le prend pas en charge.Il a la URIEncoding attribut dans <Context> entrée, mais cela s'applique uniquement aux requêtes GET, pas aux requêtes POST.


  3. Signalez-le comme un bug à PrimeFaces.Y a-t-il vraiment une raison légitime de vérifier que la requête HTTP est une requête ajax en vérifiant un paramètre de requête au lieu d'un en-tête de requête comme vous le feriez pour le JSF standard et par exemple jQuery ?Les PrimeFaces core.js JavaScript fait cela.Ce serait mieux s'il le définissait comme en-tête de requête de XMLHttpRequest.


Des solutions qui ne fonctionnent PAS

Peut-être tomberez-vous sur les « solutions » ci-dessous quelque part sur Internet en enquêtant sur ce problème.Ces solutions ne fonctionneront jamais dans ce cas précis.L’explication suit.

  • Paramétrage du prologue XML :

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

    Cela indique uniquement à l'analyseur XML d'utiliser UTF-8 pour décoder la source XML avant de construire l'arborescence XML autour d'elle.L'analyseur XML actuellement utilisé par Facelts est SAX pendant JSF voir le temps de construction.Cette partie n'a absolument rien à voir avec l'encodage des requêtes/réponses HTTP.

  • Définition de la balise méta HTML :

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

    La balise méta HTML est ignorée lorsque la page est servie sur HTTP via un http(s):// URI.Il n'est utilisé que lorsque la page est enregistrée par le client sous forme de fichier HTML sur le système de disque local, puis rouverte par un file:// URI dans le navigateur.

  • Définition du formulaire HTML acceptant l'attribut charset :

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

    Les navigateurs modernes l'ignorent.Cela n'a d'effet que dans le navigateur Microsoft Internet Explorer.Même dans ce cas, il le fait mal.Ne l'utilisez jamais.Tous les vrais navigateurs Web utiliseront à la place l'attribut charset spécifié dans le Content-Type en-tête de la réponse.Même MSIE le fera correctement tant que vous ne spécifiez pas le accept-charset attribut.

  • Définition de l'argument JVM :

    -Dfile.encoding=UTF-8
    

    Ceci n'est utilisé que par la JVM Oracle (!) Pour lire et analyser les fichiers source Java.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top