2009-08-31 50 views
343

Trong Java, Làm thế nào để soạn một thông báo yêu cầu HTTP và gửi nó tới máy chủ HTTP WebServer?Làm thế nào để gửi yêu cầu HTTP trong java?

+27

[Có một hướng dẫn nhỏ tại đây tại SO] (http: // stackoverflow.com/questions/2793150/how-to-use-java-net-urlconnection-to-fire-and-handle-http-yêu cầu). – BalusC

+0

http://java.sun.com/javase/6/docs/api/java/net/HttpURLConnection.html Cụ thể, getHeaderField, getHeaderFieldKey và getContent –

+0

Bạn có thể sử dụng liboup lib (http://jsoup.org). Nó thực hiện chính xác những gì bạn yêu cầu! Tài liệu doc ​​= Jsoup.connect ("http://en.wikipedia.org"). được(); (từ trang web). Một cách khác nữa cho java. – user2007447

Trả lời

254

Bạn có thể sử dụng java.net.HttpUrlConnection.

Ví dụ (from here), với các cải tiến. Trong trường hợp liên kết thối:

public static String executePost(String targetURL, String urlParameters) { 
    HttpURLConnection connection = null; 

    try { 
    //Create connection 
    URL url = new URL(targetURL); 
    connection = (HttpURLConnection) url.openConnection(); 
    connection.setRequestMethod("POST"); 
    connection.setRequestProperty("Content-Type", 
     "application/x-www-form-urlencoded"); 

    connection.setRequestProperty("Content-Length", 
     Integer.toString(urlParameters.getBytes().length)); 
    connection.setRequestProperty("Content-Language", "en-US"); 

    connection.setUseCaches(false); 
    connection.setDoOutput(true); 

    //Send request 
    DataOutputStream wr = new DataOutputStream (
     connection.getOutputStream()); 
    wr.writeBytes(urlParameters); 
    wr.close(); 

    //Get Response 
    InputStream is = connection.getInputStream(); 
    BufferedReader rd = new BufferedReader(new InputStreamReader(is)); 
    StringBuilder response = new StringBuilder(); // or StringBuffer if Java version 5+ 
    String line; 
    while ((line = rd.readLine()) != null) { 
     response.append(line); 
     response.append('\r'); 
    } 
    rd.close(); 
    return response.toString(); 
    } catch (Exception e) { 
    e.printStackTrace(); 
    return null; 
    } finally { 
    if (connection != null) { 
     connection.disconnect(); 
    } 
    } 
} 
+2

Dưới đây là một đoạn mã đẹp khác thay thế cho Java Almanac: [HttpUrlConnection-Example] (http://www.xyzws.com/Javafaq/how-to-use-httpurlconnection-post-data-to-web-server/139) – GreenTurtle

+9

Đưa một số mã thực tế vào câu trả lời này sẽ giúp tránh sự liên kết thối ... – Cypher

202

Từ Oracle's java tutorial

import java.net.*; 
import java.io.*; 

public class URLConnectionReader { 
    public static void main(String[] args) throws Exception { 
     URL yahoo = new URL("http://www.yahoo.com/"); 
     URLConnection yc = yahoo.openConnection(); 
     BufferedReader in = new BufferedReader(
           new InputStreamReader(
           yc.getInputStream())); 
     String inputLine; 

     while ((inputLine = in.readLine()) != null) 
      System.out.println(inputLine); 
     in.close(); 
    } 
} 
+1

Điều kỳ lạ là một số máy chủ sẽ trả lời bạn trở lại lạ? ký tự (có vẻ như lỗi mã hóa liên quan đến tiêu đề yêu cầu nhưng không) nếu bạn không mở luồng đầu ra và xóa luồng đầu tiên. Tôi không biết tại sao điều này lại xảy ra nhưng sẽ tuyệt vời nếu ai đó có thể giải thích tại sao? – Gorky

+1

@Gorky: Đặt một câu hỏi mới –

+51

Đây là cách quá nhiều dòng tiếng ồn để gửi một yêu cầu HTTP imo. Tương phản với thư viện yêu cầu của Python: 'response = requests.get ('http://www.yahoo.com/')'; một cái gì đó của ngắn gọn tương tự nên có thể trong Java. –

59

Tôi biết những người khác sẽ khuyên http-client Apache, nhưng nó thêm phức tạp (ví dụ, nhiều thứ có thể đi sai) đó là hiếm khi bảo hành. Đối với một nhiệm vụ đơn giản, java.net.URL sẽ thực hiện.

URL url = new URL("http://www.y.com/url"); 
InputStream is = url.openStream(); 
try { 
    /* Now read the retrieved document from the stream. */ 
    ... 
} finally { 
    is.close(); 
} 
+5

Điều đó không có ích nếu bạn muốn khỉ với các tiêu đề yêu cầu, điều gì đó đặc biệt hữu ích khi xử lý các trang web sẽ chỉ phản hồi một cách nhất định cho các trình duyệt phổ biến. – Jherico

+30

Bạn có thể khỉ với tiêu đề yêu cầu bằng cách sử dụng URLConnection, nhưng người đăng không yêu cầu điều đó; đánh giá từ câu hỏi, một câu trả lời đơn giản là quan trọng. – erickson

54

Apache HttpComponents. Các ví dụ cho hai mô-đun - HttpCoreHttpClient sẽ giúp bạn bắt đầu ngay lập tức.

Không phải HttpUrlConnection là một lựa chọn tồi, HttpComponents sẽ trừu tượng hóa rất nhiều mã nguệch ngoạc. Tôi sẽ giới thiệu điều này, nếu bạn thực sự muốn hỗ trợ rất nhiều máy chủ/máy khách HTTP với mã tối thiểu. Bằng cách này, HttpCore có thể được sử dụng cho các ứng dụng (máy khách hoặc máy chủ) với chức năng tối thiểu, trong khi HttpClient được sử dụng cho các khách hàng yêu cầu hỗ trợ cho nhiều lược đồ xác thực, hỗ trợ cookie, v.v.

+2

FWIW, mã của chúng tôi bắt đầu với java.net.HttpURLConnection, nhưng khi chúng tôi phải thêm SSL và làm việc xung quanh một số trường hợp sử dụng kỳ lạ trong các mạng nội bộ khó hiểu của chúng tôi, nó đã trở thành một nhức đầu thực sự. Các thành phần Apache HttpComponents đã lưu trong ngày. Dự án của chúng tôi hiện vẫn sử dụng kết hợp xấu xí, với một vài bộ điều hợp tinh vi để chuyển đổi java.net.URL thành các URIs HttpComponents sử dụng. Tôi tái cấu trúc chúng thường xuyên. Mã HttpComponents thời gian duy nhất hóa ra phức tạp hơn nhiều là phân tích các ngày từ một tiêu đề. Nhưng [giải pháp] (http://stackoverflow.com/a/1930240/1450294) cho điều đó vẫn còn đơn giản. –

7

Có một liên kết tuyệt vời về việc gửi Yêu cầu POST here theo Ví dụ Depot ::

try { 
    // Construct data 
    String data = URLEncoder.encode("key1", "UTF-8") + "=" + URLEncoder.encode("value1", "UTF-8"); 
    data += "&" + URLEncoder.encode("key2", "UTF-8") + "=" + URLEncoder.encode("value2", "UTF-8"); 

    // Send data 
    URL url = new URL("http://hostname:80/cgi"); 
    URLConnection conn = url.openConnection(); 
    conn.setDoOutput(true); 
    OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); 
    wr.write(data); 
    wr.flush(); 

    // Get the response 
    BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
    String line; 
    while ((line = rd.readLine()) != null) { 
     // Process line... 
    } 
    wr.close(); 
    rd.close(); 
} catch (Exception e) { 
} 

Nếu bạn muốn gửi yêu cầu GET, bạn có thể sửa đổi mã một chút để phù hợp với nhu cầu của mình. Cụ thể, bạn phải thêm các tham số bên trong hàm tạo của URL. Sau đó, cũng nhận xét ra điều này wr.write(data);

Một điều không được viết và bạn nên cẩn thận, là hết thời gian chờ. Đặc biệt là nếu bạn muốn sử dụng nó trong WebServices bạn phải thiết lập timeout, nếu không mã trên sẽ chờ đợi vô thời hạn hoặc trong một thời gian rất dài ít nhất và đó là một cái gì đó có lẽ bạn không muốn.

Timeouts được thiết lập như conn.setReadTimeout(2000); này các tham số đầu vào là trong mili giây

12

này sẽ giúp bạn. Đừng quên thêm JAR HttpClient.jar vào đường dẫn lớp.

import java.io.FileOutputStream; 
import java.io.IOException; 

import org.apache.commons.httpclient.HttpClient; 
import org.apache.commons.httpclient.HttpStatus; 
import org.apache.commons.httpclient.NameValuePair; 
import org.apache.commons.httpclient.methods.PostMethod; 

public class MainSendRequest { 

    static String url = 
     "http://localhost:8080/HttpRequestSample/RequestSend.jsp"; 

    public static void main(String[] args) { 

     //Instantiate an HttpClient 
     HttpClient client = new HttpClient(); 

     //Instantiate a GET HTTP method 
     PostMethod method = new PostMethod(url); 
     method.setRequestHeader("Content-type", 
       "text/xml; charset=ISO-8859-1"); 

     //Define name-value pairs to set into the QueryString 
     NameValuePair nvp1= new NameValuePair("firstName","fname"); 
     NameValuePair nvp2= new NameValuePair("lastName","lname"); 
     NameValuePair nvp3= new NameValuePair("email","[email protected]"); 

     method.setQueryString(new NameValuePair[]{nvp1,nvp2,nvp3}); 

     try{ 
      int statusCode = client.executeMethod(method); 

      System.out.println("Status Code = "+statusCode); 
      System.out.println("QueryString>>> "+method.getQueryString()); 
      System.out.println("Status Text>>>" 
        +HttpStatus.getStatusText(statusCode)); 

      //Get data as a String 
      System.out.println(method.getResponseBodyAsString()); 

      //OR as a byte array 
      byte [] res = method.getResponseBody(); 

      //write to file 
      FileOutputStream fos= new FileOutputStream("donepage.html"); 
      fos.write(res); 

      //release connection 
      method.releaseConnection(); 
     } 
     catch(IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+1

Nghiêm túc, tôi thực sự thích Java, nhưng vấn đề với danh sách hoặc mảng ngu ngốc 'NameValuePair' đó là gì. Tại sao không phải là một 'Bản đồ ' đơn giản? Vì vậy, nhiều mã bản mẫu cho các trường hợp sử dụng đơn giản như vậy ... – Joffrey

+2

@Joffrey Maps theo định nghĩa có 1 khóa cho mỗi giá trị, có nghĩa là: 'Một bản đồ không thể chứa các khóa trùng lặp'! Nhưng thông số HTTP có thể có các khóa trùng lặp. – Ben

9

Bạn có thể sử dụng Socket cho như

String host = "www.yourhost.com"; 
Socket socket = new Socket(host, 80); 
String request = "GET/HTTP/1.0\r\n\r\n"; 
OutputStream os = socket.getOutputStream(); 
os.write(request.getBytes()); 
os.flush(); 

InputStream is = socket.getInputStream(); 
int ch; 
while((ch=is.read())!= -1) 
    System.out.print((char)ch); 
socket.close();  
+0

@ laksys tại sao phải là '\ r \ n' thay vì' \ n'? – CuriousGuy

+0

@CuriousGuy xem liên kết này http://programmers.stackexchange.com/questions/29075/difference-between-n-and-r-n – laksys

20

này Dưới đây là hoàn tất một chương trình Java 7:

class GETHTTPResource { 
    public static void main(String[] args) throws Exception { 
    try (java.util.Scanner s = new java.util.Scanner(new java.net.URL("http://tools.ietf.org/rfc/rfc768.txt").openStream())) { 
     System.out.println(s.useDelimiter("\\A").next()); 
    } 
    } 
} 

mới thử-với-các nguồn lực sẽ tự động đóng Scanner, mà sẽ tự động đóng InputStream.

+0

Bạn có một ngoại lệ chưa được xử lý tại đây. Đây là Java và bạn có 500 ngoại lệ để xử lý cho mọi dòng mã :) – Ska

+0

@Ska Không có ngoại lệ không được giải quyết. 'main()' ném ngoại lệ, bao gồm MalformedURLException và IOException. – jerzy

12

Google java http client có API tốt cho yêu cầu http. Bạn có thể dễ dàng thêm hỗ trợ JSON, v.v. Mặc dù yêu cầu đơn giản nó có thể là quá mức cần thiết.

import com.google.api.client.http.GenericUrl; 
import com.google.api.client.http.HttpRequest; 
import com.google.api.client.http.HttpResponse; 
import com.google.api.client.http.HttpTransport; 
import com.google.api.client.http.javanet.NetHttpTransport; 
import java.io.IOException; 
import java.io.InputStream; 

public class Network { 

    static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); 

    public void getRequest(String reqUrl) throws IOException { 
     GenericUrl url = new GenericUrl(reqUrl); 
     HttpRequest request = HTTP_TRANSPORT.createRequestFactory().buildGetRequest(url); 
     HttpResponse response = request.execute(); 
     System.out.println(response.getStatusCode()); 

     InputStream is = response.getContent(); 
     int ch; 
     while ((ch = is.read()) != -1) { 
      System.out.print((char) ch); 
     } 
     response.disconnect(); 
    } 
} 
+0

Bạn có ý gì với 'phương tiện'? – raspi

+0

Xin lỗi, đó phải là 'HTTP_TRANSPORT', tôi đã chỉnh sửa câu trả lời. – Tombart

+0

tại sao HttpResponse không tự động sửa chữa? Sự khác biệt này là gì và làm việc với CloseableHttpClient của Apache? –

Các vấn đề liên quan