Cuộc gọi RESTful trong Java


150

Tôi sẽ thực hiện một cuộc gọi RESTful trong Java. Tuy nhiên, tôi không biết làm thế nào để thực hiện cuộc gọi. Tôi có cần sử dụng URLConnection hoặc những người khác không? Ai giúp tôi với. cảm ơn bạn.


Nó phụ thuộc vào cách bạn thực hiện các cuộc gọi nghỉ ngơi trong ứng dụng của bạn. Bạn có sử dụng triển khai JaxRS không? Một cái cụ thể? Bạn đang làm yêu cầu bằng tay?
Colin Hebert

@Colin Hebert, cảm ơn bạn đã trả lời. Nhưng tôi không có ý tưởng nào về cuộc gọi RESTful. bạn có thể cho tôi thêm thông tin về các phần khác nhau của cuộc gọi RESTful không.
Câu hỏi

thanh toán http khách hàng yên tĩnh bấm vào đây
Gaurav J

Câu trả lời:


91

Nếu bạn đang gọi một dịch vụ RESTful từ Nhà cung cấp dịch vụ (ví dụ: Facebook, Twitter), bạn có thể thực hiện điều đó với bất kỳ hương vị nào bạn chọn:

Nếu bạn không muốn sử dụng các thư viện bên ngoài, bạn có thể sử dụng java.net.HttpURLConnectionhoặc javax.net.ssl.HttpsURLConnection(cho SSL), nhưng đó là cuộc gọi được gói gọn trong mẫu kiểu Nhà máy trong java.net.URLConnection. Để nhận được kết quả, bạn sẽ phải connection.getInputStream()trả lại cho bạn mộtInputStream . Sau đó, bạn sẽ phải chuyển đổi luồng đầu vào của mình thành chuỗi và phân tích chuỗi thành đối tượng đại diện của nó (ví dụ: XML, JSON, v.v.).

Ngoài ra, Apache httpClient (phiên bản 4 là phiên bản mới nhất). Nó ổn định và mạnh mẽ hơn so với mặc định của java URLConnectionvà nó hỗ trợ hầu hết (nếu không phải tất cả) giao thức HTTP (cũng như có thể được đặt thành chế độ Nghiêm). Phản hồi của bạn sẽ vẫn còn InputStreamvà bạn có thể sử dụng nó như đã đề cập ở trên.


Tài liệu về HttpClient: http://hc.apache.org/httpcomponents-client-ga/tutorial/html/index.html


5
Đừng phát minh lại bánh xe, hãy sử dụng một trong các triển khai RESTful hiện có.
Qwerky

13
Đó không phải là phát minh lại bánh xe, tôi đang nói bạn có thể sử dụng bất cứ thứ gì flavourbạn muốn. Một số muốn mặc định URLConnection, một số muốn HttpClient. Dù bằng cách nào, nó ở đó để bạn sử dụng.
Buhake Sindi

@ Quý ông ưu tú, cảm ơn bạn đã trả lời. Sau khi kiểm tra tất cả các thư viện, tôi muốn sử dụng ApacheClClient, bạn có phiền để cho tôi tham khảo thêm về cái này không?
Câu hỏi

@Questions, liên kết đến các ví dụ về HTTPClient 4 dường như đã bị hỏng, vì vậy nếu bạn có bất kỳ câu hỏi nào (ý định chơi chữ ... lol), hãy cho tôi biết .... Tôi giải quyết nó gần như hàng ngày.
Buhake Sindi

Vui lòng hiển thị mã ví dụ về cách sử dụng các lớp này, thay vì chỉ lưu ý đến sự tồn tại của chúng
Jonathan

150

Cập nhật: Đã gần 5 năm kể từ khi tôi viết câu trả lời dưới đây; hôm nay tôi có một quan điểm khác.

99% khi mọi người sử dụng thuật ngữ REST, họ thực sự có nghĩa là HTTP; họ có thể chăm sóc ít hơn về “tài nguyên”, “đại diện”, “chuyển nhà”, “thống nhất giao diện”, “hypermedia”, hoặc bất kỳ khác hạn chế hoặc các khía cạnh của REST phong cách kiến trúc xác định bởi Fielding . Do đó, các tóm tắt được cung cấp bởi các khung REST khác nhau rất khó hiểu và không có ích.

Vì vậy: bạn muốn gửi các yêu cầu HTTP bằng Java vào năm 2015. Bạn muốn một API rõ ràng, biểu cảm, trực quan, thành ngữ, đơn giản. Dùng gì? Tôi không còn sử dụng Java nữa, nhưng trong vài năm qua, thư viện máy khách Java HTTP có vẻ hứa hẹn và thú vị nhất là OkHttp . Kiểm tra nó ra.


Bạn chắc chắn có thể tương tác với các dịch vụ web RESTful bằng cách sử dụng URLConnectionhoặc HTTPClient để mã hóa các yêu cầu HTTP.

Tuy nhiên, nói chung, mong muốn sử dụng một thư viện hoặc khung cung cấp API đơn giản hơn và ngữ nghĩa hơn được thiết kế riêng cho mục đích này. Điều này làm cho mã dễ viết, đọc và gỡ lỗi hơn và giảm sự trùng lặp nỗ lực. Các khung này thường triển khai một số tính năng tuyệt vời không nhất thiết phải có hoặc dễ sử dụng trong các thư viện cấp thấp hơn, chẳng hạn như đàm phán nội dung, lưu trữ và xác thực.

Một số tùy chọn trưởng thành nhất là Jersey , REST EASRestlet .

Tôi quen thuộc nhất với Restlet và Jersey, hãy xem cách chúng tôi tạo ra POST yêu cầu với cả hai API.

Ví dụ Jersey

Form form = new Form();
form.add("x", "foo");
form.add("y", "bar");

Client client = ClientBuilder.newClient();

WebTarget resource = client.target("http://localhost:8080/someresource");

Builder request = resource.request();
request.accept(MediaType.APPLICATION_JSON);

Response response = request.get();

if (response.getStatusInfo().getFamily() == Family.SUCCESSFUL) {
    System.out.println("Success! " + response.getStatus());
    System.out.println(response.getEntity());
} else {
    System.out.println("ERROR! " + response.getStatus());    
    System.out.println(response.getEntity());
}

Ví dụ phục hồi

Form form = new Form();
form.add("x", "foo");
form.add("y", "bar");

ClientResource resource = new ClientResource("http://localhost:8080/someresource");

Response response = resource.post(form.getWebRepresentation());

if (response.getStatus().isSuccess()) {
    System.out.println("Success! " + response.getStatus());
    System.out.println(response.getEntity().getText());
} else {
    System.out.println("ERROR! " + response.getStatus());
    System.out.println(response.getEntity().getText());
}

Tất nhiên, các yêu cầu GET thậm chí còn đơn giản hơn và bạn cũng có thể chỉ định những thứ như thẻ thực thể và Accepttiêu đề, nhưng hy vọng những ví dụ này hữu ích không tầm thường nhưng không quá phức tạp.

Như bạn có thể thấy, Restlet và Jersey có API khách hàng tương tự. Tôi tin rằng chúng được phát triển cùng một lúc, và do đó ảnh hưởng lẫn nhau.

Tôi thấy API Restlet có ngữ nghĩa hơn một chút, và do đó rõ ràng hơn một chút, nhưng YMMV.

Như tôi đã nói, tôi quen thuộc nhất với Restlet, tôi đã sử dụng nó trong nhiều ứng dụng trong nhiều năm và tôi rất hài lòng với nó. Đó là một khung rất trưởng thành, mạnh mẽ, đơn giản, hiệu quả, tích cực và được hỗ trợ tốt. Tôi không thể nói chuyện với Jersey hoặc REST EAS, nhưng ấn tượng của tôi là cả hai cũng là những lựa chọn vững chắc.


2
Nhưng vẫn là một bài viết tuyệt vời. Và tôi phải đồng ý với "99% thời gian khi mọi người sử dụng thuật ngữ REST, họ thực sự có nghĩa là HTTP; ... Các tóm tắt được cung cấp bởi các khung REST khác nhau rất khó hiểu và không có ích."
AlexD

2
Trong ví dụ Jersey của bạn, đối tượng Form được sử dụng ở đâu / như thế nào? Nó được tạo ra, nhưng nó không xuất hiện để thêm bất cứ điều gì vào ví dụ.
bắn tung tóe

29

Điều này rất phức tạp trong java, đó là lý do tại sao tôi khuyên bạn nên sử dụng tính RestTemplatetrừu tượng của Spring :

String result = 
restTemplate.getForObject(
    "http://example.com/hotels/{hotel}/bookings/{booking}",
    String.class,"42", "21"
);

Tài liệu tham khảo:


24

Nếu bạn chỉ cần thực hiện một cuộc gọi đơn giản đến dịch vụ REST từ java, bạn sử dụng một cái gì đó dọc theo các dòng này

/*
 * Stolen from http://xml.nig.ac.jp/tutorial/rest/index.html
 * and http://www.dr-chuck.com/csev-blog/2007/09/calling-rest-web-services-from-java/
*/
import java.io.*;
import java.net.*;

public class Rest {

    public static void main(String[] args) throws IOException {
        URL url = new URL(INSERT_HERE_YOUR_URL);
        String query = INSERT_HERE_YOUR_URL_PARAMETERS;

        //make connection
        URLConnection urlc = url.openConnection();

        //use post mode
        urlc.setDoOutput(true);
        urlc.setAllowUserInteraction(false);

        //send query
        PrintStream ps = new PrintStream(urlc.getOutputStream());
        ps.print(query);
        ps.close();

        //get result
        BufferedReader br = new BufferedReader(new InputStreamReader(urlc
            .getInputStream()));
        String l = null;
        while ((l=br.readLine())!=null) {
            System.out.println(l);
        }
        br.close();
    }
}

1
Có một số API REST thực sự tốt xung quanh, tôi khuyên bạn nên sử dụng một API thay vì phát minh lại bánh xe.
Qwerky

như tôi đã nói: phức tạp như địa ngục. (không, tôi đã không đánh giá thấp điều này, đó là một giải pháp hoàn toàn hợp lệ)
Sean Patrick Floyd

4
Các thư viện API phía máy khách @Qwerky thường vi phạm các ràng buộc REST. Họ giới thiệu quá nhiều khớp nối. Sử dụng một thư viện HTTP tốt là một lựa chọn tốt hơn trong dài hạn.
Darrel Miller

10

Có một số API RESTful xung quanh. Tôi muốn giới thiệu Jersey;

https://jersey.java.net/

Tài liệu API của khách hàng ở đây;

https://jersey.java.net/documentation/latest/index.html

Cập nhật
Vị trí cho các tài liệu OAuth trong nhận xét bên dưới là một liên kết chết và đã được chuyển đến https://jersey.java.net/nonav/documentation/latest/security.html#d0e12334


6
OP không tạo ra ứng dụng RESTful, anh ta thực hiện các cuộc gọi RESTful, tức là gọi tài nguyên phương thức API Twitter.
Buhake Sindi

@Qwerky - Tôi nghĩ sẽ hữu ích khi đưa lý do tại sao bạn đề xuất Jersey vào câu trả lời của bạn.
Daniel Bullis

7

Tôi muốn chia sẻ trải nghiệm cá nhân của mình, gọi một WS WS với cuộc gọi JSON Post:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLConnection;

public class HWS {

    public static void main(String[] args) throws IOException {
        URL url = new URL("INSERT YOUR SERVER REQUEST");
        //Insert your JSON query request
        String query = "{'PARAM1': 'VALUE','PARAM2': 'VALUE','PARAM3': 'VALUE','PARAM4': 'VALUE'}";
        //It change the apostrophe char to double colon char, to form a correct JSON string
        query=query.replace("'", "\"");

        try{
            //make connection
            URLConnection urlc = url.openConnection();
            //It Content Type is so importan to support JSON call
            urlc.setRequestProperty("Content-Type", "application/xml");
            Msj("Conectando: " + url.toString());
            //use post mode
            urlc.setDoOutput(true);
            urlc.setAllowUserInteraction(false);

            //send query
            PrintStream ps = new PrintStream(urlc.getOutputStream());
            ps.print(query);
            Msj("Consulta: " + query);
            ps.close();

            //get result
            BufferedReader br = new BufferedReader(new InputStreamReader(urlc.getInputStream()));
            String l = null;
            while ((l=br.readLine())!=null) {
                Msj(l);
            }
            br.close();
        } catch (Exception e){
            Msj("Error ocurrido");
            Msj(e.toString());
        }
    }

    private static void Msj(String texto){
        System.out.println(texto);
    }
}

5

Bạn có thể kiểm tra CXF . Bạn có thể truy cập Điều JAX-RS tại đây

Gọi đơn giản như thế này (trích dẫn):

BookStore store = JAXRSClientFactory.create("http://bookstore.com", BookStore.class);
// (1) remote GET call to http://bookstore.com/bookstore
Books books = store.getAllBooks();
// (2) no remote call
BookResource subresource = store.getBookSubresource(1);
// {3} remote GET call to http://bookstore.com/bookstore/1
Book b = subresource.getDescription();

5

Thật vậy, đây là "rất phức tạp trong Java":

Từ: https://jersey.java.net/documentation/latest/client.html

Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://foo").path("bar");
Invocation.Builder invocationBuilder = target.request(MediaType.TEXT_PLAIN_TYPE);
Response response = invocationBuilder.get();

4

Giải pháp dễ dàng nhất sẽ được sử dụng thư viện máy khách Apache http. tham khảo mã mẫu sau .. mã này sử dụng bảo mật cơ bản để xác thực.

Thêm phụ thuộc sau.

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.4</version>
</dependency>
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
Credentials credentials = new UsernamePasswordCredentials("username", "password");
credentialsProvider.setCredentials(AuthScope.ANY, credentials);
HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(credentialsProvider).build();
HttpPost request = new HttpPost("https://api.plivo.com/v1/Account/MAYNJ3OT/Message/");HttpResponse response = client.execute(request);
    // Get the response
    BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
    String line = "";
    while ((line = rd.readLine()) != null) {    
    textView = textView + line;
    }
    System.out.println(textView);


-1

Bạn có thể sử dụng Async http Client (Thư viện cũng hỗ trợ Giao thức WebSocket ) như thế:

    String clientChannel = UriBuilder.fromPath("http://localhost:8080/api/{id}").build(id).toString();

    try (AsyncHttpClient asyncHttpClient = new AsyncHttpClient())
    {
        BoundRequestBuilder postRequest = asyncHttpClient.preparePost(clientChannel);
        postRequest.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
        postRequest.setBody(message.toString()); // returns JSON
        postRequest.execute().get();
    }

nó không hoạt động (không thể kích hoạt ASyncHttpClient).
Java chính
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.