โทรสงบใน Java


150

ฉันจะโทรหาสงบใน Java อย่างไรก็ตามฉันไม่รู้วิธีโทรออก ฉันต้องใช้การเชื่อมต่อ URL หรืออื่น ๆ หรือไม่? ทุกคนสามารถช่วยฉันได้ ขอบคุณ.


ขึ้นอยู่กับว่าคุณพักสายในใบสมัครของคุณอย่างไร คุณใช้งาน JaxRS หรือไม่? หนึ่งโดยเฉพาะอย่างยิ่ง? คุณกำลังทำคำขอด้วยตนเองหรือไม่?
Colin Hebert

@ Colin Hebert ขอบคุณสำหรับการตอบกลับของคุณ แต่ฉันไม่มีความคิดในการโทรสงบ คุณสามารถให้ข้อมูลเพิ่มเติมเกี่ยวกับส่วนต่าง ๆ ของการโทรแบบสงบได้ไหม
คำถาม

ชำระเงินลูกค้า http พักผ่อนคลิกที่นี่
Gaurav J

คำตอบ:


91

หากคุณกำลังโทรหาบริการ RESTful จากผู้ให้บริการ (เช่น Facebook, Twitter) คุณสามารถทำได้ด้วยรสชาติที่คุณต้องการ:

หากคุณไม่ต้องการที่จะใช้ห้องสมุดภายนอกคุณสามารถใช้java.net.HttpURLConnectionหรือjavax.net.ssl.HttpsURLConnection(สำหรับ SSL) java.net.URLConnectionแต่ที่เป็นสายห่อหุ้มในรูปแบบประเภทโรงงาน หากต้องการรับผลลัพธ์คุณจะต้องconnection.getInputStream()ส่งคืนInputStreamและ จากนั้นคุณจะต้องแปลงอินพุตสตรีมของคุณเป็นสตริงและแยกสตริงเป็นวัตถุตัวแทน (เช่น XML, JSON และอื่น ๆ )

หรืออีกวิธีหนึ่งคือApache HttpClient (เวอร์ชัน 4 เป็นเวอร์ชั่นล่าสุด) มีความเสถียรและแข็งแกร่งกว่าค่าเริ่มต้นของจาวาURLConnectionและรองรับโปรโตคอล HTTP ส่วนใหญ่ (ถ้าไม่ใช่ทั้งหมด) (รวมถึงสามารถตั้งค่าเป็นโหมดเข้มงวด) คำตอบของคุณจะยังคงอยู่InputStreamและคุณสามารถใช้งานได้ตามที่กล่าวไว้ข้างต้น


เอกสารเกี่ยวกับ HttpClient: http://hc.apache.org/httpcomponents-client-ga/tutorial/html/index.html


5
อย่าประดิษฐ์ล้อเลื่อนใช้หนึ่งในการใช้งาน RESTful ที่มีอยู่
Qwerky

13
มันไม่ใช่การพลิกโฉมวงล้อฉันกำลังบอกว่าคุณสามารถใช้อะไรก็ได้ที่flavourคุณต้องการ บางคนต้องการเริ่มต้นบางอย่างต้องการURLConnection HttpClientไม่ว่าจะด้วยวิธีใดก็มีให้คุณใช้
Buhake Sindi

@ สุภาพบุรุษผู้ยอดขอบคุณสำหรับการตอบกลับของคุณ หลังจากตรวจสอบห้องสมุดทั้งหมดแล้วฉันต้องการใช้ Apache HttpClient คุณจะให้การอ้างอิงเพิ่มเติมเกี่ยวกับห้องสมุดนี้หรือไม่
คำถาม

@ คำถามลิงก์ไปยังตัวอย่าง HttpClient 4 ดูเหมือนว่าจะพังดังนั้นหากคุณมีคำถาม (ปุนตั้งใจ ... lol) แจ้งให้เราทราบ .... ฉันจัดการกับมันเกือบทุกวัน
Buhake Sindi

โปรดแสดงตัวอย่างรหัสวิธีใช้คลาสเหล่านี้แทนที่จะแสดงให้เห็นว่ามีอยู่จริง
Jonathan

150

Update:เกือบ 5 ปีแล้วที่ฉันเขียนคำตอบด้านล่าง; วันนี้ฉันมีมุมมองที่แตกต่าง

99% ของเวลาที่คนใช้คำว่า REST หมายถึง HTTP จริงๆ พวกเขาสามารถดูแลน้อยเกี่ยวกับ“ทรัพยากร”,“การแสดง”,“การถ่ายโอนรัฐ”,“อินเตอร์เฟซเครื่องแบบ”,“สื่อสิ่งพิมพ์” หรืออื่น ๆข้อ จำกัด หรือด้านของรูปแบบสถาปัตยกรรมที่เหลือระบุฟีลดิง abstractions ที่จัดเตรียมโดยกรอบงาน REST ต่างๆนั้นทำให้เกิดความสับสนและไม่ช่วยเหลือ

ดังนั้น: คุณต้องการส่งคำขอ HTTP โดยใช้ Java ในปี 2015 คุณต้องการ API ที่ชัดเจนแสดงออกใช้งานง่ายสำนวนง่าย จะใช้อะไรดี? ผมไม่ได้ใช้ Java แต่ไม่กี่ปีที่ผ่านมาห้องสมุด Java ลูกค้า HTTP ที่ได้ดูเหมือนมีแนวโน้มมากที่สุดและที่น่าสนใจคือOkHttp ลองดูสิ


คุณสามารถโต้ตอบกับเว็บเซอร์วิส RESTful ได้อย่างแน่นอนโดยใช้URLConnectionหรือHTTPClientไปยังคำขอรหัส HTTP

อย่างไรก็ตามโดยทั่วไปแล้วเป็นที่ต้องการมากกว่าที่จะใช้ไลบรารีหรือกรอบงานซึ่งมี API ที่เรียบง่ายและมีความหมายมากขึ้นซึ่งออกแบบมาเพื่อวัตถุประสงค์นี้โดยเฉพาะ สิ่งนี้ทำให้การเขียนอ่านและดีบักง่ายขึ้นและลดความซ้ำซ้อน โดยทั่วไปเฟรมเวิร์กเหล่านี้จะใช้คุณสมบัติที่ยอดเยี่ยมซึ่งไม่จำเป็นต้องมีอยู่หรือใช้งานง่ายในไลบรารีระดับล่างเช่นการเจรจาต่อรองเนื้อหาการแคชและการพิสูจน์ตัวตน

บางส่วนของตัวเลือกที่เป็นผู้ใหญ่มากที่สุดคือย์ , RESTEasyและRestlet

ฉันคุ้นเคยกับ Restlet และ Jersey มากที่สุดมาดูกันว่าเราจะทำPOSTคำขอกับ API ทั้งสองอย่างไร

ตัวอย่างเจอร์ซีย์

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

ตัวอย่าง Restlet

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

แน่นอนว่าคำขอของ GET นั้นง่ายกว่าและคุณสามารถระบุสิ่งต่างๆเช่นแท็กเอนทิตีและAcceptส่วนหัวได้ แต่หวังว่าตัวอย่างเหล่านี้จะเป็นประโยชน์เล็กน้อยไม่ซับซ้อน แต่ไม่ซับซ้อนเกินไป

อย่างที่คุณเห็น Restlet และ Jersey มี API ลูกค้าที่คล้ายกัน ฉันเชื่อว่าพวกเขาได้รับการพัฒนาในเวลาเดียวกันและดังนั้นจึงมีอิทธิพลต่อกัน

ฉันพบว่า Restlet API มีความหมายมากกว่านี้เล็กน้อยดังนั้นจึงชัดเจนกว่า แต่ YMMV

อย่างที่ฉันบอกว่าฉันคุ้นเคยกับ Restlet มากที่สุดฉันใช้มันในหลาย ๆ ปีมาแล้วและฉันก็มีความสุขมาก มันเป็นเฟรมเวิร์คที่โตเต็มที่แข็งแกร่งง่ายมีประสิทธิภาพใช้งานและได้รับการสนับสนุนเป็นอย่างดี ฉันไม่สามารถคุยกับ Jersey หรือ RESTEasy ได้ แต่ความประทับใจของฉันคือพวกเขาทั้งคู่ต่างก็มีตัวเลือกที่ดี


2
แต่ยังคงโพสต์ที่ดี และฉันต้องเห็นด้วยกับ "99% ของเวลาที่ผู้คนใช้คำว่า REST พวกเขาหมายถึง HTTP จริง ๆ ... ... นามธรรมที่จัดทำโดยกรอบ REST ต่างๆนั้นทำให้เกิดความสับสนและไม่ช่วยเหลือ"
AlexD

2
ในตัวอย่าง Jersey ของคุณแบบฟอร์มวัตถุได้ / ใช้ที่ไหน? มันถูกสร้างขึ้น แต่ดูเหมือนจะไม่เพิ่มอะไรเข้าไปในตัวอย่าง
splungebob

29

นี่คือซับซ้อนมากใน java ซึ่งเป็นเหตุผลที่ฉันแนะนำให้ใช้RestTemplateนามธรรมของ Spring :

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

อ้างอิง:


24

หากคุณเพียงแค่ต้องโทรไปที่บริการ REST จาก java คุณสามารถใช้บางอย่างในบรรทัดเหล่านี้

/*
 * 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
มี REST API ที่ดีอยู่รอบตัวฉันขอแนะนำให้ใช้อย่างใดอย่างหนึ่งแทนที่จะสร้างวงล้อใหม่
Qwerky

อย่างที่ฉันพูด: ซับซ้อนเหมือนนรก (ไม่ฉันไม่ได้ลงคะแนนนี่มันเป็นทางออกที่ถูกต้องสมบูรณ์)
Sean Patrick Floyd

4
@Qwerky API ฝั่งไคลเอ็นต์มักจะเป็นการละเมิดข้อ จำกัด REST พวกเขาแนะนำการมีเพศสัมพันธ์มากเกินไป การใช้ไลบรารี HTTP ที่ดีเป็นตัวเลือกที่ดีกว่าในระยะยาว
Darrel Miller

10

มี RESTful API หลายตัวรอบตัว ฉันอยากจะแนะนำ Jersey;

https://jersey.java.net/

เอกสาร API ไคลเอนต์อยู่ที่นี่;

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

อัปเดต
ตำแหน่งสำหรับเอกสาร OAuth ในความคิดเห็นด้านล่างเป็นลิงก์ที่ใช้งานไม่ได้และย้ายไปที่ https://jersey.java.net/nonav/documentation/latest/security.html#d0e12334


6
OP ไม่ได้สร้างแอปพลิเคชัน RESTful แต่เขากำลังทำการโทรออก RESTful เช่นการเรียกทรัพยากรเมธอด Twitter API
Buhake Sindi

@Qwerky - ฉันคิดว่ามันจะมีประโยชน์ในการรวมเหตุผลที่คุณแนะนำ Jersey ในคำตอบของคุณ
Danny Bullis

7

ฉันต้องการแบ่งปันประสบการณ์ส่วนตัวของฉันการเรียก REST WS ด้วยการโพสต์การโทร JSON:

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

คุณสามารถตรวจสอบCXF คุณสามารถเยี่ยมชมบทความ JAX-RS ได้ที่นี่

การโทรนั้นง่ายมาก (อ้าง):

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


4

โซลูชั่นที่ง่ายที่สุดจะใช้ห้องสมุดไคลเอนต์ Apache http อ้างอิงรหัสตัวอย่างต่อไปนี้ .. รหัสนี้ใช้ความปลอดภัยขั้นพื้นฐานสำหรับการตรวจสอบ

เพิ่มการพึ่งพาต่อไปนี้

<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

ฉันเห็นคำตอบมากมายนี่คือสิ่งที่เราใช้ในปี 2020 WebClientและ BTW RestTemplateกำลังจะถูกปฏิเสธ (สามารถตรวจสอบสิ่งนี้) RestTemplate กำลังจะถูกคัดค้าน


แทนที่จะให้ลิงก์คุณสามารถเพิ่มคำอธิบายที่นี่ได้ไหม
Kishan Bharda

-1

คุณสามารถใช้Async Http Client (ไลบรารียังรองรับโปรโตคอลWebSocket ) เช่นนั้น:

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

มันไม่ทำงาน (ไม่สามารถเปิดใช้งาน ASyncHttpClient)
Java Main
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.