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

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

特點:
- HttpClient別名:HttpComponents
- HttpClient可以發(fā)送get、post、put、delete、…等請求
1.3、 HttpClient入門案例
導入maven坐標
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.4</version>
</dependency>
1.3.1、 發(fā)起Get請求
- 1創(chuàng)建一個客戶端 CloseableHttpClient
- 2創(chuàng)建一個get方法請求實例 HttpGet
- 3發(fā)送請求 execute
- 4獲取響應(yīng)的頭信息
- 5獲取響應(yīng)的主題內(nèi)容
- 6關(guān)閉響應(yīng)對象
使用HttpClient發(fā)起Get請求的案例代碼:
public class DoGET {
public static void main(String[] args) throws Exception {
// 創(chuàng)建Httpclient對象,相當于打開了瀏覽器
CloseableHttpClient httpclient = HttpClients.createDefault();
// 創(chuàng)建HttpGet請求,相當于在瀏覽器輸入地址
HttpGet httpGet = new HttpGet("http://www.baidu.com/");
CloseableHttpResponse response = null;
try {
// 執(zhí)行請求,相當于敲完地址后按下回車。獲取響應(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í)行日志:
請求頭:

響應(yīng)頭:

數(shù)據(jù):

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

public class DoGETParam {
public static void main(String[] args) throws Exception {
// 創(chuàng)建Httpclient對象
CloseableHttpClient httpclient = HttpClients.createDefault();
// 創(chuàng)建URI對象,并且設(shè)置請求參數(shù)
URI uri = new URIBuilder("http://www.baidu.com/s").setParameter("wd", "java").build();
// 創(chuàng)建http GET請求
HttpGet httpGet = new HttpGet(uri);
// HttpGet get = new HttpGet("http://www.baidu.com/s?wd=java");
CloseableHttpResponse response = null;
try {
// 執(zhí)行請求
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請求
/*
* 演示:使用HttpClient發(fā)起POST請求
*/
public class DoPOST {
public static void main(String[] args) throws Exception {
// 創(chuàng)建Httpclient對象
CloseableHttpClient httpclient = HttpClients.createDefault();
// 創(chuàng)建http POST請求
HttpPost httpPost = new HttpPost("http://www.oschina.net/");
// 把自己偽裝成瀏覽器。否則開源中國會攔截訪問
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í)行請求
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請求
/*
* 演示:使用HttpClient發(fā)起帶有參數(shù)的POST請求
*/
public class DoPOSTParam {
public static void main(String[] args) throws Exception {
// 創(chuàng)建Httpclient對象
CloseableHttpClient httpclient = HttpClients.createDefault();
// 創(chuàng)建http POST請求,訪問開源中國
HttpPost httpPost = new HttpPost("http://www.oschina.net/search");
// 根據(jù)開源中國的請求需要,設(shè)置post請求參數(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)造一個form表單式的實體
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);
// 將請求實體設(shè)置到httpPost對象中
httpPost.setEntity(formEntity);
CloseableHttpResponse response = null;
try {
// 執(zhí)行請求
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();
}
}
}
二、項目整合HttpClient—與SpringBoot整合
SpringBoot官方并沒有對HttpClient的啟動器。所以我們需要自己完成配置,還好,我們剛才在測試案例中已經(jīng)寫過了。
不過,SpringBoot雖然沒有提供啟動器,但是卻提供了一個統(tǒng)一的對Restful服務(wù)進行調(diào)用的模板類:RestTemplate,底層可以使用HttpClient來實現(xiàn)。有了這個我們就無需自己定義APIService了。
1、導入maven坐標
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、在項目中創(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;// 每個host的最大連接
private Integer connectTimeout;// 連接超時時間
private Integer connectionRequestTimeout;// 請求超時時間
private Integer socketTimeout;// 響應(yīng)超時時間
/**
* HttpClient連接池
* @return
*/
@Bean
public HttpClientConnectionManager httpClientConnectionManager() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(maxTotal);
connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
return connectionManager;
}
/**
* 注冊RequestConfig
* @return
*/
@Bean
public RequestConfig requestConfig() {
return RequestConfig.custom().setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout)
.build();
}
/**
* 注冊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來初始化一個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提供了多種便捷訪問遠程Http服務(wù)的方法,能夠大大提高客戶端的編寫效率。
之前的HTTP開發(fā)是用apache的HttpClient開發(fā),代碼復雜,還得操心資源回收等。代碼很復雜,冗余代碼多。
導入坐標:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、創(chuàng)建RestTemplate對象

第一步:創(chuàng)建RestTemplate類,在類中創(chuàng)建RestTemplate對象
/**
* Created by yxq on 2020/08/05.
* RestTemplate工具類,主要用來提供RestTemplate對象
*/
@Configuration//加上這個注解作用,可以被Spring掃描
public class RestTemplateConfig {
/**
* 創(chuàng)建RestTemplate對象,將RestTemplate對象的生命周期的管理交給Spring
* @return
*/
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
第二步:創(chuàng)建RestTempController,注入RestTemplate
/**
* Created by yxq on 2019/11/29.
* 本項目不連接數(shù)據(jù)庫,通過RestTemplate發(fā)出get、post、put、delete請求,請求admin-project項目中controller的方法
*
*
*/
@RestController
@RequestMapping("/rest")
public class RestTempController {
// 從Spring的容器中獲取restTemplate
@Autowired
private RestTemplate restTemplate;
}
3、get請求
第一步:在RestTempController中編寫代碼,發(fā)起get請求:
/**
* 發(fā)起get請求,請求admin-project
* http://localhost:8088/admin -->分頁查找
*/
@GetMapping
public ResponseEntity<String> findByPage(){
/**
* 第一個參數(shù):url
* 第二個參數(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());
}
測試結(jié)果:

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


5、post請求的中文亂碼bug
在RestTemplateConfig中編寫處理亂碼的問題:
/**
* Created by yxq on 2020/08/05.
* RestTemplate工具類,主要用來提供RestTemplate對象
*/
@Configuration//加上這個注解作用,可以被Spring掃描
public class RestTemplateConfig {
/**
* 創(chuàng)建RestTemplate對象,將RestTemplate對象的生命周期的管理交給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請求
第一步:在RestTempController中編寫方法,發(fā)送put請求
/**
* 修改數(shù)據(jù)
*
*/
@PutMapping
public ResponseEntity<String> updateAdmin(@RequestBody Admin admin){
// 第一個參數(shù):url
// 第二個參數(shù):對象,數(shù)據(jù)
restTemplate.put("http://localhost:8088/admin",admin);
return ResponseEntity.ok("修改成功");
}
7、delete請求
第一步:在RestTempController中編寫方法,發(fā)送delete請求
@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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot整合Swagger3生成接口文檔的示例代碼
Swagger 是一個 RESTful API 的開源框架,它的主要目的是幫助開發(fā)者設(shè)計、構(gòu)建、文檔化和測試 Web API,本文給大家介紹了SpringBoot整合Swagger3生成接口文檔的流程,并通過代碼講解的非常詳細,需要的朋友可以參考下2024-04-04
Java多線程使用阻塞隊列實現(xiàn)生產(chǎn)者消費者模型詳解
這篇文章主要介紹了Java多線程使用阻塞隊列實現(xiàn)生產(chǎn)者消費者模型詳解,主要講解阻塞隊列的特性、實際開發(fā)中常用的到的生產(chǎn)者消費者模型,以及生產(chǎn)者消費者模型解耦合、削峰填谷的好處,需要的朋友可以參考下2023-07-07
IntelliJ IDEA自定義代碼提示模板Live Templates的圖文教程
這篇文章主要介紹了IntelliJ IDEA自定義代碼提示模板Live Templates,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03

