Codificação Java URL de parâmetros de query string

Digamos que eu tenho um URL.

http://example.com/query?q=

e eu tenho uma consulta introduzida pelo usuário, como por exemplo:

palavra aleatória £500 banco $

Eu quero que o resultado seja um URL devidamente codificado:

http://example.com/query?q=random%20word%20%A3500%20bank%20%24

Qual'é a melhor maneira de conseguir isto? Eu tentei URLEncoder e criar objetos URI/URL, mas nenhum deles saiu muito bem.

Solução

TURLEncoder` deve ser o caminho a seguir. Você só precisa ter em mente para codificar somente o nome e/ou valor do parâmetro individual da query string, não a URL inteira, com certeza não o caractere separador do parâmetro da query string & nem o caractere separador do valor do nome do parâmetro =.

String q = "random word £500 bank $";
String url = "http://example.com/query?q=" + URLEncoder.encode(q, "UTF-8");

Note que os espaços nos parâmetros de consulta são representados por +, e não por %20, o que é legitimamente válido. O %20 é normalmente utilizado para representar espaços no próprio URI (a parte antes do caractere separador da string URI ?``), não na string da consulta (a parte depois de?``).

Note também que existem dois métodos encode(). Um sem argumento charset e outro com. O sem argumento de charset é depreciado. Nunca o utilize e sempre especifique o argumento charset. O javadoc recomenda mesmo explicitamente a utilização da codificação UTF-8, conforme mandado por RFC3986 e W3C.

Todos os outros caracteres são inseguros e são primeiro convertidos em um ou mais bytes usando algum esquema de codificação. Depois cada byte é representado pela cadeia de 3 caracteres "%xy" onde xy é a representação hexadecimal de dois dígitos do byte. **O esquema de codificação recomendado para usar é UTF-8***. Entretanto, por razões de compatibilidade, se uma codificação não for especificada, então a codificação padrão da plataforma é usada.

Vê também:

Comentários (11)

Eu não utilizaria o URLEncoder. Além de ser chamado incorretamente (o URLEncoder não tem nada a ver com URLs), ineficiente (ele utiliza um StringBuffer ao invés de Builder e faz algumas outras coisas que são lentas) Também é muito fácil estragar tudo.

Ao invés disso eu utilizaria URIBuilder ou Spring's org.springframework.web.util.UriUtils.encodeQuery ou Commons Apache HttpClient. A razão sendo que você tem que escapar do nome dos parâmetros da consulta (ie BalusC's answer q) de forma diferente do valor do parâmetro.

A única desvantagem do acima (que eu descobri dolorosamente) é que URL's não são um verdadeiro subconjunto de URI's.

Código da amostra:

import org.apache.http.client.utils.URIBuilder;

URIBuilder ub = new URIBuilder("http://example.com/query");
ub.addParameter("q", "random word £500 bank \$");
String url = ub.toString();

// Result: http://example.com/query?q=random+word+%C2%A3500+bank+%24

Desde I'estou apenas a ligar a outras respostas, marquei isto como um wiki comunitário. Sinta-se à vontade para editar.

Comentários (9)