2009-08-31 3 views
343

В Java, как составить сообщение HTTP-запроса и отправить его на HTTP-сервер?Как отправить HTTP-запрос в java?

+27

[Здесь в SO] есть мини-учебник (http: // stackoverflow.ком/вопросы/2793150/как в использовании, Java-нетто-URLConnection пожаробезопасности-и ручка-HTTP-запросов). – BalusC

+0

http://java.sun.com/javase/6/docs/api/java/net/HttpURLConnection.html В частности, getHeaderField, getHeaderFieldKey и getContent –

+0

Вы можете использовать JSoup lib (http://jsoup.org). Он делает именно то, что вы просите! Документ doc = Jsoup.connect ("http://en.wikipedia.org"). получить(); (с сайта). Более pythonic путь для java. – user2007447

ответ

254

Вы можете использовать java.net.HttpUrlConnection. (from here) с улучшениями. В случае ссылки гнили:

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

Вот еще один хороший фрагмент кода вместо Java Almanac: [HttpUrlConnection-Example] (http://www.xyzws.com/Javafaq/how-to-use-httpurlconnection-post-data-to-web-server/139) – GreenTurtle

+9

Ввод фактического кода в этот ответ поможет избежать гниения ссылок ... – Cypher

202

От 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

Странно, что некоторые серверы ответят вам странно? символов (что кажется ошибкой кодирования, связанной с заголовками запроса, но не), если вы не открываете выходной поток и сначала не очищаете его. Я понятия не имею, почему это происходит, но будет здорово, если кто-нибудь сможет объяснить, почему? – Gorky

+1

@Gorky: Задайте новый вопрос –

+51

Это слишком большой линейный шум для отправки HTTP-запроса imo. Контраст с библиотекой запросов Python: 'response = requests.get ('http://www.yahoo.com/')'; что-то похожее краткость должно быть возможным на Java. –

59

Я знаю, что другие будут рекомендовать HTTP-клиент Apache, но это добавляет сложности (то есть больше вещей, которые могут пойти не так), что редко гарантия. Для простой задачи, java.net.URL будет делать.

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

Это не поможет, если вы хотите обезьяны с заголовками запросов, что особенно полезно при работе с сайтами, которые будут реагировать определенным образом на популярные браузеры. – Jherico

+30

Вы можете обезьяны с заголовками запросов с использованием URLConnection, но плакат не спрашивает об этом; Судя по этому вопросу, очень важен простой ответ. – erickson

54

Apache HttpComponents. Примеры для двух модулей - HttpCore и HttpClient помогут вам начать работу сразу.

Не то, чтобы HttpUrlConnection - это плохой выбор, HttpComponents отвлекут много утомительной кодировки. Я бы рекомендовал это, если вы действительно хотите поддерживать множество HTTP-серверов/клиентов с минимальным кодом. Кстати, HttpCore может использоваться для приложений (клиентов или серверов) с минимальными функциональными возможностями, тогда как HttpClient должен использоваться для клиентов, которым требуется поддержка нескольких схем аутентификации, поддержка файлов cookie и т. Д.

+2

FWIW, наш код начинался с java.net.HttpURLConnection, но когда нам приходилось добавлять SSL и работать с некоторыми странными вариантами использования в наших сумасшедших внутренних сетях, это стало настоящей головной болью. Апач HttpComponents сохранил этот день. Наш проект в настоящее время по-прежнему использует уродливый гибрид с несколькими изворотными адаптерами для преобразования java.net.URLs в URI, используемые HttpComponents. Я регулярно реорганизую их. Единственный раз, когда код HttpComponents оказался значительно сложнее, - это синтаксический анализ дат из заголовка. Но [решение] (http://stackoverflow.com/a/1930240/1450294) для этого все еще просто. –

7

Существует отличная ссылка на отправку POST запрос here по примеру 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) { 
} 

Если вы хотите отправить запрос GET вы можете изменить код немного, чтобы удовлетворить ваши потребности. В частности, вам нужно добавить параметры внутри конструктора URL. Тогда, также закомментируйте это wr.write(data);

Одна вещь, которая не написана, и вы должны остерегаться, это таймауты. Особенно, если вы хотите использовать его в WebServices, вам нужно установить таймауты, иначе приведенный выше код будет ждать неопределенно долго или в течение очень долгого времени, по крайней мере, и это то, что вы, вероятно, не хотите.

Таймауты устанавливаются как этот conn.setReadTimeout(2000); входной параметр находится в миллисекундах

12

Это поможет вам. Не забудьте добавить JAR HttpClient.jar в путь к классам.

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

Серьезно, мне очень нравится Java, но в чем дело с этим глупым списком или массивом NameValuePair. Почему бы не просто «Карта <Строка, Строка>»? Так много шаблонов кода для таких простых случаев использования ... – Joffrey

+2

@Joffrey Карты по определению имеют 1 ключ за значение, означает: 'Карта не может содержать дубликаты ключей'! Но параметры HTTP могут иметь дубликаты ключей. – Ben

9

Вы можете использовать гнездо для этого, как

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, почему это должно быть '\ r \ n' вместо' \ n'? – CuriousGuy

+0

@CuriousGuy посмотрите на эту ссылку http://programmers.stackexchange.com/questions/29075/difference-between-n-and-r-n – laksys

20

Вот полный 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()); 
    } 
    } 
} 

Новая попытка-с-ресурсов будет автоматически закрыть сканер, который будет автоматически закрывать InputStream.

+0

У вас здесь необработанное исключение. Это Java, и у вас есть 500 исключений для обработки каждой строки кода :) – Ska

+0

@Ska Исключено необработанное исключение. 'main()' throws Exception, который включает в себя MalformedURLException и IOException. – jerzy

12

Google java http client имеет хороший API для запросов HTTP. Вы можете легко добавить поддержку JSON и т. Д. Хотя для простого запроса это может быть излишним.

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

Что значит «транспорт»? – raspi

+0

К сожалению, это должен был быть 'HTTP_TRANSPORT', я отредактировал ответ. – Tombart

+0

Почему HttpResponse не AutoClosable? В чем отличие от этого и от работы с CloseableHttpClient от Apache? –

Смежные вопросы