¿Cuál es la forma idiomática de componer una URL o URI en Java?

115

¿Cómo creo una URL o una URI en Java? ¿Existe una forma idiomática o bibliotecas que lo hagan fácilmente?

Necesito permitir comenzar desde una cadena de solicitud, analizar / cambiar varias partes de la URL (esquema, host, ruta, cadena de consulta) y admitir la adición y codificación automática de parámetros de consulta.

jon077
fuente
7
Votar a favor la pregunta mucho después de que se cierre porque no está claro si existe una solución popular no obsoleta para este problema. Encontré esto buscando en Google 'clase de parámetro de URL de Java'.
user1445967
4
Mi intención era encontrar un creador de URL para Java, y esta pregunta es útil para mí al menos.
Whirlwin

Respuestas:

76

A partir del componente HTTP Apache HttpClient 4.1.3, del 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 de v4.2 URIUtils.createURI()se ha desaprobado a 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
fuente
20
Esto funciona, pero a partir de la versión 4.2, URIUtils.createURI () ha quedado obsoleto en favor de URIBuilder. En el lado positivo, este URIBuilder parece tener un método addParameter (), por lo que la creación de cadenas de solicitud debería ser al menos más simple ahora.
stian
6
URIBuilder builder = new URIBuilder() .setScheme("http") .setHost("www.google.com") .setParameters(qparams);como dijo @stian
vanduc1102
Imprimir arriba imprime lo siguiente; google.com/…
Berkan Ercan
61

Como autor, probablemente no soy la mejor persona para juzgar si mi constructor de URL / URI es bueno , pero aquí está: https://github.com/mikaelhg/urlbuilder

Quería la solución completa más simple posible con cero dependencias fuera del JDK, así que tuve que lanzar la mía.

Mikael Gueck
fuente
6
Se ve muy bien Mikael, ¿has pensado en publicarlo en maven central? Sé que es pequeño pero facilita su uso. No puedo encontrar una clase similar además de JAX-RS. La falta de dependencias es definitivamente una ventaja.
Barry Pitman
Se ve bien, pero dado que es un constructor y, por lo tanto, mutable, ¿por qué hay establecedores solo para parámetros, pero no para host, puerto, protocolo y ruta? Y, bueno, no hay captadores para esos también. UPD: Oh, no es mutable, setParameter crea un clon. Bueno, todavía setHost / setPort / ... podría funcionar de la misma manera. O, quizás, también sería bueno tener una versión mutable.
mvmn
3
"La solución completa más simple posible sin dependencias" - ¡Parece que sabe lo que es importante! Su respuesta debe ser la aceptada en mi humilde opinión. Incluir todo HttpClient (con todas sus actualizaciones de versión e incluso desaprobar la propia API de la que trata esta pregunta) solo para crear una URL es lo que hace que las aplicaciones estén plagadas de errores.
Stijn de Witt
2
Finalmente en Maven Central, y solo me tomó cuatro años terminarlo.
Mikael Gueck
@mikaelhg ¡Gracias! ¡Necesito exactamente en este momento!
Fabian Damken
29

Usar HTTPClient funcionó bien.

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
fuente
6
Esta ahora es una funcionalidad obsoleta. ¿Alguien sabe cómo usar el nuevo paquete de componentes HTTP para hacer lo mismo porque me deja perplejo?
Link19
3
La nueva versión 4x ya no admite esto.
Joscha
13

Hay muchas bibliotecas que pueden ayudarlo con la construcción de URI (no reinvente la rueda). Aquí hay tres para comenzar:


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();

Consulte también: GIST> Pruebas de constructor de URI

Nick Grealy
fuente
2
EE 7 es la respuesta correcta. Todo lo que tiene que hacer es extraer todo el conjunto de bibliotecas EE, elegir una implementación JAX-RS, resolver conflictos de versiones de jax-rs y, como recompensa, tendrá una práctica clase UriBuilder que funciona realmente bien. Dejando a un lado el sarcasmo, esta es la respuesta correcta. :)
tekHedd
1
A partir de Spring 5, consulte UriBuilder( docs.spring.io/spring-framework/docs/current/javadoc-api/org/… ) y UriBuilderFactory( docs.spring.io/spring-framework/docs/current/javadoc-api/org /… )
Brice Roncace
10

Utilice OkHttp

Es 2020 y hay una biblioteca muy popular llamada OkHttp que ha sido destacada 35K veces en GitHub. Con esta biblioteca, puede crear una URL como la siguiente:

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
fuente
He arreglado un error tipográfico, que es addPathSegment(no addPathSegments).
PapaFreud
1

Después de ser criticado por sugerir la clase de URL. Seguiré el consejo del comentarista y sugeriré la clase URI en su lugar. Le sugiero que observe de cerca los constructores de un URI, ya que la clase es muy inmutable una vez creada.
Creo que este constructor te permite configurar todo lo que puedas necesitar en el URI.

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
fuente
8
Pero no proporciona la funcionalidad para construir y codificar realmente una cadena de consulta a partir de un conjunto de pares de nombre y valor.
Enlace
4
Como el niño prodigio le dijo a Alan Partridge: uno no puede tener degradaciones de la inmutabilidad, lo es o no lo es ;-) youtube.com/watch?v=_lvFns5Lubc
Stewart
El constructor de URI hace cosas desagradables en la ruta. Consulte blog.palominolabs.com/2013/10/03/… para obtener más detalles.
mpierce
1
Deje que esta respuesta sea un ejemplo de cómo NO hacer esto entonces.
Mike Pone
1
Consulta de cadenas ... Gracias Sun / Oracle por la granularidad. Simplemente reemplazaremos todos los espacios con símbolos más, codificaremos todos los parámetros en uri y los vincularemos todos con símbolos y luego ... golpea la cabeza en la mesa repetidamente
Stijn de Witt