Codificación y decodificación
A través de la siguiente figura, podemos entender dónde hay transcodificación en Javaweb:
El usuario desea que el servidor envíe una solicitud HTTP. Se requieren los lugares donde la codificación son URL, galletas y parámetros. Después de codificar, el servidor acepta la solicitud HTTP, analiza la solicitud HTTP y luego decodifica la URL, las cookies y el parámetro. Durante el procesamiento lógico comercial del servidor, puede ser necesario leer bases de datos, archivos locales u otros archivos en la red, etc., y estos procesos requieren codificación y decodificación. Una vez completado el procesamiento, el servidor codifica los datos y los envía al cliente, y el navegador lo muestra al usuario después de decodificar. Hay muchas codificaciones y decodificaciones involucradas en todo este proceso, y el lugar más probable para aparecer confuso es el proceso de interactuar con el servidor y el cliente.
Todo el proceso anterior se puede resumir de la siguiente manera: los datos codificados por la página se pasan al servidor, y el servidor decodifica los datos obtenidos, y después de algún procesamiento de lógica comercial, el resultado final se codifica y procesa, y el cliente decodifica y lo muestra al usuario. A continuación, solicitaré una explicación de la codificación y decodificación de Javaweb.
Si el cliente desea que el servidor envíe una solicitud, pasará cuatro situaciones:
1. Acceso directo por URL.
2. Enlace de página.
3. Formulario Obtener envío
4. Formulario posterior a la presentación
Método de URL: para URL, si todas las URL están en inglés, no hay problema. Si hay chino, la codificación estará involucrada. ¿Cómo codificar? ¿Qué reglas quieres codificar? Entonces, ¿cómo decodificarlo? ¡Las respuestas serán respondidas una por una a continuación! Primero mire los componentes de la URL:
En esta URL, el navegador codificará la ruta y el parámetro. Para explicar mejor el proceso de codificación, use la siguiente URL
http://127.0.0.1:8080/perbank/i am cm? name = I am cm
Ingrese la dirección anterior en el cuadro de entrada URL del navegador. Al ver la información del encabezado del mensaje HTTP, podemos ver cómo la codifica el navegador. Aquí están las condiciones de codificación de tres navegadores:
Puedes ver que la codificación de "I Am" por los principales navegadores es el siguiente:
parte del camino | Cadena de consulta | |
Firefox | E6 88 91 E6 98 AF | E6 88 91 E6 98 AF |
Cromo | E6 88 91 E6 98 AF | E6 88 91 E6 98 AF |
ES DECIR | E6 88 91 E6 98 AF | CE D2 CA C7 |
Converturi void protegido (MessageBytes uri, solicitud de solicitud) lanza la excepción {bytechunk bc = uri.getByTechunk (); int longitud = bc.getLength (); Charchunk cc = uri.getcharchunk (); cc.allocate (longitud, -1); Cadena enc = conector.geturiencoding (); // Obtenga el conjunto de decodificación de URI if (Enc! = NULL) {B2CConverter Conv = request.geturiconverter (); intente {if (conv == null) {conv = new B2CConverter (ENC); request.seturiconverter (conv); }} catch (ioException e) {...} if (conv! = null) {try {conv.convert (bc, cc, cc.getBuffer (). longitud - cc.getend ()); uri.setchars (cc.getBuffer (), cc.getStart (), cc.getLength ()); devolver; } catch (ioException e) {...}}} // codificación predeterminada: byte de conversión rápida [] bbuf = bc.getBuffer (); char [] cbuf = cc.getBuffer (); int inicio = bc.getStart (); for (int i = 0; i <longitud; i ++) {cbuf [i] = (char) (bbuf [i+start] & 0xff); } uri.setchars (cbuf, 0, longitud); } En el código anterior, podemos ver que la operación de decodificación del URI primero es obtener el conjunto de decodificación del conector, que está configurado en server.xml
<Conector uriEncoding = "utf-8" />
Si no se define, la codificación predeterminada de ISO-8859-1 se utilizará para el análisis.
Para la parte de la cadena de consulta, sabemos que si la enviamos a través de Get o Post, todos los parámetros se guardan en los parámetros, y luego usamos request.getParameter, el trabajo de decodificación se realiza cuando el método GetParameter se llama la primera vez. Dentro del método GetParameter llama al método ParseParameters de org.apache.catalina.connector.request, que decodificará los parámetros pasados. El siguiente código es solo parte del método ParseParameters:
// Obtener la cadena de codificación enc = getCharacteriCoding (); // Obtenga el booleano Charset definido en ContentType UseBodyBodyEncodingForUri = conector.getUseBodyEncodingForUri (); if (enc! = null) {// Si la codificación no está vacía, establezca la codificación en parámetros ENC.setEncoding (ENC); if (UseBodyEncodingForuri) {// if se establece el gráfico, configure la decodificación de QueryString a los parámetros del gráfico. }} else {// Establezca los parámetros del método de decodificación predeterminado.setEncoding (org.apache.coyote.constants.default_character_encoding); if (UseBodyEncodingForUri) {Parameters.SetQueryStringEncoding (org.apache.coyote.constants.default_character_encoding); }} En el código anterior, podemos ver que el formato de decodificación de la cadena de consulta usa el cuadro establecido o usa el formato de decodificación predeterminado ISO-8859-1. Tenga en cuenta que el gráfico en esta configuración es el ContentType definido en el encabezado HTTP. Al mismo tiempo, si necesitamos cambiar el atributo especificado para entrar en vigencia, necesitamos configurar lo siguiente:
<Conector uriEncoding = "UTF-8" UseBodyEncodingForUri = "True"/>
La parte anterior introduce el proceso de codificación y decodificación de las solicitudes de URL en detalle. De hecho, para nosotros, nuestras más formas son enviar en el formulario.
Formulario Get Get
Sabemos que enviar datos a través de URL es fácil de causar problemas de código confuso, por lo que tendemos a usar formularios de formularios. Cuando el usuario hace clic en Enviar el formulario, el navegador establecerá más códigos para pasar los datos al servidor. Los datos enviados a través de GET se empalman después de la URL (¿se puede considerar como una cadena de consulta? El servidor TomCat decodificará de acuerdo con el conjunto URIEncoding, y si no está configurado, usará el ISO-8859-1 predeterminado para decodificar. Si establecemos la codificación en UTF-8 en la página, y UriEncoding no está o no está configurado, entonces el código confuso se producirá cuando el servidor decodte. En este momento, generalmente podemos obtener los datos correctos a través de la forma de nueva cadena (request.getParameter ("nombre"). GetBytes ("ISO-8859-1"), "UTF-8").
Formulario
Para el método de publicación, la codificación que utiliza también está determinada por la página, es decir, contentType. Cuando envío un formulario haciendo clic en el botón Enviar en la página, el navegador codificará primero los parámetros del formulario de publicación de acuerdo con el formato de codificación Charset del OntentType y lo enviará al servidor. En el lado del servidor, también usa el conjunto de caracteres establecido en el ContentType para decodificar (es diferente del método GET aquí). Esto significa que los parámetros enviados a través del formulario posterior generalmente no tienen problemas confusos. Por supuesto, podemos establecer el conjunto de caracteres que codifica nosotros mismos: request.setcharacterEncoding (charset).
Resuelve el problema de las URL confundidas en chino
Principalmente enviamos solicitudes al servidor a través de dos formularios de envío: URL y formulario. El formulario de forma generalmente no tiene problemas confusos, y los problemas confusos están principalmente en la URL. A través de la introducción de los blogs anteriores, sabemos que el proceso de enviar la codificación de solicitudes al servidor por URL es realmente demasiado confuso. Diferentes sistemas operativos, diferentes navegadores y diferentes conjuntos de caracteres web conducirán a resultados de codificación completamente diferentes. ¿No es demasiado aterrador si los programadores quieren tener en cuenta todos los resultados? ¿Hay alguna manera de asegurarse de que el cliente solo use un método de codificación para emitir una solicitud al servidor?
¡tener! Aquí proporciono principalmente los siguientes métodos
javascript
El uso de la codificación de JavaScript no le da al navegador la oportunidad de intervenir. Después de codificar, envíe una solicitud al servidor y luego la decodifique en el servidor. Al dominar este método, necesitamos tres métodos de codificación de JavaScript: Escape (), Encodeuri () y EncodeUriComponent ().
escapar
La cadena especificada se codifica utilizando el conjunto de caracteres SIO Latin. Todos los caracteres no ASCII están codificados como cadenas en formato %xx, donde xx representa el número hexadecimal correspondiente al carácter en el conjunto de caracteres. Por ejemplo, la codificación correspondiente al formato es %20. Su método de decodificación correspondiente es unescape ().
De hecho, Escape () no se puede usar directamente para la codificación de URL, su función real es devolver el valor codificado unicode de un personaje. Por ejemplo, el resultado de "I Am CM" anterior es %U6211 %U662FCM, donde la codificación correspondiente de "I" es 6211, la codificación de "Sí" es 662F y la codificación de "CM" es CM.
Tenga en cuenta que Escape () no está codificado por "+". Pero sabemos que cuando una página web envía un formulario, si hay espacios, se convertirá en + caracteres. Cuando el servidor procesa los datos, el signo + se procesará en espacios. Por lo tanto, tenga cuidado al usarlo.
encodeuri
Codificando la URL completa, utiliza el formato UTF-8 para emitir la cadena codificada. Sin embargo, Codeuri no codificará algunos caracteres especiales, excepto la codificación ASCII, como :! @ # $ & * () =: /; ? + '.
encodeuricomponent
Convierta las cadenas URI en cadenas de formato de escape en formato de codificación UTF-8. En comparación con Codeuri, CodeuricOponent será más poderoso, y se codificará para símbolos (; / ?: @ & = + $, #) que no están codificados en Encodeuri (). Sin embargo, CodeuricOponent solo codificará los componentes de la URL individualmente y no se utilizará para codificar toda la URL. El método de función de decodificación correspondiente decodeuricomponent.
Por supuesto, generalmente usamos la parte Codeuri para realizar operaciones de codificación. La llamada codificación y decodificación de JavaScript dos veces en el fondo es usar este método. Hay dos soluciones para resolver este problema en JavaScript: uno de transcodificación y dos métodos de transcodificación.
Transcoding una vez
Transcodificación de JavaScript:
var url = '<s: propiedad value = "webpath" />/showmoblieqrcode.servlet?name=i am cm'; window.location.href = codeDuri (url);
URL transcodificada: http://127.0.0.1:8080/perbank/showmoblieqrcode.servlet?name=%E6%88%91%E6%98%afcm
Procesamiento de backend:
Name de cadena = request.getParameter ("nombre"); System.out.println ("Parámetros entrantes de primer plano:" + nombre); name = new String (name.getBytes ("ISO-8859-1"), "UTF-8"); System.out.println ("Parámetros decodificados:" + nombre); Resultado de salida:
Parámetros entrantes en la recepción: ?????? CM
Después de los parámetros de decodificación: soy CM
Transcodificación secundaria
javascript
var url = '<s: propiedad value = "webpath" />/showmoblieqrcode.servlet?name=i am cm'; window.location.href = encodeuri (encodeuri (url));
URL transcodificada: http://127.0.0.1:8080/perbank/showmoblieqrcode.servlet?name=%25E6%2588%2591%25E6%2598%25Afcm
Procesamiento de backend:
Name de cadena = request.getParameter ("nombre"); System.out.println ("Parámetros entrantes de primer plano:" + nombre); nombre = urlDecoder.Decode (nombre, "UTF-8"); System.out.println ("Parámetros decodificados:" + nombre); Resultado de salida:
Parámetros entrantes frontales: E68891E698AFCM
Después de los parámetros de decodificación: soy CM
filtrar
Usando filtros, los filtros proporcionan dos tipos, el primero es establecer la codificación, y el segundo es realizar operaciones de decodificación directamente en el filtro.
Filtro 1
Este filtro establece directamente el formato de codificación de la solicitud.
El personaje de la clase pública implementa el filtro {configuración privada FilterConfig; Codificación de cadena = nulo; public void destruye () {config = null; } public void dofilter (ServletRequest Solicitud, Respuesta ServletResponse, FilterChain Chain) lanza ioexception, servletException {request.setcharacterEncoding (codificación); Chain.dofilter (solicitud, respuesta); } public void init (FilterConfig config) lanza ServletException {this.config = config; // Obtener parámetros de configuración String str = config.getInitParameter ("codificación"); if (str! = null) {coding = str; }}} Configuración:
<!-Configuración de filtro chino-> <filter> <filter-name> chinocoding </filter-name> <filter-class> com.test.filter.characterIncoding </filter-class> <init-param> <amamname> codificación </aam-name> <amam-value> utf-8 </param-value> </init-param> <///filtro-mapeo> <filter-name> cheenEncoding </filter-name> <url-pattern>/*</ url-pattern> </filter-mapping>
Filtro 2
En el método de procesamiento, el filtro decodifica directamente los parámetros y luego restablece los parámetros decodificados al atributo de solicitud.
El personaje de la clase pública implementa el filtro {FilterConfig FilterConfig de FilterConfig protegido; Codificación de cadena = nulo; public void destruye () {this.filterConfig = null; } / *** Inicializar* / public void init (filterconfig filterconfig) {this.filterconfig = filterconfig; } / *** Convierta Instr en el formulario de codificación de UTF -8** @param Instr Enter String* @return Utf - El formulario de codificación de 8 String* @throws UnspportedEnCodingEntingException* / private String toutf (String Instr) lanza UnspportedEncodingException {String Outstr = ""; "; if (instr! = null) {outstr = new String (instr.getBytes ("ISO-8859-1"), "UTF-8"); } return outstr; } / *** Procesamiento de filtrado de confuso chino* / public void dofilter (ServLetRequest ServLetRequest, ServletResponse ServLetResponse, FilterChain Chain) lanza IOException, ServletException {httpServletRequest solicitud = (httpServletRequest) ServLetRequest; HttpservletResponse respuesta = (httpservletResponse) servletResponse; // El método para obtener la solicitud (1.post o 2.get), y se realiza un procesamiento diferente de acuerdo con diferentes métodos de solicitud, método de cadena = request.getMethod (); // 1. Para las solicitudes enviadas en la publicación, establezca directamente la codificación en UTF-8 if (Method.equalSignorEcase ("Post")) {try {request.setcharacterEncoding ("utf-8"); } catch (UnsupportedEncodingException e) {E.PrintStackTrace (); }} // 2. Solicitud enviada en Get Else {// Obtenga el conjunto de parámetros enviado por la enumeración del cliente <String> paramNames = request.getParamTernames (); // atraviesa el conjunto de parámetros para obtener el nombre y el valor de cada parámetro mientras (paramNames.hasmoreElements ()) {String name = paramNames.NextElement (); // Obtenga los valores de cadena de nombre del parámetro [] = request.getParametervalues (nombre); // Saque su valor de acuerdo con el nombre del parámetro // si el conjunto de valor del parámetro no está vacío if (valores! = Nulo) {// atraviesa el valor del parámetro establecido para (int i = 0; i <valores.length; i ++) {try {// círculo hacia atrás y llame a cada valor toutf (valores [i]) método para convertir el carácter que encodula el valor de parámetro VLURC = toutf (valores de valor toutf (valores [i]) para convertir el carácter que encodifica el valor de parámetro VLURC. valores [i] = vlustr; } catch (UnsupportedEncodingException e) {E.PrintStackTrace (); }} // Ocultar el valor en forma de atributo en solicitud Solicitud de solicitud.SetAttribute (nombre, valores); }}} // Establezca el método de respuesta y admite la respuesta del conjunto de caracteres chino.setContentType ("text/html; charset = utf-8"); // Continuar ejecutando el siguiente filtro. Si no hay filtro, la solicitud será Chain.dofilter (solicitud, respuesta); }} Configuración:
<!-Configuración de filtro chino-> <filter> <filter-name> chinocoding </filter-name> <filter-class> com.test.filter.characteriCoding </filter-class> </filtre> <filter-mapping> <filter-name> chinebrooding </filtre-name> <url-pattern>/*</ url-pattern> </filter-papping>
otro
1. Establezca PageCoding y ContentType
<%@ page lenguaje = "java" contentType = "text/html; charset = utf-8" pageEncoding = "UTF-8"%>
2. Establezca el uriencoding de Tomcat
De manera predeterminada, el servidor TomCat utiliza el formato de codificación ISO-8859-1 para codificar la URL solicitada por el parámetro UriEncoding, por lo que solo necesitamos agregar UriEncoding = "UTF-8" a la etiqueta <nector> del archivo Server.xml de TomCat.