Java HttpClient技術(shù)詳解
一、HttpClient
1.1、 前臺(tái)系統(tǒng)訪問后臺(tái)接口的方式
兩個(gè)系統(tǒng)間如何互相訪問?兩個(gè)tomcat上的項(xiàng)目如何互相訪問
采用HttpClient實(shí)現(xiàn)跨系統(tǒng)的接口調(diào)用。
1.2、 什么是HttpClient

官網(wǎng):http://hc.apache.org/index.html
現(xiàn)在也叫:HttpComponents

特點(diǎn):
- HttpClient別名:HttpComponents
- HttpClient可以發(fā)送get、post、put、delete、…等請(qǐng)求
1.3、 HttpClient入門案例
導(dǎo)入maven坐標(biāo)
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.4</version>
</dependency>
1.3.1、 發(fā)起Get請(qǐng)求
- 1創(chuàng)建一個(gè)客戶端 CloseableHttpClient
- 2創(chuàng)建一個(gè)get方法請(qǐng)求實(shí)例 HttpGet
- 3發(fā)送請(qǐng)求 execute
- 4獲取響應(yīng)的頭信息
- 5獲取響應(yīng)的主題內(nèi)容
- 6關(guān)閉響應(yīng)對(duì)象
使用HttpClient發(fā)起Get請(qǐng)求的案例代碼:
public class DoGET {
public static void main(String[] args) throws Exception {
// 創(chuàng)建Httpclient對(duì)象,相當(dāng)于打開了瀏覽器
CloseableHttpClient httpclient = HttpClients.createDefault();
// 創(chuàng)建HttpGet請(qǐng)求,相當(dāng)于在瀏覽器輸入地址
HttpGet httpGet = new HttpGet("http://www.baidu.com/");
CloseableHttpResponse response = null;
try {
// 執(zhí)行請(qǐng)求,相當(dāng)于敲完地址后按下回車。獲取響應(yīng)
response = httpclient.execute(httpGet);
// 判斷返回狀態(tài)是否為200
if (response.getStatusLine().getStatusCode() == 200) {
// 解析響應(yīng),獲取數(shù)據(jù)
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content);
}
} finally {
if (response != null) {
// 關(guān)閉資源
response.close();
}
// 關(guān)閉瀏覽器
httpclient.close();
}
}
}
執(zhí)行日志:
請(qǐng)求頭:

響應(yīng)頭:

數(shù)據(jù):

1.3.2、 帶參數(shù)的Get請(qǐng)求
- 1創(chuàng)建一個(gè)客戶端 CloseableHttpClient
- 2通過URIBuilder傳遞參數(shù)
- 3創(chuàng)建一個(gè)get方法請(qǐng)求實(shí)例 HttpGet
- 4發(fā)送請(qǐng)求 execute
- 5獲取響應(yīng)的頭信息
- 6獲取響應(yīng)的主題內(nèi)容
- 7關(guān)閉響應(yīng)對(duì)象
訪問網(wǎng)站的爬蟲協(xié)議:

public class DoGETParam {
public static void main(String[] args) throws Exception {
// 創(chuàng)建Httpclient對(duì)象
CloseableHttpClient httpclient = HttpClients.createDefault();
// 創(chuàng)建URI對(duì)象,并且設(shè)置請(qǐng)求參數(shù)
URI uri = new URIBuilder("http://www.baidu.com/s").setParameter("wd", "java").build();
// 創(chuàng)建http GET請(qǐng)求
HttpGet httpGet = new HttpGet(uri);
// HttpGet get = new HttpGet("http://www.baidu.com/s?wd=java");
CloseableHttpResponse response = null;
try {
// 執(zhí)行請(qǐng)求
response = httpclient.execute(httpGet);
// 判斷返回狀態(tài)是否為200
if (response.getStatusLine().getStatusCode() == 200) {
// 解析響應(yīng)數(shù)據(jù)
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content);
}
} finally {
if (response != null) {
response.close();
}
httpclient.close();
}
}
}
1.3.3、 發(fā)起POST請(qǐng)求
/*
* 演示:使用HttpClient發(fā)起POST請(qǐng)求
*/
public class DoPOST {
public static void main(String[] args) throws Exception {
// 創(chuàng)建Httpclient對(duì)象
CloseableHttpClient httpclient = HttpClients.createDefault();
// 創(chuàng)建http POST請(qǐng)求
HttpPost httpPost = new HttpPost("http://www.oschina.net/");
// 把自己偽裝成瀏覽器。否則開源中國會(huì)攔截訪問
httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
CloseableHttpResponse response = null;
try {
// 執(zhí)行請(qǐng)求
response = httpclient.execute(httpPost);
// 判斷返回狀態(tài)是否為200
if (response.getStatusLine().getStatusCode() == 200) {
// 解析響應(yīng)數(shù)據(jù)
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content);
}
} finally {
if (response != null) {
response.close();
}
// 關(guān)閉瀏覽器
httpclient.close();
}
}
}
1.3.4、 帶參數(shù)POST請(qǐng)求
/*
* 演示:使用HttpClient發(fā)起帶有參數(shù)的POST請(qǐng)求
*/
public class DoPOSTParam {
public static void main(String[] args) throws Exception {
// 創(chuàng)建Httpclient對(duì)象
CloseableHttpClient httpclient = HttpClients.createDefault();
// 創(chuàng)建http POST請(qǐng)求,訪問開源中國
HttpPost httpPost = new HttpPost("http://www.oschina.net/search");
// 根據(jù)開源中國的請(qǐng)求需要,設(shè)置post請(qǐng)求參數(shù)
List<NameValuePair> parameters = new ArrayList<NameValuePair>(0);
parameters.add(new BasicNameValuePair("scope", "project"));
parameters.add(new BasicNameValuePair("q", "java"));
parameters.add(new BasicNameValuePair("fromerr", "8bDnUWwC"));
// 構(gòu)造一個(gè)form表單式的實(shí)體
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);
// 將請(qǐng)求實(shí)體設(shè)置到httpPost對(duì)象中
httpPost.setEntity(formEntity);
CloseableHttpResponse response = null;
try {
// 執(zhí)行請(qǐng)求
response = httpclient.execute(httpPost);
// 判斷返回狀態(tài)是否為200
if (response.getStatusLine().getStatusCode() == 200) {
// 解析響應(yīng)體
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content);
}
} finally {
if (response != null) {
response.close();
}
// 關(guān)閉瀏覽器
httpclient.close();
}
}
}
二、項(xiàng)目整合HttpClient—與SpringBoot整合
SpringBoot官方并沒有對(duì)HttpClient的啟動(dòng)器。所以我們需要自己完成配置,還好,我們剛才在測(cè)試案例中已經(jīng)寫過了。
不過,SpringBoot雖然沒有提供啟動(dòng)器,但是卻提供了一個(gè)統(tǒng)一的對(duì)Restful服務(wù)進(jìn)行調(diào)用的模板類:RestTemplate,底層可以使用HttpClient來實(shí)現(xiàn)。有了這個(gè)我們就無需自己定義APIService了。
1、導(dǎo)入maven坐標(biāo)
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、在項(xiàng)目中創(chuàng)建HttpClientConfig類–類似util

3、在application.properties添加如下配置:
#The config for HttpClient http.maxTotal=300 http.defaultMaxPerRoute=50 http.connectTimeout=1000 http.connectionRequestTimeout=500 http.socketTimeout=5000 http.staleConnectionCheckEnabled=true
4、在類中編寫代碼
/**
* HttpClient的配置類
*
*/
@Configuration
@ConfigurationProperties(prefix = "http", ignoreUnknownFields = true)
public class HttpClientConfig {
private Integer maxTotal;// 最大連接
private Integer defaultMaxPerRoute;// 每個(gè)host的最大連接
private Integer connectTimeout;// 連接超時(shí)時(shí)間
private Integer connectionRequestTimeout;// 請(qǐng)求超時(shí)時(shí)間
private Integer socketTimeout;// 響應(yīng)超時(shí)時(shí)間
/**
* HttpClient連接池
* @return
*/
@Bean
public HttpClientConnectionManager httpClientConnectionManager() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(maxTotal);
connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
return connectionManager;
}
/**
* 注冊(cè)RequestConfig
* @return
*/
@Bean
public RequestConfig requestConfig() {
return RequestConfig.custom().setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout)
.build();
}
/**
* 注冊(cè)HttpClient
* @param manager
* @param config
* @return
*/
@Bean
public HttpClient httpClient(HttpClientConnectionManager manager, RequestConfig config) {
return HttpClientBuilder.create().setConnectionManager(manager).setDefaultRequestConfig(config)
.build();
}
/**
* 使用連接池管理連接
* @param httpClient
* @return
*/
@Bean
public ClientHttpRequestFactory requestFactory(HttpClient httpClient) {
return new HttpComponentsClientHttpRequestFactory(httpClient);
}
/**
* 使用HttpClient來初始化一個(gè)RestTemplate
* @param requestFactory
* @return
*/
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory) {
RestTemplate template = new RestTemplate(requestFactory);
List<HttpMessageConverter<?>> list = template.getMessageConverters();
for (HttpMessageConverter<?> mc : list) {
if (mc instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter) mc).setDefaultCharset(Charset.forName("UTF-8"));
}
}
return template;
}
public Integer getMaxTotal() {
return maxTotal;
}
public void setMaxTotal(Integer maxTotal) {
this.maxTotal = maxTotal;
}
public Integer getDefaultMaxPerRoute() {
return defaultMaxPerRoute;
}
public void setDefaultMaxPerRoute(Integer defaultMaxPerRoute) {
this.defaultMaxPerRoute = defaultMaxPerRoute;
}
public Integer getConnectTimeout() {
return connectTimeout;
}
public void setConnectTimeout(Integer connectTimeout) {
this.connectTimeout = connectTimeout;
}
public Integer getConnectionRequestTimeout() {
return connectionRequestTimeout;
}
public void setConnectionRequestTimeout(Integer connectionRequestTimeout) {
this.connectionRequestTimeout = connectionRequestTimeout;
}
public Integer getSocketTimeout() {
return socketTimeout;
}
public void setSocketTimeout(Integer socketTimeout) {
this.socketTimeout = socketTimeout;
}
}
三、RestTemplate使用詳解
1、概述:
RestTemplate是Spring提供的用于訪問Rest服務(wù)的客戶端,RestTemplate提供了多種便捷訪問遠(yuǎn)程Http服務(wù)的方法,能夠大大提高客戶端的編寫效率。
之前的HTTP開發(fā)是用apache的HttpClient開發(fā),代碼復(fù)雜,還得操心資源回收等。代碼很復(fù)雜,冗余代碼多。
導(dǎo)入坐標(biāo):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、創(chuàng)建RestTemplate對(duì)象

第一步:創(chuàng)建RestTemplate類,在類中創(chuàng)建RestTemplate對(duì)象
/**
* Created by yxq on 2020/08/05.
* RestTemplate工具類,主要用來提供RestTemplate對(duì)象
*/
@Configuration//加上這個(gè)注解作用,可以被Spring掃描
public class RestTemplateConfig {
/**
* 創(chuàng)建RestTemplate對(duì)象,將RestTemplate對(duì)象的生命周期的管理交給Spring
* @return
*/
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
第二步:創(chuàng)建RestTempController,注入RestTemplate
/**
* Created by yxq on 2019/11/29.
* 本項(xiàng)目不連接數(shù)據(jù)庫,通過RestTemplate發(fā)出get、post、put、delete請(qǐng)求,請(qǐng)求admin-project項(xiàng)目中controller的方法
*
*
*/
@RestController
@RequestMapping("/rest")
public class RestTempController {
// 從Spring的容器中獲取restTemplate
@Autowired
private RestTemplate restTemplate;
}
3、get請(qǐng)求
第一步:在RestTempController中編寫代碼,發(fā)起get請(qǐng)求:
/**
* 發(fā)起get請(qǐng)求,請(qǐng)求admin-project
* http://localhost:8088/admin -->分頁查找
*/
@GetMapping
public ResponseEntity<String> findByPage(){
/**
* 第一個(gè)參數(shù):url
* 第二個(gè)參數(shù):返回值類型
*/
ResponseEntity<String> entity = restTemplate.getForEntity("http://localhost:8088/admin?page=1&rows=3", String.class);
System.out.println("狀態(tài)碼:"+entity.getStatusCode());
System.out.println("響應(yīng)體"+entity.getBody());
return ResponseEntity.ok(entity.getBody());
}
測(cè)試結(jié)果:

4、post請(qǐng)求
第一步:創(chuàng)建實(shí)體類Admin
public class Admin {
/**
* 編號(hào)
*/
private Integer id;
/**
* 管理員名
*/
private String adminname;
/**
* 密碼
*/
private String password;
/**
* 郵箱
*/
private String email;
/**
* 手機(jī)號(hào)
*/
private String phone;
/**
* 狀態(tài),0禁用,1啟用
*/
private Integer state;
/**
* 時(shí)間
*/
private Date time;
/**
* 角色id
*/
private String rid;
// 省略getter和setter方法
}
第二步:在RestTempController中編寫方法,發(fā)送post請(qǐng)求
@PostMapping
public ResponseEntity<String> addAdmin(@RequestBody Admin admin){
/**
* 第一個(gè)參數(shù):url
* 第二個(gè)參數(shù):數(shù)據(jù)
* 第三個(gè)參數(shù):返回值類型
*/
ResponseEntity<String> entity = restTemplate.postForEntity("http://localhost:8088/admin", admin, String.class);
return entity;
}
第三步:采用postman測(cè)試


5、post請(qǐng)求的中文亂碼bug
在RestTemplateConfig中編寫處理亂碼的問題:
/**
* Created by yxq on 2020/08/05.
* RestTemplate工具類,主要用來提供RestTemplate對(duì)象
*/
@Configuration//加上這個(gè)注解作用,可以被Spring掃描
public class RestTemplateConfig {
/**
* 創(chuàng)建RestTemplate對(duì)象,將RestTemplate對(duì)象的生命周期的管理交給Spring
* @return
*/
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
// 設(shè)置中文亂碼問題方式一
restTemplate.getMessageConverters().add(1,new StringHttpMessageConverter(Charset.forName("UTF-8")));
// 設(shè)置中文亂碼問題方式二
// restTemplate.getMessageConverters().set(1,
// new StringHttpMessageConverter(StandardCharsets.UTF_8)); // 支持中文編碼
return restTemplate;
}
}
6、put請(qǐng)求
第一步:在RestTempController中編寫方法,發(fā)送put請(qǐng)求
/**
* 修改數(shù)據(jù)
*
*/
@PutMapping
public ResponseEntity<String> updateAdmin(@RequestBody Admin admin){
// 第一個(gè)參數(shù):url
// 第二個(gè)參數(shù):對(duì)象,數(shù)據(jù)
restTemplate.put("http://localhost:8088/admin",admin);
return ResponseEntity.ok("修改成功");
}
7、delete請(qǐng)求
第一步:在RestTempController中編寫方法,發(fā)送delete請(qǐng)求
@DeleteMapping("/{id}")
public ResponseEntity<String> deleteAdmin(@PathVariable("id") Integer id){
restTemplate.delete("http://localhost:8088/admin/"+id);
return ResponseEntity.ok("刪除成功");
}
到此這篇關(guān)于Java HttpClient技術(shù)詳解的文章就介紹到這了,更多相關(guān)Java HttpClient內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中優(yōu)先隊(duì)列PriorityQueue常用方法示例
這篇文章主要介紹了Java中優(yōu)先隊(duì)列PriorityQueue常用方法示例,PriorityQueue是一種特殊的隊(duì)列,滿足隊(duì)列的“隊(duì)尾進(jìn)、隊(duì)頭出”條件,但是每次插入或刪除元素后,都對(duì)隊(duì)列進(jìn)行調(diào)整,使得隊(duì)列始終構(gòu)成最小堆(或最大堆),需要的朋友可以參考下2023-09-09
基于Java編寫一個(gè)簡(jiǎn)單的風(fēng)控組件
這篇文章主要為大家詳細(xì)介紹了如何基于Java編寫一個(gè)簡(jiǎn)單的風(fēng)控組件,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定的幫助,需要的可以參考一下2022-12-12
SpringBoot使用郵箱發(fā)送驗(yàn)證碼實(shí)現(xiàn)注冊(cè)功能
這篇文章主要為大家詳細(xì)介紹了SpringBoot使用郵箱發(fā)送驗(yàn)證碼實(shí)現(xiàn)注冊(cè)功能實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02
JFrame中添加和設(shè)置JPanel的方法實(shí)例解析
這篇文章主要介紹了JFrame中添加和設(shè)置JPanel的方法實(shí)例解析,具有一定借鑒價(jià)值2018-01-01
Java+opencv3.2.0實(shí)現(xiàn)人臉檢測(cè)功能
這篇文章主要為大家詳細(xì)介紹了Java+opencv3.2.0實(shí)現(xiàn)人臉檢測(cè)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
SpringBoot快速過濾出一次請(qǐng)求的所有日志的示例代碼
在現(xiàn)網(wǎng)出現(xiàn)故障時(shí),我們經(jīng)常需要獲取一次請(qǐng)求流程里的所有日志進(jìn)行定位,本文給大家介紹了SpringBoot如何快速過濾出一次請(qǐng)求的所有日志,文中有相關(guān)的代碼和示例供大家參考,需要的朋友可以參考下2024-03-03
spring cloud oauth2 實(shí)現(xiàn)用戶認(rèn)證登錄的示例代碼
這篇文章主要介紹了spring cloud oauth2 實(shí)現(xiàn)用戶認(rèn)證登錄的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Java實(shí)現(xiàn)讀取html文本內(nèi)容并按照格式導(dǎo)出到excel中
這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)讀取html文本提取相應(yīng)內(nèi)容按照格式導(dǎo)出到excel中,文中的示例代碼講解詳細(xì),需要的可以參考下2024-02-02
深入淺出重構(gòu)Mybatis與Spring集成的SqlSessionFactoryBean(上)
通常來講,重構(gòu)是指不改變功能的情況下優(yōu)化代碼,但本文所說的重構(gòu)也包括了添加功能。這篇文章主要介紹了重構(gòu)Mybatis與Spring集成的SqlSessionFactoryBean(上)的相關(guān)資料,需要的朋友可以參考下2016-11-11

