HttpClient

maven

xml 复制代码
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.14</version>
</dependency>

使用

下面的代码片段阐述了使用 HttpClient 本地 API 执行 HTTP GET 和 POST 请求。

java 复制代码
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://targethost/homepage");
CloseableHttpResponse response1 = httpclient.execute(httpGet);

try {
    System.out.println(response1.getStatusLine());
    HttpEntity entity1 = response1.getEntity();
    
    EntityUtils.consume(entity1);
} finally {
    response1.close();
}

HttpPost httpPost = new HttpPost("http://targethost/login");
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("username", "vip"));
nvps.add(new BasicNameValuePair("password", "secret"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
CloseableHttpResponse response2 = httpclient.execute(httpPost);

try {
    System.out.println(response2.getStatusLine());
    HttpEntity entity2 = response2.getEntity();
    
    EntityUtils.consume(entity2);
} finally {
    response2.close();
}

链式调用发送请求:

java 复制代码
Request.Get("http://targethost/homepage")
    .execute().returnContent();
Request.Post("http://targethost/login")
    .bodyForm(Form.form().add("username",  "vip").add("password",  "secret").build())
    .execute().returnContent();

HttpClient 是线程安全的,当不再需要 HttpClient 实例的时候应该通过调用 HttpClient#close() 释放资源。

HTTP 请求

HttpClient 可以用于发送 HTTP 请求,最简单的使用 HttpClient API 执行请求的模板代码如下:

java 复制代码
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/");
CloseableHttpResponse response = httpclient.execute(httpget);
try {
    doSomething();
} finally {
    response.close();
}

HttpClient 为每一个 HTTP 方法都定义了一个特定的类,对应关系如下:

  • GET:HttpGet
  • POST:HttpPost
  • HEAD:HttpHead
  • PUT:HttpPut
  • DELETE:HttpDelete
  • TRACE:HttpTrace
  • OPTIONS:HttpOptions

URIBuilder 使用 HttpClient 提供的用于构建 URL 的实用工具类,其使用方式如下:

java 复制代码
URI uri = new URIBuilder()
        .setScheme("http")
        .setHost("www.google.com")
        .setPath("/search")
        .setParameter("q", "httpclient")
        .setParameter("btnG", "Google Search")
        .setParameter("aq", "f")
        .setParameter("oq", "")
        .build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());

上述代码将构建如下所示的 URL 字符串:

tex 复制代码
http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=

HTTP 请求可以由请求体,HTTP 响应也可以有响应体,在 HttpClient 中被称为实体,顶级接口就是 HttpEntity,它有很多的实现类,不同的类就表示不同类型的实体。

为 HTTP 请求设置请求体

java 复制代码
// 文件实体
File file = new File("somefile.txt");
FileEntity entity = new FileEntity(file, ContentType.create("text/plain", "UTF-8"));        

HttpPost httppost = new HttpPost("http://localhost/action.do");
httppost.setEntity(entity);

// 表单实体
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("param1", "value1"));
formparams.add(new BasicNameValuePair("param2", "value2"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
HttpPost httppost = new HttpPost("http://localhost/handler.do");
httppost.setEntity(entity);

处理响应最简单和最方便的方式就是给请求设置响应处理器 ResponseHandler。

java 复制代码
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/json");

ResponseHandler<MyJsonObject> rh = new ResponseHandler<MyJsonObject>() {

    @Override
    public JsonObject handleResponse(
            final HttpResponse response) throws IOException {
        StatusLine statusLine = response.getStatusLine();
        HttpEntity entity = response.getEntity();
        if (statusLine.getStatusCode() >= 300) {
            throw new HttpResponseException(
                    statusLine.getStatusCode(),
                    statusLine.getReasonPhrase());
        }
        if (entity == null) {
            throw new ClientProtocolException("Response contains no content");
        }
        Gson gson = new GsonBuilder().create();
        ContentType contentType = ContentType.getOrDefault(entity);
        Charset charset = contentType.getCharset();
        Reader reader = new InputStreamReader(entity.getContent(), charset);
        return gson.fromJson(reader, MyJsonObject.class);
    }
};
MyJsonObject myjson = client.execute(httpget, rh);

HTTP 响应

HTTP 响应式服务器在接收并解析 HTTP 请求后发送回客户端的消息,它由协议版本、响应状态和响应体组成。

java 复制代码
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 
HttpStatus.SC_OK, "OK");

System.out.println(response.getProtocolVersion());
System.out.println(response.getStatusLine().getStatusCode());
System.out.println(response.getStatusLine().getReasonPhrase());
System.out.println(response.getStatusLine().toString());

以上代码片段的输出如下:

tex 复制代码
HTTP/1.1
200
OK
HTTP/1.1 200 OK

HttpClient 提供给响应添加响应头的 API,如添加Context-Length、Context-Type 等。

java 复制代码
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
response.addHeader("Set-Cookie", "c1=a; path=/; domain=localhost");
response.addHeader("Set-Cookie", "c2=b; path=\"/\", c3=c; domain=\"localhost\"");

Header h1 = response.getFirstHeader("Set-Cookie");
Header h2 = response.getLastHeader("Set-Cookie");
Header[] hs = response.getHeaders("Set-Cookie");
System.out.println(h1);
System.out.println(h2);
System.out.println(hs.length);

上述代码输出如下:

tex 复制代码
Set-Cookie: c1=a; path=/; domain=localhost
Set-Cookie: c2=b; path="/", c3=c; domain="localhost"
2

可以通过迭代器来迭代所有的响应头。

java 复制代码
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
response.addHeader("Set-Cookie", "c1=a; path=/; domain=localhost");
response.addHeader("Set-Cookie", "c2=b; path=\"/\", c3=c; domain=\"localhost\"");

HeaderIterator it = response.headerIterator("Set-Cookie");
while (it.hasNext()) {
    System.out.println(it.next());
}

上述代码输出如下:

tex 复制代码
Set-Cookie: c1=a; path=/; domain=localhost
Set-Cookie: c2=b; path="/", c3=c; domain="localhost"

有些响应头包含多个键值对,HttpClient 同样提供了相应 API 来迭代它们:

java 复制代码
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
response.addHeader("Set-Cookie", "c1=a; path=/; domain=localhost");
response.addHeader("Set-Cookie", "c2=b; path=\"/\", c3=c; domain=\"localhost\"");

HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator("Set-Cookie"));

while (it.hasNext()) {
    HeaderElement elem = it.nextElement(); 
    System.out.println(elem.getName() + " = " + elem.getValue());
    NameValuePair[] params = elem.getParameters();
    for (int i = 0; i < params.length; i++) {
        System.out.println(" " + params[i]);
    }
}

上述代码输出如下:

tex 复制代码
c1 = a
path=/
domain=localhost
c2 = b
path=/
c3 = c
domain=localhost

通过 HttpResponse#getEntity() 方法来获取响应中的实体。

java 复制代码
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/");
CloseableHttpResponse response = httpclient.execute(httpget);
try {
    HttpEntity entity = response.getEntity();
    if (entity != null) {
        InputStream instream = entity.getContent();
        try {
            // do something useful
        } finally {
            instream.close();
        }
    }
} finally {
    response.close();
}

HTTP 是基于请求响应的无状态协议,随着 HTTP 协议越来越受欢迎和采用,越来越多的系统开始将它用于它从未打算用于的应用程序,例如作为电子商务应用程序的传输。因此,对状态管理的支持成为一种必然。于是 Cookie 技术被提出。

Cookie 是 HTTP 请求的一个请求头,它本质上是一份存储在用户本地的文件,里面包含了每次请求中都需要传递的信息。在 HttpClient 中 Cookie 的抽象是 Cookie 接口。

Cookie 接口实现关系如下所示:

在最简单的形式中,HTTP Cookie 只是一个名称/值对。通常 HTTP Cookie 还包含许多属性,例如有效的域、指定此 Cookie 适用的源服务器上 URL 子集的路径,以及 Cookie 有效的最长时间。

下面时创建客户端 Cookie 对象的示例:

java 复制代码
BasicClientCookie cookie = new BasicClientCookie("name", "value");
// Set effective domain and path attributes
cookie.setDomain(".mycompany.com");
cookie.setPath("/");
// Set attributes exactly as sent by the server
cookie.setAttribute(ClientCookie.PATH_ATTR, "/");
cookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".mycompany.com");

持久化

java 复制代码
// Create a local instance of cookie store
CookieStore cookieStore = new BasicCookieStore();
// Populate cookies if needed
BasicClientCookie cookie = new BasicClientCookie("name", "value");
cookie.setDomain(".mycompany.com");
cookie.setPath("/");
cookieStore.addCookie(cookie);
// Set the store
CloseableHttpClient httpclient = HttpClients.custom()
        .setDefaultCookieStore(cookieStore)
        .build();

实例

pom.xml

xml 复制代码
<dependencies>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.3</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.28</version>
    </dependency>
</dependencies>

测试 GET 请求

java 复制代码
public static void main(String[] args) throws IOException {
        //1.打开浏览器
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //2.声明get请求
        HttpGet httpGet = new HttpGet("http://www.baidu.com/s?wd=java");
        //3.发送请求
        CloseableHttpResponse response = httpClient.execute(httpGet);
        //4.判断状态码
        if(response.getStatusLine().getStatusCode()==200){
            HttpEntity entity = response.getEntity();
           //使用工具类EntityUtils,从响应中取出实体表示的内容并转换成字符串
            String string = EntityUtils.toString(entity, "utf-8");
            System.out.println(string);
        }
        //5.关闭资源
        response.close();
        httpClient.close();
    }

测试 POST 请求

java 复制代码
public static void main(String[] args) throws IOException {
        //1.打开浏览器
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //2.声明get请求
        HttpPost httpPost = new HttpPost("https://www.oschina.net/");
        //3.开源中国为了安全,防止恶意攻击,在post请求中都限制了浏览器才能访问
        httpPost.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36");
        //4.判断状态码
        List<NameValuePair> parameters = new ArrayList<NameValuePair>(0);
        parameters.add(new BasicNameValuePair("scope", "project"));
        parameters.add(new BasicNameValuePair("q", "java"));

        UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters,"UTF-8");

        httpPost.setEntity(formEntity);

        //5.发送请求
        CloseableHttpResponse response = httpClient.execute(httpPost);

        if(response.getStatusLine().getStatusCode()==200){
            HttpEntity entity = response.getEntity();
            String string = EntityUtils.toString(entity, "utf-8");
            System.out.println(string);
        }
        //6.关闭资源
        response.close();
        httpClient.close();
    }

参考:

https://hc.apache.org/httpcomponents-client-4.5.x/quickstart.html

相关推荐
没书读了21 分钟前
ssm框架-spring-spring声明式事务
java·数据库·spring
小二·29 分钟前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic1 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
懒洋洋大魔王1 小时前
RocketMQ的使⽤
java·rocketmq·java-rocketmq
武子康1 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神2 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
qq_327342732 小时前
Java实现离线身份证号码OCR识别
java·开发语言
阿龟在奔跑3 小时前
引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例
java·jvm·安全·list
飞滕人生TYF3 小时前
m个数 生成n个数的所有组合 详解
java·递归
代码小鑫3 小时前
A043-基于Spring Boot的秒杀系统设计与实现
java·开发语言·数据库·spring boot·后端·spring·毕业设计