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