Résolution complète des problèmes d'encodage chinois dans les Servlets Java

Compréhension fondamentale de l'encodage des caractères

Lors du développement web avec des servlets Java, l'affichage incorrect des caractères chinois (appelé couramment "caractères fantaisie" ou "乱码") est un problème fréquent. Ce phénomène provient principalement d'une incohérence entre les schémas d'encodage utilisés lors de la transmission des données entre le navigateur et le serveur.

Notions de base à retenir :

  • Les systèmes d'exploitation chinois utilisent généralement GBK comme encodage par défaut (compatible avec GB2312).
  • Les points critiques d'encodage sont : la requête envoyée par le client, la réponse générée par le serveur, et l'interprétation par le navigateur.
  • En Java, on peut obtenir l'encodage par défaut via Charset.defaultCharset().
  • Les méthodes getOutputStream() et getWriter() de HttpServletResponse ne doivent pas être utilisées simultanément.
  • La méthode String.getBytes() utilise l'encodage par défaut sauf si spécifié (ex: getBytes("UTF-8")).

Mécanisme d'encodage/décodage

L'encodage consiste à convertir un texte en une séquence d'octets selon une table prédéfinie (UTF-8, GBK, etc.). Le décodage est l'opération inverse. Pour que les données soient correctement interprétées, le processus de décodage doit utiliser la même table que celui utilisé pour l'encodage.

Solutions aux erreurs d'encodage

Problèmes liés aux requêtes (Request)

Pour les requêtes GET

Les paramètres GET sont inclus dans l'URL. Les navigateurs modernes encodent souvent ces paramètres en UTF-8, mais le serveur Tomcat, s'il n'est pas configuré, les interprète en ISO-8859-1.

Solution 1 : Configuration côté serveur
Modifier le fichier server.xml de Tomcat pour imposer l'UTF-8 sur les URI :

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           URIEncoding="UTF-8"
           useBodyEncodingForURI="true" />

Cette configuration garantit que les paramètres URI sont correctement décodés en UTF-8.

Solution 2 : Recodage manuel
Si la configuration serveur n'est pas possible, corriger manuellement l'encodage dans le code :

String nom = request.getParameter("nom");
if (nom != null) {
    nom = new String(nom.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
}

Solution 3 : Encodage côté client
Utiliser URLEncoder pour préparer les données sensibles (comme les noms de fichiers) :

String cheminFichier = "/documents/简历.pdf";
String nomFichier = cheminFichier.substring(cheminFichier.lastIndexOf('/') + 1);
response.setHeader("Content-Disposition", 
    "attachment; filename*=UTF-8''" + URLEncoder.encode(nomFichier, "UTF-8"));

Pour les requêtes POST

Les données POST sont contenues dans le corps de la requête. Il suffit d'indiquer au serveur l'encodage attendu avant de lire les paramètres :

// À placer impérativement avant getParameter()
request.setCharacterEncoding("UTF-8");
String donnee = request.getParameter("champ");

Note : Cette méthode n'affecte que les données du corps (POST), pas les paramètres d'URL (GET).

Problèmes liés aux réponses (Response)

Le désordre d'affichage survient quand le navigateur interprète mal les données envoyées par le serveur.

Étape 1 : Indiquer le type MIME et l'encodage
Informer le navigateur du format et de l'encodage des données :

response.setContentType("text/html; charset=UTF-8");

Étape 2 : Gérer l'encodage selon le flux utilisé

  • Avec getWriter() (flux de caractères) : ``` response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("Bonjour, 世界 !");

  • Avec getOutputStream() (flux d'octets) : ``` response.setContentType("text/plain; charset=UTF-8"); OutputStream os = response.getOutputStream(); os.write("Message en chinois".getBytes(StandardCharsets.UTF_8)); os.flush();

    
    

Bonnes pratiques et astuces

  • Toujours définir contentType en début de traitement de réponse.
  • Utiliser StandardCharsets.UTF_8 plutôt que des chaînes littérales ("UTF-8") pour éviter les erreurs.
  • Valider que les pages HTML source utilisent également UTF-8 via la balise <meta charset="utf-8">.
  • Consulter l'encodage actuel avec response.getContentType().
  • Éviter d'utiliser print("<meta ...>") pour fixer l'encodage ; privilégier les en-têtes HTTP.

Étiquettes: Servlet Java encodage UTF-8 Charset

Publié le 25 août à 18h40