过时的Java HttpClient - 有多难?

181

我想做的就是下载一些 JSON 并将其反序列化为一个对象。但我还没来得及下载 JSON。

几乎所有我找到的 HttpClient 示例,包括那些在 Apache 网站上的示例,看起来都差不多……

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;

public void blah() {
    HttpClient client = new DefaultHttpClient();
    ...
}

然而,Netbeans告诉我DefaultHttpClient已过时。我试着搜索DefaultHttpClient deprecated和其他我能想到的变体,但找不到任何有用的结果,所以我显然漏了什么。

下载网页内容的正确Java7方法是什么?语言中真的没有像样的Http客户端吗?我很难相信。

我用的Maven依赖是...

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>LATEST</version>
    <type>jar</type>
</dependency>

2
NetBeans告诉你的是错误的,或者你可能读错了什么。DefaultHttpClient绝对没有被弃用。你在POM中指定了哪个版本? - Perception
8
在4.3-alpha1中,它似乎已经被弃用了。 - Arun P Johny
3
你说得对,httpclient API 真是一团糟。 - Hans Westerbeek
2
我建议您将版本设置为某个主要发布号,而不是LATEST。这样可以让您手动控制升级过程,而不是让Maven为您决定。 - Christophe Roussy
1
@ChristopheRoussy 我们不妨不争论了,各有所见。 - Basic
显示剩余5条评论
10个回答

276

相关导入:

import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import java.io.IOException;

使用方法:

HttpClient httpClient = HttpClientBuilder.create().build();

在Jules的建议之后进行编辑:

由于build()方法返回一个CloseableHttpClient,它是AutoClosable的一种,因此您可以将声明放在try-with-resources语句(Java 7+)中:

try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {

    // use httpClient (no need to close it explicitly)

} catch (IOException e) {

    // handle

}

2
您正在使用低于4.3版本的程序(应该使用Apache HTTPClient而不是Commons HTTPClient)。 - Alfishe
7
请注意,返回值是一个CloseableHttpClient对象,您需要在使用后关闭它。它实现了AutoCloseable接口,在Java 7+中您可以使用try-with-resources语句:try (CloseableHttpClient httpclient = ...) { ... } - Jules
2
CloseableHttpClient httpClient = HttpClientBuilder.create().build(); 这段代码对我起作用。 - Sameer Kazi
7
我们是否应该保留create()静态方法返回的HttpClientBuilder实例?或者我们只需在需要时随时调用create()?另外,对于任何需要导入语句的人,可以使用import org.apache.http.impl.client.HttpClientBuilder - ADTC
1
@HartmutPfitzinger 在 Android 上使用 OkHttp。他们在一个分叉的 Apache Http Client 上搞砸了,现在已经过时了。 - sschrass
显示剩余5条评论

61

个人认为被接受的回答是正确的,但缺少一些“教导”,因为它没有解释如何得出答案。 对于所有弃用的类,请查看JavaDoc(如果您没有它,可以下载它或在线查看),它会提示使用哪个类来替换旧代码。当然,它不会告诉您所有内容,但这是一个开始。例如:

...
 *
 * @deprecated (4.3) use {@link HttpClientBuilder}.  <----- THE HINT IS HERE !
 */
@ThreadSafe
@Deprecated
public class DefaultHttpClient extends AbstractHttpClient {
现在你已经有了可用的类HttpClientBuilder,由于没有构造函数来获取一个builder实例,因此你可能猜测必须有一个静态方法:create。一旦你获得了该builder,你还可以猜测,就像大多数建造者一样,它有一个build方法,因此:
org.apache.http.impl.client.HttpClientBuilder.create().build();

自动关闭:

正如Jules在评论中暗示的那样,返回的类实现了java.io.Closable接口,因此如果您使用Java 7或以上版本,则现在可以执行以下操作:

    try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {...}

优点是您不必处理finally和null。

其他相关信息

还要确保阅读有关连接池的内容,并设置超时时间


13

Apache的示例 使用此方法:

CloseableHttpClient httpclient = HttpClients.createDefault();

自4.3版本以来就有org.apache.http.impl.client.HttpClients类。

HttpClients.createDefault()的代码与这里的接受答案相同。


使用HttpClient client = HttpClients.createDefault()时,出现错误"Caused by: java.lang.VerifyError: org/apache/http/conn/ssl/DefaultHostnameVerifier"。 - Md Imran Choudhury

7

由于您使用了 LATEST 版本规范,因此在版本 4.3-alpha1 中已被弃用。如果您查看该类的 javadoc,它会告诉您应使用什么替代品:HttpClientBuilder

在最新稳定版(4.2.3)中,DefaultHttpClient 尚未被弃用。


谢谢回复 - Netbeans没有显示任何org.apache的JavaDocs - 但我想那是另一个问题。 - Basic
你可能没有将源代码附加到库中。我不使用Netbeans,但我猜测有一种方法可以让它下载依赖项的源代码。 - zagyi

7
尝试使用jcabi-http,这是一个流畅的Java HTTP客户端,例如:
String html = new JdkRequest("https://www.google.com")
  .header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML)
  .fetch()
  .as(HttpResponse.class)
  .assertStatus(HttpURLConnection.HTTP_OK)
  .body();

还请查看这篇博客文章:http://www.yegor256.com/2014/04/11/jcabi-http-intro.html


4
如果您只想读取JSON数据,我建议使用以下方法。
URL requestUrl=new URL(url);
URLConnection con = requestUrl.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb=new StringBuilder();
int cp;
try {
    while((cp=rd.read())!=-1){
    sb.append((char)cp);
  }
 catch(Exception e){
 }
 String json=sb.toString();

问题说DefaultHttpClient已经被弃用,而你在回答中建议使用它... - Basic
感谢提供另一种方法。我已经选择了被接受的答案,但这个方法看起来足够轻量级,下次我会尝试一下。 - Basic

2
您可以添加以下Maven依赖项。
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpmime</artifactId>
        <version>4.5.1</version>
    </dependency>

您可以在Java代码中使用以下导入。
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGett;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.client.methods.HttpUriRequest;

您可以在Java代码中使用以下代码块。
HttpClient client = HttpClientBuilder.create().build();
HttpUriRequest httpUriRequest = new HttpGet("http://example.domain/someuri");

HttpResponse response = client.execute(httpUriRequest);
System.out.println("Response:"+response);

谢谢您抽出时间回答,但这与被接受的答案有何不同? - Basic
1
大多数答案都是伪代码,我尝试使用Apache HTTP Client API以及Maven依赖项编写了一段端到端的基本Java工作代码。虽然不是很出色。 - Red Boy

2
使用HttpClientBuilder构建HttpClient,而不是使用DefaultHttpClient。请参考以下链接:HttpClientBuilderHttpClient
MinimalHttpClient httpclient = new HttpClientBuilder().build();

 // Prepare a request object
 HttpGet httpget = new HttpGet("http://www.apache.org/");

为什么要使用new HttpClientBuilder()而不是HttpClientBuilder.create() - ADTC

1

这是我应用于Android 22版本中HttpClient被弃用问题的解决方案。

 public static String getContenxtWeb(String urlS) {
    String pagina = "", devuelve = "";
    URL url;
    try {
        url = new URL(urlS);
        HttpURLConnection conexion = (HttpURLConnection) url
                .openConnection();
        conexion.setRequestProperty("User-Agent",
                "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)");
        if (conexion.getResponseCode() == HttpURLConnection.HTTP_OK) {
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(conexion.getInputStream()));
            String linea = reader.readLine();
            while (linea != null) {
                pagina += linea;
                linea = reader.readLine();
            }
            reader.close();

            devuelve = pagina;
        } else {
            conexion.disconnect();
            return null;
        }
        conexion.disconnect();
        return devuelve;
    } catch (Exception ex) {
        return devuelve;
    }
}

-2

针对这个问题,我建议您应用以下逻辑:

 CloseableHttpClient httpClient = HttpClientBuilder.create().build();
 HttpPost httpPostRequest = new HttpPost();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接