Como você cria um cliente REST para Java? [fechadas]

247

Com o JSR 311 e suas implementações, temos um padrão poderoso para expor objetos Java via REST. No entanto, no lado do cliente, parece haver algo em falta comparável ao Apache Axis para SOAP - algo que oculta o serviço da Web e empacota os dados de forma transparente de volta aos objetos Java.

Como você cria clientes Java RESTful? Usando HTTPConnection e análise manual do resultado? Ou clientes especializados, por exemplo, Jersey ou Apache CXR?

Yaba
fonte
Acabei de encontrar o Apache Wink na Incubadora Apache. Pode ser um projeto interessante para criar servidores e clientes REST.
Yaba
2
verifique isso: igorpolevoy.blogspot.com/2011/01/java-rest-with-ease.html obrigado igor
ipolevoy
Confira [Resting] ( code.google.com/p/resting ). Ele promete chamar os serviços REST e criar uma lista de objetos a partir da resposta XML / JSON / YAML em uma etapa.
neel 21/07
O descanso tem problemas com solicitações POST.
RyanBrady
2
Você pode fazer isso de uma maneira muito simples com resteasy (by Jboss). Eu escrevi um post sobre como desenvolver um cliente Java REST, se você quiser um guia de introdução. De qualquer forma, existem centenas de alternativas em Java.
Guido

Respostas:

204

Esta é uma pergunta antiga (2008), portanto há muito mais opções do que antes:

ATUALIZAÇÕES (projetos ainda ativos em 2020):

  • Componentes Apache HTTP (4.2) Adaptador fluente - Substituição básica do JDK, usada por vários outros candidatos nesta lista. Melhor do que o antigo Cliente HTTP 3 do Commons e mais fácil de usar para criar seu próprio cliente REST. Você precisará usar algo como osuporte de análise Jackson para JSON e poderá usar os componentes HTTP URIBuilder para construir URIs de recursos semelhantes ao cliente Jersey / JAX-RS Rest. Os componentes HTTP também suportam NIO, mas duvido que você obtenha um desempenho melhor que o BIO, dada a curta solicitação de natureza do REST. O Apache HttpComponents 5 possui suporte a HTTP / 2.
  • OkHttp - Substituição básica do JDK, semelhante aos componentes http, usada por vários outros candidatos nesta lista. Suporta protocolos HTTP mais recentes (SPDY e HTTP2). Funciona no Android. Infelizmente, ele não oferece uma verdadeira opção assíncrona baseada em loop de reator (consulte os componentes Ning e HTTP acima). No entanto, se você usar o protocolo HTTP2 mais recente, isso será um problema menor (supondo que a contagem de conexões seja um problema).
  • Ning Async-http-client - fornece suporte a NIO. Anteriormente conhecido como Async-http-client pelo Sonatype .
  • Fingir wrapper para clientes http de nível inferior (okhttp, apache httpcomponents). Cria automaticamente clientes com base em stubs de interface semelhantes a algumas extensões de Jersey e CXF. Forte integração de molas.
  • Retrofit - wrapper para clientes http de nível inferior (okhttp). Cria automaticamente clientes com base em stubs de interface semelhantes a algumas extensões de Jersey e CXF.
  • Volley wrapper para jdk http cliente, por google
  • wrapper google-http para o cliente http jdk ou apache httpcomponents, pelo google
  • Wrapper Unirest para cliente http jdk, por kong
  • Wrapper JakartaEE Resteasy para cliente http jdk, por jboss, parte do framework jboss
  • wrapper jcabi-http para httpcomponents apache, parte da coleção jcabi
  • wrapper de restlet para httpcomponents do apache, parte da estrutura de restlet
  • invólucro com garantia de segurança para testes fáceis

Uma ressalva na escolha de clientes HTTP / REST. Certifique-se de verificar o que sua pilha de estrutura está usando para um cliente HTTP, como funciona a segmentação e, idealmente, use o mesmo cliente, se ele oferecer um. Ou seja, se você estiver usando algo como Vert.x ou Play, tente usar o cliente de apoio para participar de qualquer loop de barramento ou reator que a estrutura forneça ... caso contrário, esteja preparado para possíveis problemas de segmentação.

Adam Gent
fonte
1
Infelizmente cliente Jersey não suporta método PATCH se usado com JDK <8
botchniaque
3
O Unirest é muito fácil de usar, mas seu design estático o torna inutilizável em ambientes compartilhados e de servidor.
bekce 12/10
9
Com relação ao comentário mais unirest , gostaria de acrescentar que atualmente (final de 2016) parece que este projeto não é mais mantido. Existe até um problema em aberto que pede um novo mantenedor.
wegenmic
4
Para quem gosta de Unirest , tenho uma bifurcação que está sendo ativamente mantida / atualizada.
23418 Josh
3
seria bom transformar a resposta em um wiki da comunidade
tkruse
71

Como mencionei neste tópico , costumo usar Jersey, que implementa o JAX-RS e vem com um bom cliente REST. O bom é que, se você implementar seus recursos RESTful usando JAX-RS, o cliente Jersey poderá reutilizar os provedores de entidades como JAXB / XML / JSON / Atom e assim por diante - para poder reutilizar os mesmos objetos no lado do servidor. use no teste de unidade do lado do cliente.

Por exemplo aqui é um caso de teste de unidade do projeto Apache Camel que olha para cima payloads XML a partir de um recurso RESTful (usando os Endpoints JAXB objeto). O método resource (uri) é definido nesta classe base, que apenas usa a API do cliente Jersey.

por exemplo

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

BTW Espero que a versão futura do JAX-RS adicione uma API agradável do lado do cliente ao longo da linha de Jersey

James Strachan
fonte
Existe um método em que podemos mencionar a lista de servidores de serviço REST no ClientResource, caso o servidor esteja inativo, tente o próximo servidor?
Njax3SmmM2x2a0Zf7Hpd
1
Apenas uma atualização, mas para o endereço James' 'BTW' comentário, a nova versão do JAX-RS 2.0 terá uma API do lado do cliente: infoq.com/presentations/Java-REST
Nick Klauer
64

Você pode usar as APIs Java SE padrão:

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

Ou você pode usar as APIs do cliente REST fornecidas pelas implementações do JAX-RS, como Jersey. Essas APIs são mais fáceis de usar, mas requerem jars adicionais no caminho da sua classe.

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 mais informações, veja:

bdoughan
fonte
15
13 linhas para uma chamada simples descanso, em 2018 , soa como demasiado ...
Clint Eastwood
1
Depois de adicionar o tratamento de erros e as opções, não é realmente muito diferente. Se a abordagem SE parecer longa, você sempre poderá agrupá-la em uma classe ...:> Após dois dias de depuração de conflitos na biblioteca JAX-RS, estou muito bem com 5 linhas de código extras para evitar todo o pesadelo do SPI.
tekHedd
2
@ClintEastwood este post foi escrito em 2010
0ddlyoko
12

Se você deseja apenas chamar um serviço REST e analisar a resposta, pode experimentar o 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
fonte
9

Você também pode verificar o Restlet, que possui recursos completos do lado do cliente, mais orientado para REST que as bibliotecas de nível inferior, como HttpURLConnection ou Apache HTTP Client (que podemos utilizar como conectores).

Atenciosamente, Jerome Louvel

Jerome Louvel
fonte
2
A partir de 24/10/2019, o link fornecido retorna: 'A plataforma Restlet chegou ao fim da vida útil'.
Hans Deragon 24/10/19
6

Você poderia tentar Rapa . Deixe-nos saber o seu feedback sobre o mesmo. E fique à vontade para registrar problemas ou recursos esperados.

Jaspe
fonte
1
O Rapa tem uma interface muito boa e poucas dependências. Uma boa alternativa ao RestSharp no mundo .NET.
Segunda
projeto parece morto
tkruse 5/03
6

Eu gostaria de destacar mais duas opções:

Ophir Radnitz
fonte
1
Restfulie parece morto
tkruse 5/03
5

Tente JdkRequestem jcabi-http (eu sou desenvolvedor). É assim que funciona:

String body = new JdkRequest("http://www.google.com")
  .header("User-Agent", "it's me")
  .fetch()
  .body()

Verifique esta publicação no blog para obter mais detalhes: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html

yegor256
fonte
5

Eu tentei recentemente Retrofit Library da square, é ótimo e você pode chamar sua API de descanso com muita facilidade. A configuração baseada em anotação nos permite eliminar grande parte da codificação da placa da caldeira.

Yasitha Waduge
fonte
4

Eu uso o Apache HTTPClient para lidar com todo o lado HTTP das coisas.

Escrevo analisadores XML SAX para o conteúdo XML que analisa o XML em seu modelo de objeto. Acredito que o Axis2 também expõe métodos XML -> Model (o Axis 1 ocultou essa parte, irritantemente). Geradores XML são trivialmente simples.

Não demora muito para codificar e é bastante eficiente, na minha opinião.

JeeBee
fonte
4
Na minha opinião, esta é a pior maneira de fazer o REST. Manipular manualmente a serialização em Java é um desperdício de tempo quando você tem tantas opções como JAXB e Jackson. Mesmo carregar o documento inteiro e usar o XPath é um pouco mais lento que o SAX e nada comparado à obtenção do XML (velocidade da rede).
Adam Gent
1
Também concordo e escrevi o comentário original. Naquela época, eu tinha o desejo de controlar a desserialização, mas hoje em dia eu usava Jackson e decentemente anotava classes de modelo.
JeeBee
4

O OkHttp é leve e poderoso quando combinado com o Retrofit também. Isso funciona bem para uso geral em Java e no 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();
}

Retrofit : http://square.github.io/retrofit/

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

Como ninguém mencionou, aqui está outro: Feign , que é usado pelo Spring Cloud .

Leon
fonte
2

Embora seja simples criar um cliente HTTP e fazer um novo pedido. Mas se você quiser usar alguns clientes gerados automaticamente, poderá usar o WADL para descrever e gerar código.

Você pode usar o RestDescribe para gerar e compilar o WSDL, você pode gerar clientes em php, ruby, python, java e C # usando isso. Ele gera código limpo e há uma boa alteração que você precisa ajustá-lo um pouco após a geração do código, você pode encontrar boa documentação e pensamentos subjacentes por trás da ferramenta aqui .

Existem poucas ferramentas interessantes e úteis de WADL mencionadas no wintermute.

GG.
fonte
1

Eu escrevi uma biblioteca que mapeia uma interface java para um serviço 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
fonte
0

Tente olhar para http-rest-client

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

Aqui está um exemplo simples:

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

A biblioteca cuida da serialização e ligação do json para você.

Aqui está outro exemplo,

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

E um último exemplo,

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

Felicidades!

g00dnatur3
fonte
0

Exemplos de jersey Rest client:
Adicionando dependência:

         <!-- 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 e passando dois 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 passando um parâmetro e Obtendo uma resposta 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));    
    }

Em Acima, ele retorna uma lista que estamos aceitando como uma lista e depois a convertemos em Json Array e, em seguida, Json Array em List.

Se o pedido posterior passar o 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 "));
    }
anéis de abhishek
fonte
0

Atualmente, estou usando https://github.com/kevinsawicki/http-request Eu gosto da simplicidade e da maneira como os exemplos são mostrados, mas principalmente eu fui vendido quando li:

Quais são as dependências?

Nenhum. O objetivo desta biblioteca é ser uma classe de classe única com algumas classes estáticas internas. O projeto de teste requer o Jetty para testar solicitações em relação à implementação real do servidor HTTP.

que resolveu alguns problemas em um projeto java 1.6. Quanto à decodificação de json em objetos, o gson é invencível :)

Edoardo
fonte
1
projeto parece morto, não é confirmado desde 2015.
tkruse 5/03