Codificação e decodificação
Através da figura a seguir, podemos entender onde há transcodificação em Javaweb:
O usuário deseja que o servidor envie uma solicitação HTTP. Os locais onde a codificação são URL, cookies e parâmetro são necessários. Após a codificação, o servidor aceita a solicitação HTTP, analisa a solicitação HTTP e decodifica o URL, os cookies e o parâmetro. Durante o processamento da lógica de negócios do servidor, pode ser necessário ler bancos de dados, arquivos locais ou outros arquivos na rede etc., e esses processos requerem codificação e decodificação. Após a conclusão do processamento, o servidor codifica os dados e os envia para o cliente, e o navegador os exibe ao usuário após a decodificação. Existem muitas codificação e decodificação envolvidas em todo esse processo, e o local mais provável para parecer ilegal é o processo de interagir com o servidor e o cliente.
Todo o processo acima pode ser resumido da seguinte forma: os dados codificados pela página são passados para o servidor e o servidor decodifica os dados obtidos e, após algum processamento lógico de negócios, o resultado final é codificado e processado, e o cliente decodifica e o exibe para o usuário. Então, abaixo, pedirei uma explicação da codificação e decodificação de Javaweb.
Se o cliente quiser que o servidor envie uma solicitação, ele passará quatro situações:
1. Acesso direto por URL.
2. Link da página.
3. Formulário Obtenha envio
4. Formulário Post Submission
Método URL: Para URLs, se todos os URLs estiverem em inglês, não há problema. Se houver chinês, a codificação estará envolvida. Como codificar? Que regras você deseja codificar? Então, como decodificá -lo? As respostas serão respondidas uma a uma abaixo! Primeiro veja os componentes do URL:
Neste URL, o navegador codificará o caminho e o parâmetro. Para explicar melhor o processo de codificação, use o seguinte URL
http://127.0.0.1:8080/perbank/i am cm? name = eu sou cm
Digite o endereço acima na caixa de entrada URL do navegador. Ao visualizar as informações do cabeçalho da mensagem HTTP, podemos ver como o navegador as codifica. Aqui estão as condições de codificação de três navegadores:
Você pode ver que a codificação de "I Am" pelos principais navegadores é a seguinte:
parte do caminho | String 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 |
Ou seja | E6 88 91 E6 98 AF | CE D2 CA C7 |
Void protegido converturi (MessageBytes URI, solicitação de solicitação) lança a exceção {bytechunk bc = uri.getbytechunk (); int length = bc.getLength (); Charchunk cc = uri.getcharchunk (); cc.Allocate (comprimento, -1); String ENC = Connector.geturiencoding (); // Obtenha o conjunto de decodificação de URI se (Enc! = NULL) {B2CConverter conv = request.geturiconverter (); tente {if (conv == null) {conv = new B2CConverter (ENC); request.seturiconverter (conv); }} catch (ioexception e) {...} if (conv! = null) {tente {conv.convert (bc, cc, cc.getBuffer (). length - cc.getEnd ()); uri.setchars (cc.getBuffer (), cc.getStart (), cc.getLength ()); retornar; } catch (ioexception e) {...}}} // codificação padrão: byte de conversão rápida [] bbuf = bc.getBuffer (); char [] cbuf = cc.getBuffer (); int start = bc.getStart (); for (int i = 0; i <comprimento; i ++) {cbuf [i] = (char) (bbuf [i+start] & 0xff); } uri.setchars (cbuf, 0, comprimento); } A partir do código acima, podemos ver que a operação de decodificação do URI é primeiro obter o conjunto de decodificação do conector, que está configurado no server.xml
<Conector uriencoding = "utf-8" />
Se não for definido, o ISO-8859-1 padrão será usado para análise.
Para a parte da string de consulta, sabemos que, se a enviamos por meio de Get ou Post, todos os parâmetros são salvos nos parâmetros e, em seguida, usamos o request.getParameter, o trabalho de decodificação é realizado quando o método getParameter é chamado pela primeira vez. Dentro do método getParameter, ele chama o método parseparameter de org.apache.catalina.connector.request, que decodificará os parâmetros passados. O código a seguir é apenas parte do método Parseparameters:
// obtenha a string codificadora Enc = getCharacterencoding (); // Obtenha o charset boolean definido no contentType usebodyEncodingForURI = Connector.GetuseBodyEncodingForURI (); if (enc! = null) {// Se a codificação não estiver vazia, defina a codificação como parâmetros.SetEncoding (ENC); if (usebodyEncodingForuri) {// Se o ChartSet estiver definido, defina a decodificação do querystring para o ChartSet Parameters.setQueryStringEncoding (ENC); }} else {// Defina os parâmetros do método de decodificação padrão.setEncoding (org.apache.coyote.constants.default_character_encoding); if (usebodyEncodingForuri) {parameters.setQueryStringEncoding (org.apache.coyote.constants.default_character_encoding); }} A partir do código acima, podemos ver que o formato de decodificação da sequência de consultas usa o conjunto de cartões set ou o formato de decodificação padrão ISO-8859-1. Observe que o gráfico nessa configuração é o contentType definido no cabeçalho HTTP. Ao mesmo tempo, se precisarmos alterar o atributo especificado para entrar em vigor, precisamos configurar o seguinte:
<Connector uriencoding = "utf-8" usebodyEncodingForuri = "true"/>
A parte acima apresenta o processo de codificação e decodificação das solicitações de URL em detalhes. De fato, para nós, nossos mais caminhos são enviar no formulário.
Forma obtida
Sabemos que o envio de dados através dos URLs é fácil de causar problemas de código ilegal, por isso tendemos a usar o formulário. Quando o usuário clica em enviar o formulário, o navegador define mais códigos para passar os dados para o servidor. Os dados enviados através do get são emendados após o URL (pode ser considerado uma sequência de consulta? O servidor Tomcat decodificará de acordo com o uiencoding definido e, se não estiver definido, ele usará o ISO-8859-1 padrão para decodificar. Se definirmos a codificação para o UTF-8 na página, e o UriEncoding não estiver ou não estiver definido, o código ilegal ocorrerá quando o servidor decodificar. No momento, geralmente podemos obter os dados corretos através da forma de nova string (request.getParameter ("nome"). GetBytes ("ISO-8859-1"), "UTF-8").
Formulário post
Para o método de postagem, a codificação que ele usa também é determinada pela página, ou seja, ContentType. Quando enviar um formulário clicando no botão Enviar na página, o navegador codificará primeiro os parâmetros do formulário de postagem de acordo com o formato de codificação do Charset do OntentType e o envie ao servidor. No lado do servidor, ele também usa o conjunto de caracteres no contentType para decodificar (é diferente do método GET aqui). Isso significa que os parâmetros enviados através do formulário de postagem geralmente não têm problemas ilegais. Obviamente, podemos definir o conjunto de caracteres que codifica: request.SetcharActerEncoding (charset).
Resolva o problema dos URLs ilegais em chinês
Enviamos principalmente solicitações ao servidor através de duas formas de envio: URL e formulário. A forma de forma geralmente não tem problemas ilegíveis, e os problemas ilegíveis estão principalmente no URL. Através da introdução dos blogs anteriores, sabemos que o processo de envio de solicitações de codificação para o servidor por URL é realmente muito confuso. Sistemas operacionais diferentes, diferentes navegadores e diferentes conjuntos de personagens da Web levarão a resultados de codificação completamente diferentes. Não é muito assustador se os programadores desejam levar em consideração todos os resultados? Existe uma maneira de garantir que o cliente use apenas um método de codificação para emitir uma solicitação ao servidor?
ter! Aqui eu forneço principalmente os seguintes métodos
JavaScript
O uso da codificação JavaScript não dá ao navegador a chance de intervir. Após a codificação, envie uma solicitação para o servidor e decodificá -la no servidor. Ao dominar esse método, precisamos de três métodos de codificação JavaScript: Escape (), Encodeuri () e EncodEuricomponent ().
escapar
A sequência especificada é codificada usando o conjunto de caracteres latinos SIO. Todos os caracteres não-ASCII são codificados como strings no formato %xx, onde xx representa o número hexadecimal correspondente ao caractere no conjunto de caracteres. Por exemplo, a codificação correspondente ao formato é %20. Seu método de decodificação correspondente é UNESCAPE ().
De fato, Escape () não pode ser usado diretamente para a codificação de URL, sua função real é retornar o valor codificado por unicode de um caractere. Por exemplo, o resultado de "eu sou CM" acima é %U6211 %U662FCM, onde a codificação correspondente de "I" é 6211, a codificação de "Sim" é 662F e a codificação de "CM" é CM.
Observe que o Escape () não é codificado por "+". Mas sabemos que quando uma página da web envia um formulário, se houver espaços, ele será convertido em + caracteres. Quando o servidor processa dados, o sinal + será processado em espaços. Portanto, tenha cuidado ao usá -lo.
Encodeuri
Codendo todo o URL, ele usa o formato UTF-8 para emitir a sequência codificada. No entanto, o Encodeuri não codificará alguns caracteres especiais, exceto a codificação ASCII, como :! @ # $ & * () =: /; ? + '.
Encodeuricomponent
Converta seqüências de URI em seqüências de escape no formato de codificação UTF-8. Comparado ao EncodEuri, o Encodeuricomponent será mais poderoso e será codificado para símbolos (; / ?: @ & = + $, #) que não são codificados em codeuri (). No entanto, o codeuricomponent codificará apenas os componentes do URL individualmente e não será usado para codificar todo o URL. O método de função decodificadora correspondente decodEuricomponent.
Obviamente, geralmente usamos a parte Encodeuri para executar operações de codificação. O chamado JavaScript codificando e decodificando duas vezes em segundo plano é usar esse método. Existem duas soluções para resolver esse problema no JavaScript: uma transcodificação e dois métodos de transcodificação.
Transcodificação uma vez
JavaScript Transcoding:
var url = '<s: Property value = "webpath" />/showmoblieqrcode.servlet?name=i am cm'; window.Location.href = codeuri (url);
URL transcodificado: http://127.0.0.1:8080/perbank/showmoblieqrcode.servlet?name=%E6%88%91%E6%98%AFCM
Processamento de back -end:
Nome da string = request.getParameter ("nome"); System.out.println ("Parâmetros de entrada em primeiro plano:" + nome); nome = new String (name.getBytes ("ISO-8859-1"), "UTF-8"); System.out.println ("Parâmetros decodificados:" + nome); Resultado da saída:
Parâmetros de entrada na recepção: ????? cm
Após a decodificação dos parâmetros: eu sou CM
Transcodificação secundária
JavaScript
var url = '<s: Property value = "webpath" />/showmoblieqrcode.servlet?name=i am cm'; window.Location.href = codeuri (codeuri (url));
URL transcodificado: http://127.0.0.1:8080/perbank/showmoblieqrcode.servlet?name=%25e6%2588%2591%25e6%2598%25afcm
Processamento de back -end:
Nome da string = request.getParameter ("nome"); System.out.println ("Parâmetros de entrada em primeiro plano:" + nome); nome = urldecoder.Decode (nome, "utf-8"); System.out.println ("Parâmetros decodificados:" + nome); Resultado da saída:
Parâmetros de entrada do front-end: E68891E698AFCM
Após a decodificação dos parâmetros: eu sou CM
filtro
Usando filtros, os filtros fornecem dois tipos, o primeiro é definir a codificação e o segundo é executar operações de decodificação diretamente no filtro.
Filtro 1
Este filtro define diretamente o formato de codificação da solicitação.
classe pública CaracterEncoding implementa filtro {private filterConfig config; String codinging = null; public void Destroy () {config = null; } public void Dofilter (Solicitação de servletRequest, resposta servletResponse, cadeia de filtro) lança IoException, servletexception {request.SetcharAcTerEncoding (codificação); Chain.Dofilter (solicitação, resposta); } public void init (filterConfig config) lança servletexception {this.config = config; // Obter parâmetros de configuração String str = config.getInitParameter ("Encoding"); if (str! = null) {coding = str; }}} Configuração:
<!-Configuração do filtro chinês-> <filter> <filter-name> chinês codificação </filter-name> <filter-class> com.test.filter.characterencoding </filter-class> <iit-param> <ampam-name> codificação </param-name> <aam-Value> utf-8 </param> <Filter-Name> Chinesencoding </filter-Name> <url-tattern>/*</url-tattern> </filter-Mapping>
Filtro 2
No método de processamento, o filtro decodifica diretamente os parâmetros e depois redefine os parâmetros decodificados para o atributo de solicitação.
classe pública Caracterencoding implementa filtro {Protected filterConfig filterConfig; String codinging = null; public void Destroy () {this.FilterConfig = null; } / *** inicialize* / public void init (filtroConfig filterConfig) {this.FilterConfig = filterConfig; } / *** Converta Instr no formulário de codificação do UTF -8** @param Instr Enter String* @RETURN UTF - 8 de codificação de 8 String* @Throws UnsupportEdEnCodingException* / String private Toutf (String Instr) lança UnsupportEnCodingException {String Outstr = "";; if (Instr! = NULL) {Outstr = new String (Instr.GetBytes ("ISO-8859-1"), "UTF-8"); } return fortr; } / *** Processamento de filtragem iluminado chinês* / Public void Dofilter (servletRequest servletRequest, servletResponse servletResponse, cadeia de filtro) lança IoException, servletexception {httpservleTleQuest request = (httpSleTleTequest) servleTreleTrequest; HttpServLeTResponse Response = (httpServletResponse) servletResponse; // O método para obter a solicitação (1.Post ou 2.GeT) e processamento diferente é executado de acordo com diferentes métodos de solicitação String Method = request.getMethod (); // 1. Para solicitações enviadas no post, defina diretamente a codificação como utf-8 if (method.equalsignorecase ("post")) {try {request.Setcharacterencoding ("utf-8"); } Catch (UnsupportEdEncodingException e) {E.PrintStackTrace (); }} // 2. Solicitação enviada no get else {// retire o parâmetro definido enviado pela enumeração do cliente <tring> paramnames = request.getParameterNames (); // Atravesse o parâmetro definido para obter o nome e o valor de cada parâmetro while (paramnames.hasmoreElements ()) {string name = paramnames.nextElement (); // retire o nome do parâmetro String valores [] = request.getParameTerValues (nome); // retire seu valor de acordo com o nome do parâmetro // se o conjunto de valor do parâmetro não estiver vazio se (valores! valores [i] = vluste; } Catch (UnsupportEdEncodingException e) {E.PrintStackTrace (); }} // Ocultar o valor na forma de um atributo na solicitação solicitação.SetAttribute (nome, valores); }}} // Defina o método de resposta e suporta o conjunto de caracteres chinês. // continua a executar o próximo filtro. Se não houver filtro, a solicitação será a cadeia.Dofilter (solicitação, resposta); }} Configuração:
<!-Configuração do filtro chinês-> <filter> <filter-name> chinês codificação </filter-name> <filter-class> com.test.filter.characterencoding </filter-Class> </filter> <filter-Mapping> </filter-name> chinesescoding </filter-name> <url-tattern>/*</url-Pattern>
outro
1. Defina a PageNencoding e o ContentType
<%@ página de página = "java" contentType = "text/html; charset = utf-8" pageEncoding = "utf-8"%>
2. Configure o urincoding de Tomcat
Por padrão, o servidor TomCat usa o formato de codificação ISO-8859-1 para codificar o URL solicitado pelo parâmetro Uriencoding, portanto, precisamos adicionar apenas UriEncoding = "UTF-8" à tag <nector> do arquivo server.xml do tomcat.