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

相关推荐
字节流动1 小时前
Android Java 版本的 MSAA OpenGL ES 多重采样
android·java·opengles
呜呼~225142 小时前
前后端数据交互
java·vue.js·spring boot·前端框架·intellij-idea·交互·css3
飞的肖3 小时前
从测试服务器手动热部署到生产环境的实现
java·服务器·系统架构
周伯通*3 小时前
策略模式以及优化
java·前端·策略模式
两点王爷3 小时前
Java读取csv文件内容,保存到sqlite数据库中
java·数据库·sqlite·csv
问道飞鱼3 小时前
【Springboot知识】Springboot进阶-实现CAS完整流程
java·spring boot·后端·cas
抓哇小菜鸡3 小时前
WebSocket
java·websocket
single5943 小时前
【c++笔试强训】(第四十五篇)
java·开发语言·数据结构·c++·算法
Q_19284999063 小时前
基于Spring Boot的电影网站系统
java·spring boot·后端
老鑫安全培训4 小时前
从安全角度看 SEH 和 VEH
java·网络·安全·网络安全·系统安全·安全威胁分析