【问题标题】:How to send HTTP request in java? [duplicate]如何在 Java 中发送 HTTP 请求? [复制]
【发布时间】:2010-11-24 11:40:22
【问题描述】:

在 Java 中,如何编写 HTTP 请求消息并将其发送到 HTTP WebServer?

【问题讨论】:

标签: java html http httpwebrequest


【解决方案1】:

您可以使用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();
    }
  }
}

【讨论】:

  • 这里是另一个不错的代码 sn-p 代替 Java Almanac:HttpUrlConnection-Example
  • 将一些实际代码放入此答案将有助于避免链接失效...
  • 从Java 9开始,创建HTTP请求has become much easier
  • 是的,自从给出这个答案以来的十年里发生了很多变化。并非所有人都从 JDK8 升级到 9 及更高版本。
【解决方案2】:

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

【讨论】:

  • 奇怪的是有些服务器会回复你奇怪的?如果您不打开输出流并先刷新它,则字符(这似乎是与请求标头相关但不是编码错误)。我不知道为什么会发生这种情况,但如果有人能解释为什么会很好?
  • 这对 imo 发送 HTTP 请求来说线路噪音太大。对比 Python 的 requests 库:response = requests.get('http://www.yahoo.com/');在 Java 中应该可以实现类似的简洁性。
  • @leo-the-manic 这是因为 Java 应该是一种较低级别的语言(比 python)并允许(强制)程序员处理底层的细节,而不是假设“理智”的默认值(即缓冲、字符编码等)。获得简洁的东西是可能的,但是你会失去更多准系统方法的灵活性。
  • @fortran Python 具有同样低级的选项来完成与上述相同的事情。
  • "那是因为 Java 应该是低级语言" X'D
【解决方案3】:

我知道其他人会推荐 Apache 的 http-client,但它增加了很少保证的复杂性(即,可能出错的事情更多)。对于一个简单的任务,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();
}

【讨论】:

  • 如果您想对请求标头进行猴子处理,这无济于事,这在处理只会以某种方式响应流行浏览器的网站时特别有用。
  • 您可以使用 URLConnection 处理请求标头,但发帖人并没有要求这样做;从问题来看,一个简单的答案很重要。
【解决方案4】:

Apache HttpComponents。这两个模块的示例 - HttpCoreHttpClient 将帮助您立即开始。

并不是说 HttpUrlConnection 是一个糟糕的选择,HttpComponents 会抽象掉很多繁琐的编码。如果你真的想用最少的代码支持很多 HTTP 服务器/客户端,我会推荐这个。顺便说一句,HttpCore 可用于功能最少的应用程序(客户端或服务器),而 HttpClient 用于需要支持多种身份验证方案、cookie 支持等的客户端。

【讨论】:

  • FWIW,我们的代码从 java.net.HttpURLConnection 开始,但是当我们不得不添加 SSL 并解决我们内部网络中的一些奇怪用例时,它变得非常令人头疼。 Apache HttpComponents 拯救了这一天。我们的项目目前仍然使用一个丑陋的混合体,使用一些不可靠的适配器将 java.net.URLs 转换为 HttpComponents 使用的 URIs。我定期重构那些。唯一一次 HttpComponents 代码变得更加复杂的是从标头中解析日期。但是solution 仍然很简单。
  • 在此处添加代码 sn-p 会有所帮助
【解决方案5】:

有一个关于通过 Example Depot 发送 POST 请求 here 的很棒的链接::

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);输入参数以毫秒为单位

【讨论】:

    【解决方案6】:

    这将对您有所帮助。不要忘记将 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@email.com");
    
            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();
            }
        }
    }
    

    【讨论】:

    • 说真的,我真的很喜欢 Java,但是那个愚蠢的 NameValuePair 列表或数组是怎么回事。为什么不是简单的Map<String, String>?如此简单的用例有这么多样板代码......
    • @Joffrey Maps 根据定义每个值有 1 个键,意思是:A map cannot contain duplicate keys!但是 HTTP 参数可以有重复的键。
    【解决方案7】:

    你可以像这样使用 Socket

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

    【讨论】:

    【解决方案8】:

    这是一个完整的 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());
        }
      }
    }
    

    新的 try-with-resources 将自动关闭 Scanner,这将自动关闭 InputStream。

    【讨论】:

    • @Ska 没有未处理的异常。 main() 抛出异常,包含 MalformedURLException 和 IOException。
    • 扫描仪在性能方面实际上并不是很优化。
    【解决方案9】:

    Google java http client 为 http 请求提供了很好的 API。您可以轻松地添加 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();
        }
    }
    

    【讨论】:

    • “运输”是什么意思?
    • 对不起,应该是HTTP_TRANSPORT,我已经编辑了答案。
    • 为什么 HttpResponse 不能自动关闭?这和使用 Apache 的 CloseableHttpClient 有什么区别?
    • 好处是API,这确实是个人喜好。 Google 的库在内部使用 Apache 的库。也就是说,我喜欢 Google 的 lib。
    猜你喜欢
    • 2016-11-16
    • 2021-12-21
    • 1970-01-01
    • 2013-06-15
    • 2018-08-09
    • 2011-03-20
    • 2014-03-12
    相关资源
    最近更新 更多