¿Cómo se crea un cliente REST para Java? [cerrado]

248

Con JSR 311 y sus implementaciones, tenemos un potente estándar para exponer objetos Java a través de REST. Sin embargo, en el lado del cliente, parece que falta algo que sea comparable a Apache Axis for SOAP, algo que oculta el servicio web y ordena los datos de forma transparente a los objetos Java.

¿Cómo se crean clientes RESTful de Java? ¿Usa HTTPConnection y análisis manual del resultado? ¿O clientes especializados para, por ejemplo, Jersey o Apache CXR?

Yaba
fuente
Acabo de encontrar Apache Wink en la incubadora de Apache. Podría ser un proyecto interesante para crear servidores y clientes REST.
Yaba
Consulte [Descanso] ( code.google.com/p/resting ). Promete invocar servicios REST y crear una lista de objetos a partir de la respuesta XML / JSON / YAML en un solo paso.
Neel
Descansar tiene problemas con las solicitudes POST.
RyanBrady
2
Puedes hacerlo de una manera muy simple con resteasy (por Jboss). Escribí una publicación de blog sobre cómo desarrollar un cliente REST de Java si desea una guía de inicio. De todos modos, hay cientos de alternativas en Java.
Guido

Respuestas:

205

Esta es una vieja pregunta (2008), por lo que ahora hay muchas más opciones que antes:

ACTUALIZACIONES (proyectos aún activos en 2020):

  • Componentes HTTP Apache (4.2) Adaptador fluido : reemplazo básico para JDK, utilizado por varios otros candidatos en esta lista. Mejor que el antiguo Cliente HTTP 3 de Commons y más fácil de usar para crear su propio cliente REST. Tendrá que usar algo como Jackson para el soporte de análisis JSON y puede usar los componentes HTTP URIBuilder para construir URI de recursos similares al cliente Jersey / JAX-RS Rest. Los componentes HTTP también son compatibles con NIO, pero dudo que obtenga un mejor rendimiento que BIO dada la breve naturaleza de solicitud de REST. Apache HttpComponents 5 tiene soporte HTTP / 2.
  • OkHttp : reemplazo básico para JDK, similar a los componentes http, utilizado por varios otros candidatos en esta lista. Admite protocolos HTTP más nuevos (SPDY y HTTP2). Funciona en Android. Desafortunadamente, no ofrece una verdadera opción asincrónica basada en bucle de reactor (vea los componentes Ning y HTTP más arriba). Sin embargo, si utiliza el protocolo HTTP2 más nuevo, esto no representa un problema (suponiendo que el recuento de conexiones sea un problema).
  • Ning Async-http-client : proporciona compatibilidad con NIO. Anteriormente conocido como Async-http-client por Sonatype .
  • Fingir contenedor para clientes http de nivel inferior (okhttp, apache httpcomponents). Crea automáticamente clientes basados ​​en stubs de interfaz similares a algunas extensiones de Jersey y CXF. Fuerte integración de primavera.
  • Retrofit : envoltorio para clientes http de nivel inferior (okhttp). Crea automáticamente clientes basados ​​en stubs de interfaz similares a algunas extensiones de Jersey y CXF.
  • Volley wrapper para jdk http client, de google
  • google-http wrapper para jdk http client, o apache httpcomponents, de google
  • Unirest wrapper para cliente http jdk, por kong
  • Resteasy JakartaEE wrapper para jdk http client, por jboss, parte de jboss framework
  • jcabi-http wrapper para apache httpcomponents, parte de la colección jcabi
  • envoltorio restlet para componentes http apache, parte del marco restlet
  • envoltura segura con afirmaciones para una prueba fácil

Una advertencia sobre la selección de clientes HTTP / REST. Asegúrese de verificar qué está utilizando su stack de framework para un cliente HTTP, cómo se enhebra, e idealmente use el mismo cliente si ofrece uno. Es decir, si usa algo como Vert.x o Play, puede intentar usar su cliente de respaldo para participar en cualquier bus o bucle de reactor que proporcione el marco ... de lo contrario, esté preparado para posibles problemas de subprocesos interesantes.

Adam Gent
fuente
1
Desafortunadamente, el cliente de Jersey no es compatible con el método PATCH si se usa con JDK <8
botchniaque
3
Unirest es muy fácil de usar, pero su diseño estático lo hace inutilizable en entornos compartidos y de servidor.
bekce
99
Con respecto al comentario más inquietante , me gustaría agregar que actualmente (a fines de 2016) parece que este proyecto ya no se mantiene. Incluso hay un problema abierto que solicita un nuevo responsable.
wegenmic
44
Para aquellos que les gusta Unirest , tengo una bifurcación que actualmente se mantiene / actualiza activamente.
Josh
3
sería bueno convertir la respuesta en una wiki comunitaria
tkruse
72

Como mencioné en este hilo , tiendo a usar Jersey que implementa JAX-RS y viene con un buen cliente REST. Lo bueno es que si implementa sus recursos RESTful utilizando JAX-RS, el cliente de Jersey puede reutilizar los proveedores de entidades como JAXB / XML / JSON / Atom, etc., para que pueda reutilizar los mismos objetos en el lado del servidor que usted utilizar en la prueba de unidad del lado del cliente.

Por ejemplo, aquí hay un caso de prueba de unidad del proyecto Apache Camel que busca cargas XML desde un recurso RESTful (utilizando los puntos finales del objeto JAXB). El método de recursos (uri) se define en esta clase base que solo usa la API del cliente de Jersey.

p.ej

    clientConfig = new DefaultClientConfig();
    client = Client.create(clientConfig);

    resource = client.resource("http://localhost:8080");
    // lets get the XML as a String
    String text = resource("foo").accept("application/xml").get(String.class);        

Por cierto, espero que la versión futura de JAX-RS agregue una buena API del lado del cliente en la línea de la de Jersey

James Strachan
fuente
¿Hay algún método en el que podamos mencionar la lista de servidores de servicio REST en ClientResource, en caso de que el servidor esté inactivo, intente con el siguiente servidor?
Njax3SmmM2x2a0Zf7Hpd
1
Solo una actualización, pero para abordar el comentario de James '' BTW '', la nueva versión de JAX-RS 2.0 tendrá una API del lado del cliente: infoq.com/presentations/Java-REST
Nick Klauer
65

Puede usar las API estándar de Java SE:

private void updateCustomer(Customer customer) { 
    try { 
        URL url = new URL("http://www.example.com/customers"); 
        HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
        connection.setDoOutput(true); 
        connection.setInstanceFollowRedirects(false); 
        connection.setRequestMethod("PUT"); 
        connection.setRequestProperty("Content-Type", "application/xml"); 

        OutputStream os = connection.getOutputStream(); 
        jaxbContext.createMarshaller().marshal(customer, os); 
        os.flush(); 

        connection.getResponseCode(); 
        connection.disconnect(); 
    } catch(Exception e) { 
        throw new RuntimeException(e); 
    } 
} 

O puede usar las API de cliente REST proporcionadas por implementaciones JAX-RS como Jersey. Estas API son más fáciles de usar, pero requieren frascos adicionales en su ruta de clase.

WebResource resource = client.resource("http://www.example.com/customers"); 
ClientResponse response = resource.type("application/xml");).put(ClientResponse.class, "<customer>...</customer."); 
System.out.println(response); 

Para más información, ver:

bdoughan
fuente
15
13 líneas para una simple llamada de descanso, en 2018 , parece demasiado ...
Clint Eastwood
1
Una vez que agrega el manejo de errores y las opciones, no es realmente significativamente diferente. Si el enfoque SE parece largo, siempre puede envolverlo en una clase ...:> Después de dos días de depuración de conflictos de la biblioteca JAX-RS, estoy realmente bien con 5 líneas adicionales de código para evitar toda la pesadilla SPI.
tekHedd
2
@ClintEastwood esta publicación se escribió en 2010
0ddlyoko
13

Si solo desea invocar un servicio REST y analizar la respuesta, puede probar Rest Assured

// Make a GET request to "/lotto"
String json = get("/lotto").asString()
// Parse the JSON response
List<String> winnderIds = with(json).get("lotto.winners.winnerId");

// Make a POST request to "/shopping"
String xml = post("/shopping").andReturn().body().asString()
// Parse the XML
Node category = with(xml).get("shopping.category[0]");
Johan
fuente
Encontré que esto es más elegante que muchas de las otras soluciones propuestas.
Herve Mutombo
9

También puede verificar Restlet, que tiene capacidades completas del lado del cliente, más REST orientado que las bibliotecas de nivel inferior como HttpURLConnection o Apache HTTP Client (que podemos aprovechar como conectores).

Saludos cordiales, Jerome Louvel

Jerome Louvel
fuente
2
A partir del 2019-10-24, el enlace proporcionado devuelve: 'La plataforma Restlet ha llegado al final de su vida útil'.
Hans Deragon
6

Podrías probar Rapa . Háganos saber sus comentarios sobre lo mismo. Y siéntase libre de registrar problemas o características esperadas.

Jaspe
fuente
1
Rapa tiene una interfaz realmente agradable y pocas dependencias. Una buena alternativa a RestSharp en el mundo .NET.
tarde
proyecto parece muerto
tkruse
6

Me gustaría señalar 2 opciones más:

Ophir Radnitz
fuente
1
Restfulie parece muerto
tkruse
5

Recientemente he intentado Retrofit Library desde el cuadrado, es genial y puedes llamar a tu API de descanso muy fácilmente. La configuración basada en anotaciones nos permite eliminar gran parte de la codificación de la placa de la caldera.

Yasitha Waduge
fuente
4

Yo uso Apache HTTPClient para manejar todo el lado HTTP de las cosas.

Escribo analizadores XML SAX para el contenido XML que analiza el XML en su modelo de objetos. Creo que Axis2 también expone XML -> Métodos de modelo (Axis 1 ocultó esta parte, molesto). Los generadores XML son trivialmente simples.

No lleva mucho tiempo codificar, y es bastante eficiente, en mi opinión.

JeeBee
fuente
44
En mi opinión, esta es la peor manera de hacer REST. Manejar manualmente la serialización en Java es una pérdida de tiempo cuando tienes tantas opciones como JAXB y Jackson. Incluso cargar todo el documento y usar XPath es marginalmente más lento que SAX y nada en comparación con la obtención de XML (velocidad de red).
Adam Gent
1
También estoy de acuerdo, y escribí el comentario original. En aquel entonces tenía el deseo de controlar la deserialización, pero hoy en día usaría Jackson y clases de modelos con anotaciones decentes.
JeeBee
4

OkHttp es ligero y potente cuando se combina con Retrofit también. Esto funciona bien para el uso general de Java, así como en Android.

OkHttp : http://square.github.io/okhttp/

public static final MediaType JSON
    = MediaType.parse("application/json; charset=utf-8");

OkHttpClient client = new OkHttpClient();

String post(String url, String json) throws IOException {
  RequestBody body = RequestBody.create(JSON, json);
  Request request = new Request.Builder()
      .url(url)
      .post(body)
      .build();
  Response response = client.newCall(request).execute();
  return response.body().string();
}

Modificación : http://square.github.io/retrofit/

public interface GitHubService {
  @GET("/users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}
Sam Edwards
fuente
2

Aunque es simple crear un cliente HTTP y realizar una solicitud. Pero si desea utilizar algunos clientes generados automáticamente, puede utilizar WADL para describir y generar código.

Puede usar RestDescribe para generar y compilar WSDL, puede generar clientes en php, ruby, python, java y C # usando esto. Genera código limpio y hay un buen cambio que debe modificar un poco después de la generación del código, puede encontrar buena documentación y pensamientos subyacentes detrás de la herramienta aquí .

Hay pocas herramientas WADL interesantes y útiles mencionadas en wintermute.

GG.
fuente
1

Escribí una biblioteca que asigna una interfaz de Java a un servicio JSON REST remoto:

https://github.com/ggeorgovassilis/spring-rest-invoker

public interface BookService {
   @RequestMapping("/volumes")
   QueryResult findBooksByTitle(@RequestParam("q") String q);

   @RequestMapping("/volumes/{id}")
   Item findBookById(@PathVariable("id") String id);
}
George Georgovassilis
fuente
0

Intenta mirar http-rest-client

https://github.com/g00dnatur3/http-rest-client

Aquí hay un ejemplo simple:

RestClient client = RestClient.builder().build();
String geocoderUrl = "http://maps.googleapis.com/maps/api/geocode/json"
Map<String, String> params = Maps.newHashMap();
params.put("address", "beverly hills 90210");
params.put("sensor", "false");
JsonNode node = client.get(geocoderUrl, params, JsonNode.class);

La biblioteca se encarga de la serialización y el enlace de json por usted.

Aquí hay otro ejemplo,

RestClient client = RestClient.builder().build();
String url = ...
Person person = ...
Header header = client.create(url, person);
if (header != null) System.out.println("Location header is:" + header.value());

Y un último ejemplo,

RestClient client = RestClient.builder().build();
String url = ...
Person person = client.get(url, null, Person.class); //no queryParams

¡Salud!

g00dnatur3
fuente
0

Ejemplos de Jersey Rest Client:
Agregar dependencia:

         <!-- jersey -->
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-json</artifactId>
        <version>1.8</version>
    </dependency>
   <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-server</artifactId>
        <version>1.8</version>
    </dependency>

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-client</artifactId>
    <version>1.8</version>
</dependency>

    <dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20090211</version>
</dependency>

ForGetMethod y pasando dos parámetros:

          Client client = Client.create();
           WebResource webResource1 = client
                        .resource("http://localhost:10102/NewsTickerServices/AddGroup/"
                                + userN + "/" + groupName);

                ClientResponse response1 = webResource1.get(ClientResponse.class);
                System.out.println("responser is" + response1);

GetMethod pasando un parámetro y Obteniendo un Respone de Lista:

       Client client = Client.create();

        WebResource webResource1 = client
                    .resource("http://localhost:10102/NewsTickerServices/GetAssignedUser/"+grpName);    
    //value changed
    String response1 = webResource1.type(MediaType.APPLICATION_JSON).get(String.class);

    List <String > Assignedlist =new ArrayList<String>();
     JSONArray jsonArr2 =new JSONArray(response1);
    for (int i =0;i<jsonArr2.length();i++){

        Assignedlist.add(jsonArr2.getString(i));    
    }

En Above It, devuelve una Lista que aceptamos como Lista y luego la convertimos en Json Array y luego Json Array en List.

Si la solicitud posterior pasa el objeto Json como parámetro:

   Client client = Client.create();
    WebResource webResource = client
            .resource("http://localhost:10102/NewsTickerServices/CreateJUser");
    // value added

    ClientResponse response = webResource.type(MediaType.APPLICATION_JSON).post(ClientResponse.class,mapper.writeValueAsString(user));

    if (response.getStatus() == 500) {

        context.addMessage(null, new FacesMessage("User already exist "));
    }
abhishek ringsia
fuente
0

Actualmente estoy usando https://github.com/kevinsawicki/http-request Me gusta su simplicidad y la forma en que se muestran los ejemplos, pero principalmente me vendieron cuando leí:

¿Cuáles son las dependencias?

Ninguna. El objetivo de esta biblioteca es ser una clase de clase única con algunas clases estáticas internas. El proyecto de prueba requiere Jetty para probar las solicitudes contra una implementación real del servidor HTTP.

que solucionó algunos problemas en un proyecto java 1.6. En cuanto a decodificar json en objetos, gson es simplemente invencible :)

Edoardo
fuente
1
proyecto parece muerto, sin compromisos desde 2015.
tkruse