Jak utworzyć klienta REST dla Java? [Zamknięte]

248

Z JSR 311 i jego implementacjami mamy potężny standard do eksponowania obiektów Java przez REST. Jednak po stronie klienta wydaje się, że brakuje czegoś, co jest porównywalne z Apache Axis dla SOAP - coś, co ukrywa usługę internetową i przekazuje dane w przejrzysty sposób do obiektów Java.

Jak tworzysz klientów Java RESTful? Używasz połączenia HTTP i ręcznego analizowania wyniku? Lub wyspecjalizowani klienci np. Dla Jersey lub Apache CXR?

Yaba
źródło
Właśnie znalazłem Apache Wink w inkubatorze Apache. Może to być ciekawy projekt do tworzenia serwerów i klientów REST.
Yaba
Sprawdź [Odpoczynek] ( code.google.com/p/resting ). Obiecuje wywołać usługi REST i utworzyć listę obiektów z odpowiedzi XML / JSON / YAML w jednym kroku.
neel
Odpoczynek ma problemy z żądaniami POST.
RyanBrady
2
Możesz to zrobić w bardzo prosty sposób dzięki resteasy (autor: Jboss). Napisałem wpis na blogu o tym, jak opracować klienta Java REST, jeśli potrzebujesz przewodnika dla początkujących. W każdym razie istnieją setki alternatyw w Javie.
Guido

Odpowiedzi:

205

To stare pytanie (2008), więc jest teraz o wiele więcej opcji niż wtedy:

AKTUALIZACJE (projekty nadal aktywne w 2020 r.):

  • Apache HTTP Components (4.2) Płynny adapter - Podstawowy zamiennik JDK, używany przez kilku innych kandydatów na tej liście. Lepszy niż stary klient HTTP Commons 3 i łatwiejszy w użyciu do budowania własnego klienta REST. Będziesz musiał użyć czegoś takiego jak Jackson do obsługi parsowania JSON i możesz użyć komponentów HTTP URIBuilder do budowy identyfikatorów URI zasobów podobnych do klienta Jersey / JAX-RS Rest. Komponenty HTTP obsługują również NIO, ale wątpię, aby uzyskać lepszą wydajność niż BIO, biorąc pod uwagę krótki typ żądania REST. Apache HttpComponents 5 obsługuje HTTP / 2.
  • OkHttp - Podstawowy zamiennik JDK, podobny do komponentów http, używany przez kilku innych kandydatów na tej liście. Obsługuje nowsze protokoły HTTP (SPDY i HTTP2). Działa na Androidzie. Niestety nie oferuje prawdziwej opcji asynchronicznej opartej na pętli reaktora (patrz komponenty Ning i HTTP powyżej). Jeśli jednak używasz nowszego protokołu HTTP2, jest to mniejszy problem (zakładając, że liczba połączeń jest problemem).
  • Ning Async-http-client - zapewnia obsługę NIO. Wcześniej znany jako Async-http-client przez Sonatype .
  • Feign otoki dla klientów HTTP niższego poziomu (okhttp, apache httpcomponents). Automatycznie tworzy klientów na podstawie kodów pośredniczących interfejsu podobnych do niektórych rozszerzeń Jersey i CXF. Silna integracja wiosenna.
  • Modernizacja - opakowanie dla klientów HTTP niższego poziomu (okhttp). Automatycznie tworzy klientów na podstawie kodów pośredniczących interfejsu podobnych do niektórych rozszerzeń Jersey i CXF.
  • Opakowanie siatkówki dla klienta jdk http, Google
  • opakowanie google-http dla klienta jdk http lub komponenty http apache firmy google
  • Unirest wrapper dla klienta jdk http, według kong
  • Resteasy JakartaEE otoki dla klienta jdk http, przez jboss, część frameworka jboss
  • opakowanie jcabi-http dla apache httpcomponents, część kolekcji jcabi
  • restlet owijka Apache httpcomponents część restlet ramach
  • spokojne opakowanie z zapewnieniami dla łatwego testowania

Zastrzeżenie dotyczące wybierania klientów HTTP / REST. Upewnij się, że używasz stosu frameworka dla klienta HTTP, w jaki sposób wykonuje on wątki, a najlepiej, jeśli używa tego samego klienta. To znaczy, jeśli używasz czegoś takiego jak Vert.x lub Play, możesz spróbować użyć klienta wspierającego, aby wziąć udział w dowolnej pętli magistrali lub reaktora, jaką zapewnia struktura ... w przeciwnym razie przygotuj się na potencjalnie interesujące problemy z wątkami.

Adam Gent
źródło
1
Niestety klient Jersey nie obsługuje metody PATCH, jeśli jest używany z JDK <8
botchniaque
3
Unirest jest bardzo łatwy w użyciu, ale jego statyczna konstrukcja sprawia, że ​​nie nadaje się do użytku w środowiskach współdzielonych i serwerowych.
bekce
9
Jeśli chodzi o komentarz do unirestu , chciałbym dodać, że obecnie (koniec 2016 r.) Wygląda na to, że ten projekt nie jest już obsługiwany. Jest nawet otwarty problem, który wymaga nowego opiekuna.
wegenmic,
4
Dla tych, którzy lubią Unirest , mam rozwidlenie , które jest obecnie aktywnie utrzymywane / aktualizowane.
Josh
3
byłoby miło przekształcić odpowiedź w wiki społeczności
tkruse
72

Jak wspomniałem w tym wątku , zwykle używam Jersey, który implementuje JAX-RS i ma fajnego klienta REST. Zaletą jest to, że jeśli zaimplementujesz zasoby RESTful za pomocą JAX-RS, to klient Jersey może ponownie użyć dostawców encji, takich jak JAXB / XML / JSON / Atom i tak dalej - abyś mógł ponownie używać tych samych obiektów po stronie serwera, jak ty używać w teście jednostkowym po stronie klienta.

Na przykład tutaj jest przypadek testowy jednostki z projektu Apache Camel, który wyszukuje ładunki XML z zasobu RESTful (przy użyciu punktów końcowych obiektu JAXB). Metoda zasobów (uri) jest zdefiniowana w tej klasie bazowej, która korzysta tylko z interfejsu API klienta Jersey.

na przykład

    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 Mam nadzieję, że przyszła wersja JAX-RS doda fajne API po stronie klienta, podobnie jak w Jersey

James Strachan
źródło
Czy istnieje metoda, w której możemy wspomnieć o liście serwerów usług REST w ClientResource, na wypadek, gdyby serwer nie działał, wypróbuj następny serwer?
Njax3SmmM2x2a0Zf7Hpd
1
Tylko aktualizacja, ale aby odpowiedzieć na komentarz Jamesa „BTW”, nowa wersja JAX-RS 2.0 będzie miała interfejs API po stronie klienta: infoq.com/presentations/Java-REST
Nick Klauer
65

Możesz użyć standardowych interfejsów API 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); 
    } 
} 

Lub możesz użyć interfejsów API klienta REST dostarczonych przez implementacje JAX-RS, takie jak Jersey. Te interfejsy API są łatwiejsze w użyciu, ale wymagają dodatkowych słoików na ścieżce klasy.

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

Aby uzyskać więcej informacji zobacz:

bdoughan
źródło
15
13 linii na zwykły odpoczynek, w 2018 roku , brzmi jak zdecydowanie za dużo ...
Clint Eastwood
1
Po dodaniu obsługi błędów i opcji nie różni się to tak naprawdę znacząco. Jeśli podejście SE wydaje się długie, zawsze możesz zawinąć je w klasę ...:> Po dwóch dniach debugowania konfliktów bibliotek JAX-RS jestem w porządku z 5 dodatkowymi liniami kodu, aby uniknąć całego koszmaru SPI.
tekHedd
2
@ClintEastwood ten post został napisany w 2010 roku
0ddlyoko
13

Jeśli chcesz tylko wywołać usługę REST i przeanalizować odpowiedź, możesz wypróbować opcję Gwarancja bezpieczeństwa

// 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
źródło
Uważam, że jest to bardziej eleganckie niż wiele innych proponowanych rozwiązań.
Herve Mutombo
9

Możesz także sprawdzić Restlet, który ma pełne możliwości po stronie klienta, bardziej zorientowany na REST niż biblioteki niższego poziomu, takie jak HttpURLConnection lub klient Apache HTTP (który możemy wykorzystać jako łączniki).

Z pozdrowieniami, Jerome Louvel

Jerome Louvel
źródło
2
Na dzień 24.10.2019 podany link zwraca: „Platforma Restlet osiągnęła kres eksploatacji”.
Hans Deragon
6

Możesz spróbować Rapa . Daj nam znać swoją opinię na ten sam temat. Zachęcamy do rejestrowania problemów lub oczekiwanych funkcji.

Jaspis
źródło
1
Rapa ma naprawdę fajny interfejs i kilka zależności. Dobra alternatywa dla RestSharp w świecie .NET.
po południu
projekt wygląda na martwy
tkruse
6

Chciałbym wskazać jeszcze 2 opcje:

Ophir Radnitz
źródło
1
Restfulie wygląda na martwego
tkruse
5

Niedawno wypróbowałem Retrofit Library z kwadratu, jest świetny i możesz bardzo łatwo wywołać resztę API. Konfiguracja oparta na adnotacjach pozwala nam pozbyć się dużo kodowania płyt kotłowych.

Yasitha Waduge
źródło
4

Korzystam z Apache HTTPClient do obsługi wszystkich aspektów HTTP.

Piszę parsery XML SAX dla treści XML, która analizuje XML w twoim modelu obiektowym. Uważam, że Axis2 również ujawnia XML -> Metody modelowe (Oś 1 ukrywała tę część, irytujące). Generatory XML są banalnie proste.

Kodowanie nie zajmuje dużo czasu i moim zdaniem jest dość wydajne.

JeeBee
źródło
4
Moim zdaniem jest to najgorszy sposób na REST. Ręczna obsługa serializacji w Javie to strata czasu, gdy masz tak wiele opcji, jak JAXB i Jackson. Nawet załadowanie całego dokumentu i użycie XPath jest nieznacznie wolniejsze niż SAX i nic w porównaniu z uzyskaniem XML (prędkość sieci).
Adam Gent
1
Ja też się zgadzam i napisałem oryginalny komentarz. W tamtym czasie miałem ochotę kontrolować deserizację, ale w dzisiejszych czasach używałbym Jacksona i przyzwoicie adnotowanych klas modeli.
JeeBee
4

OkHttp jest lekki i wydajny w połączeniu z Retrofit. Działa to dobrze do ogólnego użytku Java, jak również na Androidzie.

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

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

public interface GitHubService {
  @GET("/users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}
Sam Edwards
źródło
3

Ponieważ nikt nie wspomniał, oto inny: Feign , z którego korzysta Spring Cloud .

Leon
źródło
2

Chociaż łatwo jest utworzyć klienta HTTP i dokonać ponownego żądania. Ale jeśli chcesz skorzystać z niektórych automatycznie generowanych klientów, możesz użyć WADL do opisania i wygenerowania kodu.

Możesz użyć RestDescribe do generowania i kompilacji WSDL, możesz generować klientów w php, ruby, python, java i C # za pomocą tego. To generuje czysty kod i istnieje duża zmiana, że trzeba go podkręcić trochę po wygenerowaniu kodu, można znaleźć dobrą dokumentację oraz leżące u podstaw myśli tył narzędzia tutaj .

Na Wintermute wspomniano kilka interesujących i przydatnych narzędzi WADL .

GG
źródło
1

Napisałem bibliotekę, która mapuje interfejs Java do zdalnej usługi JSON REST:

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
źródło
0

Spróbuj spojrzeć na http-rest-client

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

Oto prosty przykład:

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

Biblioteka zajmuje się serializacją i wiązaniem jsonów.

Oto inny przykład

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

I ostatni przykład

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

Twoje zdrowie!

g00dnatur3
źródło
0

Przykłady koszulki Reszta klienta Jersey:
Dodawanie zależności:

         <!-- 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 i przekazanie dwóch parametrów:

          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 przekazuje jeden parametr i uzyskuje odpowiedź na listę:

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

W Above It zwraca listę, którą akceptujemy jako listę, a następnie konwertuje ją na tablicę Json, a następnie tablicę Json na listę.

Jeśli żądanie wysłania przekazuje obiekt Json jako parametr:

   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 "));
    }
pierścienie abhishek
źródło
0

Obecnie używam https://github.com/kevinsawicki/http-request Podoba mi się ich prostota i sposób wyświetlania przykładów, ale przede wszystkim zostałem sprzedany, gdy przeczytałem:

Jakie są zależności?

Żaden. Celem tej biblioteki jest bycie pojedynczą klasą z pewnymi wewnętrznymi klasami statycznymi. Projekt testowy wymaga Jetty do testowania żądań względem rzeczywistej implementacji serwera HTTP.

co rozwiązało niektóre problemy w projekcie Java 1.6. Jeśli chodzi o dekodowanie jsona na obiekty gson jest po prostu niezwyciężony :)

Edoardo
źródło
1
projekt wygląda na martwy, brak zobowiązań od 2015 r.
tkruse