Qual é a maneira idiomática de compor uma URL ou URI em Java?

115

Como faço para construir um URL ou URI em Java? Existe uma forma idiomática ou bibliotecas que fazem isso facilmente?

Preciso permitir iniciar a partir de uma string de solicitação, analisar / alterar várias partes de URL (esquema, host, caminho, string de consulta) e oferecer suporte à adição e codificação automática de parâmetros de consulta.

Jon077
fonte
7
Votar positivamente a questão muito depois de ter sido fechada porque não está claro se existe uma solução popular e não obsoleta para esse problema. Eu encontrei isso pesquisando por 'java URL parameter class'.
user1445967
4
Minha intenção era encontrar um construtor de URL para Java, e esta questão é útil pelo menos para mim.
whirlwin

Respostas:

76

A partir do Apache HTTP Component HttpClient 4.1.3, do tutorial oficial :

public class HttpClientTest {
public static void main(String[] args) throws URISyntaxException {
    List<NameValuePair> qparams = new ArrayList<NameValuePair>();
    qparams.add(new BasicNameValuePair("q", "httpclient"));
    qparams.add(new BasicNameValuePair("btnG", "Google Search"));
    qparams.add(new BasicNameValuePair("aq", "f"));
    qparams.add(new BasicNameValuePair("oq", null));
    URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
                                 URLEncodedUtils.format(qparams, "UTF-8"), null);
    HttpGet httpget = new HttpGet(uri);
    System.out.println(httpget.getURI());
    //http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
}
}

Editar: a partir da v4.2 URIUtils.createURI()tornou-se obsoleto em favor de URIBuilder:

URI uri = new URIBuilder()
        .setScheme("http")
        .setHost("www.google.com")
        .setPath("/search")
        .setParameter("q", "httpclient")
        .setParameter("btnG", "Google Search")
        .setParameter("aq", "f")
        .setParameter("oq", "")
        .build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
Chikei
fonte
20
Isso funciona, mas a partir da v4.2 URIUtils.createURI () tornou-se obsoleto em favor do URIBuilder. Do lado positivo, este URIBuilder parece ter um método addParameter (), portanto, construir strings de solicitação deve ser pelo menos mais simples agora.
stian
6
URIBuilder builder = new URIBuilder() .setScheme("http") .setHost("www.google.com") .setParameters(qparams);como @stian disse
vanduc1102
Println acima imprime o seguinte; google.com/…
Berkan Ercan
61

Como autor, provavelmente não sou a melhor pessoa para julgar se meu construtor de URL / URI é bom , mas aqui está: https://github.com/mikaelhg/urlbuilder

Eu queria a solução completa mais simples possível com zero dependências fora do JDK, então tive que lançar a minha própria.

Mikael Gueck
fonte
6
Parece ótimo Mikael, você já pensou em publicá-lo para a maven central? Eu sei que é pequeno, mas torna o uso mais fácil. Não consigo encontrar uma classe semelhante além de JAX-RS. A falta de dependências é definitivamente uma vantagem.
Barry Pitman
Parece bom, mas como é um construtor e, portanto, mutável, por que existem setters apenas para parâmetros, mas não para host, porta, protocolo e caminho? E, bem, não há getters para aqueles também. UPD: Oh, não é mutável - setParameter cria um clone. Bem, setHost / setPort / ... poderia funcionar da mesma maneira. Ou, talvez, seria bom ter uma versão mutável também.
mvmn
3
"solução completa mais simples possível com zero dependências" - Parece que você sabe o que é importante! Sua resposta deve ser a aceita. Incluir todo o HttpClient (com todas as atualizações de versão e até mesmo descontinuar a própria API sobre a qual esta questão se refere) apenas para construir uma url é o que torna os aplicativos mais cheios de bugs com muitos bugs.
Stijn de Witt
2
Finalmente no Maven Central, e levei apenas quatro anos para terminar.
Mikael Gueck de
@mikaelhg Obrigado! Eu preciso exatamente neste momento!
Fabian Damken
29

Usar HTTPClient funcionou bem.

protected static String createUrl(List<NameValuePair> pairs) throws URIException{

  HttpMethod method = new GetMethod("http://example.org");
  method.setQueryString(pairs.toArray(new NameValuePair[]{}));

  return method.getURI().getEscapedURI();

}
Jon077
fonte
6
Esta agora é uma funcionalidade obsoleta. Alguém sabe como usar o novo pacote de componentes HTTP para fazer o mesmo porque me deixou perplexo.
Link19
3
A nova versão 4x não suporta mais isso.
Joscha de
13

Existem muitas bibliotecas que podem ajudá-lo com a construção de URI (não reinvente a roda). Aqui estão três para você começar:


Java EE 7

import javax.ws.rs.core.UriBuilder;
...
return UriBuilder.fromUri(url).queryParam(key, value).build();

org.apache.httpcomponents: httpclient: 4.5.2

import org.apache.http.client.utils.URIBuilder;
...
return new URIBuilder(url).addParameter(key, value).build();

org.springframework: spring-web: 4.2.5.RELEASE

import org.springframework.web.util.UriComponentsBuilder;
...
return UriComponentsBuilder.fromUriString(url).queryParam(key, value).build().toUri();

Veja também: GIST> Testes de Construtor de URI

Nick Grealy
fonte
2
EE 7 é a resposta correta. Tudo o que você precisa fazer é obter todo o pacote de bibliotecas EE, escolher uma implementação JAX-RS, resolver conflitos de versão jax-rs e, como recompensa, você terá uma classe UriBuilder útil que funciona muito bem. Sarcasmo à parte, esta é a resposta correta. :)
tekHedd
10

Use OkHttp

É 2020 e há uma biblioteca muito popular chamado OkHttp que foi estrelou 35K vezes no GitHub. Com esta biblioteca, você pode construir um url como abaixo:

import okhttp3.HttpUrl;

URL url = new HttpUrl.Builder()
    .scheme("http")
    .host("example.com")
    .port(4567)
    .addPathSegment("foldername/1234")
    .addQueryParameter("abc", "xyz")
    .build().url();
Tyler Long
fonte
Corrigi um erro de digitação, é addPathSegment(não addPathSegments).
PapaFreud
1

Depois de ser criticado por sugerir a classe de URL. Vou seguir o conselho do comentarista e sugerir a classe URI . Eu sugiro que você olhe atentamente para os construtores de um URI, pois a classe é muito imutável depois de criada.
Acho que esse construtor permite que você defina tudo no URI que você possa precisar.

URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment)
          Constructs a hierarchical URI from the given components.
Mike Pone
fonte
8
Mas não fornece funcionalidade para realmente construir e codificar uma string de consulta a partir de um conjunto de pares nome-valor.
Link19
4
Como a criança prodígio disse a Alan Partridge - não se pode ter degradações de imutabilidade, ou é ou não é ;-) youtube.com/watch?v=_lvFns5Lubc
Stewart
O construtor do URI faz coisas desagradáveis ​​no caminho. Consulte blog.palominolabs.com/2013/10/03/… para obter os detalhes.
mpierce
1
Deixe esta resposta ser um exemplo de como NÃO fazer isso então.
Mike Pone
1
Consulta de string ... Obrigado Sun / Oracle pela granularidade. Vamos apenas substituir todos os espaços por símbolos de adição, codificar em uri todos os parâmetros e vinculá-los todos com símbolos de e comercial, então ... bate a cabeça repetidamente na mesa
Stijn de Witt