Codage et décodage
Grâce à la figure suivante, nous pouvons comprendre où il y a un transcodage dans Javaweb:
L'utilisateur souhaite que le serveur envoie une demande HTTP. Les endroits où l'encodage sont une URL, des cookies et des paramètres sont nécessaires. Après encodage, le serveur accepte la demande HTTP, analyse la demande HTTP, puis décode l'URL, les cookies et le paramètre. Pendant le traitement de la logique métier du serveur, il peut être nécessaire de lire des bases de données, des fichiers locaux ou d'autres fichiers du réseau, etc., et ces processus nécessitent un codage et un décodage. Une fois le traitement terminé, le serveur code les données et l'envoie au client, et le navigateur l'affiche à l'utilisateur après le décodage. Il existe de nombreux codages et décodages impliqués dans tout ce processus, et l'endroit le plus probable pour apparaître brouillé est le processus d'interaction avec le serveur et le client.
L'ensemble du processus ci-dessus peut être résumé comme suit: les données codées par page sont transmises au serveur, et le serveur décode les données obtenues, et après un traitement de la logique métier, le résultat final est codé et traité, et le client décode et l'affiche à l'utilisateur. Ci-dessous, je demanderai une explication de l'encodage et du décodage de Javaweb.
Si le client souhaite que le serveur envoie une demande, il passera quatre situations:
1. Accès direct par URL.
2. Lien de page.
3. Formulaire obtenez la soumission
4. Soumission de poste de formulaire
Méthode d'URL: Pour les URL, si toutes les URL sont en anglais, il n'y a pas de problème. S'il y a du chinois, l'encodage sera impliqué. Comment coder? Quelles règles souhaitez-vous encoder? Alors, comment le décoder? Les réponses seront répondues un par un ci-dessous! Regardez d'abord les composants de l'URL:
Dans cette URL, le navigateur codera le chemin et le paramètre. Pour mieux expliquer le processus de codage, utilisez l'URL suivante
http://127.0.0.1:8080/perbank/i am cm? name = je suis cm
Entrez l'adresse ci-dessus dans la zone d'entrée de l'URL du navigateur. En visualisant les informations d'en-tête de message HTTP, nous pouvons voir comment le navigateur le code. Voici les conditions de codage de trois navigateurs:
Vous pouvez voir que le codage de "Je suis" par les principaux navigateurs est le suivant:
partie du chemin | Chaîne de requête | |
Incendier | E6 88 91 E6 98 AF | E6 88 91 E6 98 AF |
Chrome | E6 88 91 E6 98 AF | E6 88 91 E6 98 AF |
C'est-à-dire | E6 88 91 E6 98 AF | CE D2 CA C7 |
Protected void converturi (messageBytes uri, demande de demande) lève l'exception {bytechunk bc = uri.getByTechunk (); int length = bc.GetLength (); Charchunk cc = uri.getCharchunk (); CC.ALLOCY (longueur, -1); String ENC = Connector.GettuRICOding (); // Obtenez l'ensemble de décodage URI if (enc! = Null) {b2cConverter conv = request.getUrIConverter (); try {if (conv == null) {conv = new B2cConverter (Enc); request.seturiConverter (conv); }} catch (ioException e) {...} if (conv! = null) {try {conv.Convert (bc, cc, cc.getBuffer (). length - cc.gettend ()); URI.Setchars (cc.GetBuffer (), cc.GetStart (), cc.GetLength ()); retour; } catch (ioException e) {...}}} // Encodage par défaut: byte de conversion rapide [] bbuf = bc.GetBuffer (); char [] cbuf = cc.getBuffer (); int start = bc.GetStart (); for (int i = 0; i <length; i ++) {cbuf [i] = (char) (bbuf [i + start] & 0xff); } uri.sechars (cbuf, 0, longueur); } À partir du code ci-dessus, nous pouvons voir que le fonctionnement de décodage de l'URI consiste d'abord à obtenir l'ensemble de décodage du connecteur, qui est configuré dans server.xml
<Connecteur uriencoding = "utf-8" />
S'il n'est pas défini, le codage par défaut ISO-8859-1 sera utilisé pour l'analyse.
Pour la partie de la chaîne de requête, nous savons que si nous le soumettons via GET ou POST, tous les paramètres sont enregistrés dans les paramètres, puis nous utilisons la demande. À l'intérieur de la méthode GetParameter, il appelle la méthode des parseparameters d'org.apache.catalina.connector.request, qui décodera les paramètres passés. Le code suivant n'est qu'une partie de la méthode des parseparamètres:
// Obtenez la chaîne de codage enc = getCacteRencoding (); // Obtenez le Charset Boolean défini dans ContentType useBodyEncodingForUri = connector.getUseBodyEncodingForUri (); if (enc! = null) {// Si le codage n'est pas vide, définissez le codage sur paramètres ENC.SetEncoding (ENC); if (useBodyEncodingForUri) {// Si ChartSet est défini, définissez le décodage de QueryString sur ChartSet Paramètres.SetQueryStRingEncoding (ENC); }} else {// Définissez la méthode de décodage par défaut Paramètres.SetEncoding (org.apache.coyote.constants.default_character_encoding); if (useBodyEncodingForUri) {paramètres.setQuerystRingEncoding (org.apache.coyote.constants.default_character_encoding); }} À partir du code ci-dessus, nous pouvons voir que le format de décodage de la chaîne de requête utilise le jeu de cartes de set ou utilise le format de décodage par défaut ISO-8859-1. Notez que le graphique dans ce paramètre est le contenu de contenu défini dans l'en-tête HTTP. Dans le même temps, si nous devons modifier l'attribut spécifié pour prendre effet, nous devons configurer ce qui suit:
<Connecteur uriencoding = "utf-8" useBodyEncodingForUri = "true" />
La partie ci-dessus introduit en détail le processus de codage et de décodage des demandes d'URL. En fait, pour nous, nos autres façons sont de se soumettre sous la forme.
Former
Nous savons que la soumission des données via des URL est facile à causer des problèmes de code brouillé, nous avons donc tendance à utiliser des formulaires de formulaire. Lorsque l'utilisateur clique sur Soumettre le formulaire, le navigateur définira plus de codes pour transmettre les données au serveur. Les données soumises via GET sont épissées après l'URL (peut-elle être considérée comme une chaîne de requête ??), donc uriencoding joue un rôle dans le processus de décodage du serveur Tomcat. Le serveur Tomcat décodera en fonction de l'URIENCODING SET, et s'il n'est pas défini, il utilisera l'ISO-8859-1 par défaut pour décoder. Si nous définissons l'encodage sur UTF-8 sur la page et que l'urieencodage n'est pas ou n'est pas défini, le code brouillé se produira lorsque le serveur décode. À l'heure actuelle, nous pouvons généralement obtenir les données correctes via la forme de nouvelle chaîne (request.getParameter ("Name"). GetBytes ("ISO-8859-1"), "UTF-8").
Post de formulaire
Pour la méthode post, le codage qu'il utilise est également déterminé par la page, c'est-à-dire contenu. Lorsque je soumets un formulaire en cliquant sur le bouton Soumettre sur la page, le navigateur encodera d'abord les paramètres du formulaire de poste en fonction du format de codage de charse du TentType et de le soumettre au serveur. Du côté du serveur, il utilise également le jeu de caractères dans le contenuType pour décoder (il est différent de la méthode GET ici). Cela signifie que les paramètres soumis par le formulaire de poste n'ont généralement pas de problèmes brouillés. Bien sûr, nous pouvons définir le jeu de caractères en codant nous-mêmes: request.secharacterencoding (charset).
Résoudre le problème des URL brouillées en chinois
Nous envoyons principalement des demandes au serveur via deux formes de soumission: URL et formulaire. La forme de forme n'a généralement pas de problèmes brouillés, et les problèmes brouillés sont principalement sur l'URL. Grâce à l'introduction des blogs précédents, nous savons que le processus d'envoi de demande d'encodage au serveur par URL est vraiment trop déroutant. Différents systèmes d'exploitation, différents navigateurs et différents jeux de caractères Web conduiront à des résultats d'encodage complètement différents. N'est-ce pas trop effrayant si les programmeurs veulent prendre en compte chaque résultat? Existe-t-il un moyen de s'assurer que le client n'utilise qu'une seule méthode d'encodage pour émettre une demande au serveur?
avoir! Ici, je fournis principalement les méthodes suivantes
javascrip
L'utilisation de codage JavaScript ne donne pas au navigateur la possibilité d'intervenir. Après encodage, envoyez une demande au serveur, puis décodez-la dans le serveur. Lors de la maîtrise de cette méthode, nous avons besoin de trois méthodes de codage JavaScript: Escape (), Encodeuri () et EncodeuRIComponent ().
s'échapper
La chaîne spécifiée est codée à l'aide du jeu de caractères SIO Latin. Tous les caractères non ASCII sont codés sous forme de chaînes au format% xx, où xx représente le nombre hexadécimal correspondant au caractère du jeu de caractères. Par exemple, le codage correspondant au format est% 20. Sa méthode de décodage correspondante est un Escape ().
En fait, Escape () ne peut pas être utilisé directement pour le codage de l'URL, sa fonction réelle est de renvoyer la valeur codée par un personnage. Par exemple, le résultat de "Je suis CM" ci-dessus est% U6211% U662FCM, où le codage correspondant de "I" est 6211, le codage de "oui" est 662f, et le codage de "CM" est CM.
Notez que Escape () n'est pas codé par "+". Mais nous savons que lorsqu'une page Web soumet un formulaire, s'il y a des espaces, il sera converti en caractères +. Lorsque le serveur traite les données, le signe + sera transformé en espaces. Par conséquent, soyez prudent lorsque vous l'utilisez.
encodéuri
Encodant l'URL entière, il utilise le format UTF-8 pour sortir la chaîne codée. Cependant, Encodeuri n'encodera pas certains caractères spéciaux, sauf le codage ASCII, tel que :! @ # $ & * () =: /; ? + '.
encopiecto-composant
Convertissez les chaînes URI en chaînes de format d'échappement au format de codage UTF-8. Par rapport à Encodeuri, EncodeuriComponent sera plus puissant, et il sera codé pour les symboles (; / ?: @ & = + $, #) qui ne sont pas codés dans Encodeuri (). Cependant, EncodeuriComponent ne codera que les composants de l'URL individuellement et ne sera pas utilisé pour coder l'URL entière. La méthode de décodage de décodage correspondante.
Bien sûr, nous utilisons généralement la partie encodéuri pour effectuer des opérations d'encodage. Le soi-disant codage JavaScript et le décodage deux fois en arrière-plan consiste à utiliser cette méthode. Il existe deux solutions pour résoudre ce problème dans JavaScript: une méthodes de transcodage et deux transcoding.
Transcoding une fois
Transcodage javascript:
var url = '<s: propriété value = "webpath" />/showmoblieqrcode.servlet?name=i am cm'; window.location.href = encodeuri (URL);
URL transcodée: http://127.0.0.1:8080/perbank/showmoblieqrcode.servlet?name=%E6%88%91%E6%98%AFCM
Traitement du backend:
String name = request.getParameter ("name"); System.out.println ("Paramètres entrants de premier plan:" + nom); name = new String (name.getBytes ("iso-8859-1"), "utf-8"); System.out.println ("Paramètres décodés:" + nom); Résultat de sortie:
Paramètres entrants dans la réception: ?????? CM
Après les paramètres de décodage: je suis CM
Transcoding secondaire
javascrip
var url = '<s: propriété value = "webpath" />/showmoblieqrcode.servlet?name=i am cm'; window.location.href = encodeuri (encodeuri (URL));
URL transcodée: http://127.0.0.1:8080/perbank/showmoblieqrcode.servlet?name=%25E6%2588%2591%25E6%2598%25AFCM
Traitement du backend:
String name = request.getParameter ("name"); System.out.println ("Paramètres entrants de premier plan:" + nom); name = urldecoder.decode (name, "utf-8"); System.out.println ("Paramètres décodés:" + nom); Résultat de sortie:
Paramètres entrants frontaux: E68891E698AFCM
Après les paramètres de décodage: je suis CM
filtre
À l'aide de filtres, les filtres fournissent deux types, le premier consiste à définir l'encodage et le second consiste à effectuer des opérations de décodage directement dans le filtre.
Filtre 1
Ce filtre définit directement le format d'encodage de la demande.
Classe publique LeCatorCcoding implémente Filter {private filterConfig config; String Encoding = null; public void destre () {config = null; } public void dofilter (ServLetRequest Request, ServletResponse Response, FilterChain Chain) lève IOException, ServletException {request.SetcharAtterencoding (Encoding); chain.dofilter (demande, réponse); } public void init (filterConfig config) lève Servlexception {this.config = config; // Obtenir les paramètres de configuration String str = config.getInitParameter ("Encoding"); if (str! = null) {coding = str; }}} Configuration:
<! - Configuration du filtre chinois -> <filter> <filter-name> chinoisencoding </filter-name> <filter-class> com.test.filter.characterencoding </filter-class> <Init-Param> <param-name> codage </ param-name> <param-valeur> utf-8 </onsam-value> <Filter-Name> Chineseencoding </filter-name> <URL-Pattern> / * </ url-sattern> </filter-mapping>
Filtre 2
Dans la méthode de traitement, le filtre décode directement les paramètres, puis réinitialise les paramètres décodés à l'attribut de demande.
La classe publique est de carter encoding implémente filter {protégée filterConfig filterConfig; String Encoding = null; public void destre () {this.filterConfig = null; } / ** * Initialize * / public void init (filterConfig filterConfig) {this.filterConfig = filterConfig; } / ** * Convertiss Instr dans le formulaire d'encodage d'UTF-8 * * @param instant entrez la chaîne * @return utf - 8's Encoding Form String * @Throws UnsupporTeDenCcodingException * / private String toutf (String instr) lance unpportedEncodingException {String outstr = ""; if (instr! = null) {outstr = new String (instr.getBytes ("iso-8859-1"), "utf-8"); } return outstr; } / ** * Traitement de filtrage brouillé chinois * / public void dofilter (servletequest servletequest, servletResponse servletResponse, filterchain chaîne) lance ioException, servlexception {httpservletRequest request = (httpservletRequest) ServLetRequest; HttpServletResponse Response = (httpServletResponse) servletResponse; // la méthode pour obtenir la demande (1.post ou 2.get), et un traitement différent est effectué en fonction de différentes méthodes de demande méthode de chaîne = request.getMethod (); // 1. Pour les demandes soumises dans le post, définissez directement l'encodage sur UTF-8 if (method.equalsignorecase ("post")) {try {request.SetcharAtterencoding ("utf-8"); } catch (UnportEnCcodingException e) {e.printStackTrace (); }} // 2. Demande soumise dans Get Else {// Sortez le jeu de paramètres soumis par le client énumération <string> paramNames = request.getParameterNames (); // Traversé le paramètre défini pour sortir le nom et la valeur de chaque paramètre while (paramNames.hasmoreElements ()) {String name = paramNames.Nexttelement (); // Sortez les valeurs de chaîne de nom de paramètre [] = request.getParameTervalues (name); // supprime sa valeur en fonction du nom du paramètre // Si le jeu de valeurs de paramètre n'est pas vide if (valeurs! = Null) {// Travel la valeur du paramètre défini pour (int i = 0; i <valeurs.length; i ++) {try {// cercle Back et appelez chaque valeur toutf (valeurs [i]) Méthode pour convertir l'encodage des caractères de la valeur paramètre de la chaîne vlustr = toutf (valeurs [i]); valeurs [i] = vlustr; } catch (UnportEnCcodingException e) {e.printStackTrace (); }} // Masquer la valeur sous le formulaire d'un attribut dans la demande de demande.setAttribute (nom, valeurs); }}} // Définissez la méthode de réponse et supportez le jeu de caractères chinois Response.SetContentType ("text / html; charset = utf-8"); // Continuez à exécuter le filtre suivant. S'il n'y a pas de filtre, la demande sera Chain.Dofilter (demande, réponse); }} Configuration:
<! - Configuration du filtre chinois -> <filter> <filter-name> chinoisencoding </filter-name> <filter-class> com.test.filter.characterencoding </filter-class> </ filter> <filter-mapping> <filter-name> chinoisencoding </filter-name> <Url-Pattern> / * </url-Pattern>-Pattern>
autre
1. Définir Pageencoding et ContentType
<% @ Page Language = "Java" ContentType = "Text / Html; charSet = UTF-8" Pageencoding = "UTF-8"%>
2. Configurez l'urien de Tomcat
Par défaut, le serveur Tomcat utilise le format de codage ISO-8859-1 pour coder l'URL demandée par le paramètre URIENCODING, nous n'avons donc qu'à ajouter uriencoding = "utf-8" à la balise <Connector> du fichier server.xml de Tomcat.