?? 簡介
??SpringBoot不僅繼承了Spring框架原有的優(yōu)秀特性,而且還通過簡化配置來進(jìn)一步簡化了Spring應(yīng)用的整個(gè)搭建和開發(fā)過程。在Spring-Boot項(xiàng)目開發(fā)中,存在著本模塊的代碼需要訪問外面模塊接口,或外部url鏈接的需求。
??調(diào)用外部接口是指在應(yīng)用程序中與其他系統(tǒng)、服務(wù)或服務(wù)端點(diǎn)進(jìn)行通信,以獲取數(shù)據(jù)或執(zhí)行某些操作。這種通信可以通過 HTTP、HTTPS、SOAP、gRPC 等協(xié)議來實(shí)現(xiàn)。
調(diào)用外部接口通常涉及以下幾個(gè)步驟:
-
創(chuàng)建請求:根據(jù)接口文檔或約定,構(gòu)造請求的 URL、請求方法(如 GET、POST、PUT、DELETE 等)、請求頭、請求參數(shù)等信息。
-
發(fā)送請求:使用合適的客戶端工具(如 RestTemplate、WebClient、Feign 等)發(fā)送請求。這些工具提供了便捷的 API 來發(fā)送請求并將響應(yīng)結(jié)果返回給你。
-
處理響應(yīng):根據(jù)接口的響應(yīng)格式(如 JSON、XML 等),解析響應(yīng)內(nèi)容并提取需要的數(shù)據(jù)。你可以使用解析庫(如 Jackson、Gson、JAXB 等)來處理響應(yīng)內(nèi)容。
-
錯(cuò)誤處理:在調(diào)用外部接口時(shí),可能會遇到各種錯(cuò)誤情況,如網(wǎng)絡(luò)連接失敗、接口返回錯(cuò)誤碼等。你需要適當(dāng)處理這些錯(cuò)誤情況,例如進(jìn)行重試、回退、記錄日志等操作。
在調(diào)用外部接口時(shí),還需要注意以下事項(xiàng):
-
接口安全性:如果接口需要身份驗(yàn)證或授權(quán),你需要提供相應(yīng)的憑據(jù)(如 API 密鑰、令牌)或配置安全設(shè)置,以確保請求能夠被正確處理。
-
異步調(diào)用和并發(fā)性:如果你的應(yīng)用程序需要高并發(fā)或異步處理,你可以考慮使用基于消息隊(duì)列、異步任務(wù)或多線程等技術(shù),在后臺進(jìn)行接口調(diào)用,以提高系統(tǒng)的性能和可伸縮性。
-
監(jiān)控和日志記錄:對于重要的接口調(diào)用,建議設(shè)置適當(dāng)?shù)谋O(jiān)控和日志記錄,以便及時(shí)發(fā)現(xiàn)問題并進(jìn)行故障排查。
總之,調(diào)用外部接口是實(shí)現(xiàn)應(yīng)用程序與其他系統(tǒng)集成的重要方式,它能夠使你的應(yīng)用程序獲取到外部數(shù)據(jù),實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)邏輯,并與其他系統(tǒng)進(jìn)行交互。選擇合適的調(diào)用方式和合理處理錯(cuò)誤情況,能夠保證接口調(diào)用的可靠性和性能。
?? 方案一:采用原生的httpClient請求
/**
1. 跨域請求工具類
*/
public class HttpClientUtils {
public static String doGet(String url, Map<String, String> param) {
// 創(chuàng)建Httpclient對象
CloseableHttpClient httpclient = HttpClients.createDefault();
String resultString = "";
CloseableHttpResponse response = null;
try {
// 創(chuàng)建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
// 創(chuàng)建http GET請求
HttpGet httpGet = new HttpGet(uri);
// 執(zhí)行請求
response = httpclient.execute(httpGet);
// 判斷返回狀態(tài)是否為200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doGet(String url) {
return doGet(url, null);
}
public static String doPost(String url, Map<String, String> param) {
// 創(chuàng)建Httpclient對象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 創(chuàng)建Http Post請求
HttpPost httpPost = new HttpPost(url);
// 創(chuàng)建參數(shù)列表
if (param != null) {
List<NameValuePair> paramList = new ArrayList<>();
for (String key : param.keySet()) {
paramList.add(new BasicNameValuePair(key, param.get(key)));
}
// 模擬表單
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
httpPost.setEntity(entity);
}
// 執(zhí)行http請求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doPost(String url) {
return doPost(url, null);
}
public static String doPostJson(String url, String json) {
// 創(chuàng)建Httpclient對象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 創(chuàng)建Http Post請求
HttpPost httpPost = new HttpPost(url);
// 創(chuàng)建請求內(nèi)容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 執(zhí)行http請求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
}
?? 方案二:采用原生的RestTemplate方法
??RestTemplate 是 Spring 框架提供的用于訪問 RESTful 服務(wù)的客戶端工具類。它封裝了常見的 HTTP 請求操作,提供了簡單易用的 API,這里主要介紹Get和Post方法的使用。
?? Get請求
??在 RestTemplate 中,getForEntity 方法有多個(gè)重載形式,可以根據(jù)需要選擇合適的方法進(jìn)行 GET 請求。提供了getForObject 、getForEntity兩種方式。
?? getForEntity
以下是 getForEntity
方法的三種形式:
1. getForEntity(String url, Class<T> responseType, Object... uriVariables);
2. getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables);
3. getForEntity(URI url, Class<T> responseType);
以下是對每個(gè)方法的說明和示例:
-
getForEntity(String url, Class<T> responseType, Object... uriVariables)
:
該方法提供了三個(gè)參數(shù),其中url為請求的地址,responseType為請求響應(yīng)body的包裝類型,urlVariables為url中的參數(shù)綁定- 此方法發(fā)送帶有路徑參數(shù)的 GET 請求,并以可變參數(shù)的形式傳遞路徑參數(shù)。
- 路徑參數(shù)將按順序替換 URL 中的占位符
{}
。
示例:
RestTemplate restTemplate = new RestTemplate(); ResponseEntity<User> response = restTemplate.getForEntity("http://example.com/api/users/{id}", User.class, 1); User user = response.getBody();
-
getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
:- 此方法發(fā)送帶有路徑參數(shù)的 GET 請求,并以鍵值對的形式傳遞路徑參數(shù)。
- 路徑參數(shù)通過鍵值對映射進(jìn)行替換。
示例:
RestTemplate restTemplate = new RestTemplate(); Map<String, Integer> uriVariables = new HashMap<>(); uriVariables.put("id", 1); ResponseEntity<User> response = restTemplate.getForEntity("http://example.com/api/users/{id}", User.class, uriVariables); User user = response.getBody();
-
getForEntity(URI url, Class<T> responseType)
:- 此方法發(fā)送 GET 請求,并通過
URI
對象來指定請求的完整 URL。
示例:
RestTemplate restTemplate = new RestTemplate(); URI url = new URI("http://example.com/api/users/1"); ResponseEntity<User> response = restTemplate.getForEntity(url, User.class); User user = response.getBody();
- 此方法發(fā)送 GET 請求,并通過
或者
RestTemplate restTemplate=new RestTemplate();
UriComponents uriComponents=UriComponentsBuilder.fromUriString("http://example.com/api/users/{id}")
.build()
.expand(1)
.encode();
URI uri=uriComponents.toUri();
ResponseEntity<User> response = restTemplate.getForEntity(uri, User.class);
User user = response.getBody();
?? getForObject
以下是 getForEntity
方法的三種形式:
1. getForObject(String url, Class<T> responseType, Object... uriVariables);
2. getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables);
3. getForObject(URI url, Class<T> responseType);
這段代碼是 RestTemplate
類中的 getForObject
方法的重寫實(shí)現(xiàn)。它用于發(fā)送 GET 請求,并返回一個(gè)指定類型的對象,而不是完整的響應(yīng)實(shí)體。
以下是對每個(gè)方法的說明和示例:
-
getForObject(String url, Class<T> responseType, Object... uriVariables)
:- 此方法發(fā)送帶有路徑參數(shù)的 GET 請求,并以可變參數(shù)的形式傳遞路徑參數(shù)。
- 路徑參數(shù)將按順序替換 URL 中的占位符
{}
。 - 最后,返回響應(yīng)體中轉(zhuǎn)換為指定類型的對象。
示例:
RestTemplate restTemplate = new RestTemplate(); User user = restTemplate.getForObject("http://example.com/api/users/{id}", User.class, 1);
-
getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
:- 此方法發(fā)送帶有路徑參數(shù)的 GET 請求,并以鍵值對的形式傳遞路徑參數(shù)。
- 路徑參數(shù)通過鍵值對映射進(jìn)行替換。
- 最后,返回響應(yīng)體中轉(zhuǎn)換為指定類型的對象。
示例:
RestTemplate restTemplate = new RestTemplate(); Map<String, Integer> uriVariables = new HashMap<>(); uriVariables.put("id", 1); User user = restTemplate.getForObject("http://example.com/api/users/{id}", User.class, uriVariables);
-
getForObject(URI url, Class<T> responseType)
:- 此方法發(fā)送 GET 請求,并通過
URI
對象來指定請求的完整 URL。 - 最后,返回響應(yīng)體中轉(zhuǎn)換為指定類型的對象。
示例:
RestTemplate restTemplate = new RestTemplate(); URI url = new URI("http://example.com/api/users/1"); User user = restTemplate.getForObject(url, User.class);
- 此方法發(fā)送 GET 請求,并通過
?? getForEntity和getForObject的聯(lián)系
getForObject
和 getForEntity
是 RestTemplate
類中用于發(fā)送 GET 請求并獲取響應(yīng)的兩個(gè)方法。它們在功能上有一些相似之處,但也有一些區(qū)別。
相同點(diǎn):
- 都用于發(fā)送 GET 請求,并接收服務(wù)器返回的響應(yīng)。
- 都支持傳遞 URL、路徑參數(shù)和查詢參數(shù)來構(gòu)建完整的請求 URL。
- 都可以指定響應(yīng)的期望類型,并進(jìn)行自動的類型轉(zhuǎn)換。
區(qū)別:
-
getForObject
方法返回的是服務(wù)器響應(yīng)體中的內(nèi)容,并將其轉(zhuǎn)換為指定類型的對象。這意味著你直接獲取到了響應(yīng)體的內(nèi)容。 -
getForEntity
方法返回的是一個(gè)ResponseEntity
對象,包含了完整的響應(yīng)信息,包括響應(yīng)頭、響應(yīng)狀態(tài)碼和響應(yīng)體??梢酝ㄟ^ResponseEntity
對象來獲取更多的響應(yīng)信息。
選擇使用哪個(gè)方法取決于你對響應(yīng)的需求:
- 如果你只需要獲得響應(yīng)體的內(nèi)容,并將其轉(zhuǎn)換為指定類型的對象,可以使用
getForObject
方法。這樣可以簡化代碼,僅關(guān)注響應(yīng)體的內(nèi)容。 - 如果你還需要獲取更多的響應(yīng)信息,例如響應(yīng)頭或狀態(tài)碼,或者需要對響應(yīng)進(jìn)行更細(xì)粒度的處理,那么可以使用
getForEntity
方法。它提供了更多的靈活性,可以訪問完整的響應(yīng)信息。
示例:
RestTemplate restTemplate = new RestTemplate();
// 使用 getForObject 方法
User user1 = restTemplate.getForObject("http://example.com/api/users/1", User.class);
// 使用 getForEntity 方法
ResponseEntity<User> responseEntity = restTemplate.getForEntity("http://example.com/api/users/1", User.class);
User user2 = responseEntity.getBody();
HttpStatus statusCode = responseEntity.getStatusCode();
HttpHeaders headers = responseEntity.getHeaders();
總之,getForObject
和 getForEntity
都是用于發(fā)送 GET 請求并獲取響應(yīng)的方法,選擇使用哪個(gè)方法取決于你對響應(yīng)的需求。
?? Post請求
Post請求提供有postForEntity
、postForObject
和postForLocation
三種方式,其中每種方式都有三種方法,下面介紹postForEntity
的使用方法。
?? postForEntity
以下是 postForEntity
方法的三種形式:
1. postForEntity(String url, @Nullable Object request,Class<T> responseType, Object... uriVariables);
2. postForEntity(String url, @Nullable Object request,Class<T> responseType, Map<String, ?> uriVariables);
3. postForEntity(URI url, @Nullable Object request, Class<T> responseType);
這段代碼是 RestTemplate
類中的 postForEntity
方法的重寫實(shí)現(xiàn)。它用于發(fā)送 POST 請求,并返回一個(gè)包含完整響應(yīng)信息的 ResponseEntity
對象,而不僅僅是響應(yīng)體內(nèi)容。
下面是對每個(gè)重寫方法的詳細(xì)說明和示例:
-
postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables)
:- 此方法發(fā)送帶有路徑參數(shù)的 POST 請求,并以可變參數(shù)的形式傳遞路徑參數(shù)。
-
request
參數(shù)用于發(fā)送 POST 請求時(shí)的請求體內(nèi)容。 - 最后,返回一個(gè)包含完整響應(yīng)信息的
ResponseEntity
對象,其中包括響應(yīng)頭、響應(yīng)狀態(tài)碼和響應(yīng)體。
示例:
RestTemplate restTemplate = new RestTemplate(); User userRequest = new User("John", "Doe"); ResponseEntity<User> responseEntity = restTemplate.postForEntity("http://example.com/api/users", userRequest, User.class, 1); User user = responseEntity.getBody(); HttpStatus statusCode = responseEntity.getStatusCode(); HttpHeaders headers = responseEntity.getHeaders();
-
postForEntity(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables)
:- 此方法發(fā)送帶有路徑參數(shù)的 POST 請求,并以鍵值對的形式傳遞路徑參數(shù)。
-
request
參數(shù)用于發(fā)送 POST 請求時(shí)的請求體內(nèi)容。 - 最后,返回一個(gè)包含完整響應(yīng)信息的
ResponseEntity
對象。
示例:
RestTemplate restTemplate = new RestTemplate(); User userRequest = new User("John", "Doe"); Map<String, Integer> uriVariables = new HashMap<>(); uriVariables.put("id", 1); ResponseEntity<User> responseEntity = restTemplate.postForEntity("http://example.com/api/users/{id}", userRequest, User.class, uriVariables); User user = responseEntity.getBody(); HttpStatus statusCode = responseEntity.getStatusCode(); HttpHeaders headers = responseEntity.getHeaders();
-
postForEntity(URI url, @Nullable Object request, Class<T> responseType)
:- 此方法發(fā)送 POST 請求,并通過
URI
對象來指定請求的完整 URL。 -
request
參數(shù)用于發(fā)送 POST 請求時(shí)的請求體內(nèi)容。 - 最后,返回一個(gè)包含完整響應(yīng)信息的
ResponseEntity
對象。
示例:
RestTemplate restTemplate = new RestTemplate(); User userRequest = new User("John", "Doe"); URI url = new URI("http://example.com/api/users"); ResponseEntity<User> responseEntity = restTemplate.postForEntity(url, userRequest, User.class); User user = responseEntity.getBody(); HttpStatus statusCode = responseEntity.getStatusCode(); HttpHeaders headers = responseEntity.getHeaders();
- 此方法發(fā)送 POST 請求,并通過
注
:
request
和uriVariables
是用于構(gòu)造 POST 請求的兩個(gè)不同的參數(shù),它們在不同的作用域中起作用。
request
參數(shù):
request
參數(shù)表示發(fā)送 POST 請求時(shí)的請求體內(nèi)容。- 它可以是任意類型的對象,根據(jù)實(shí)際的請求需求來決定具體的類型。通常情況下,
request
參數(shù)會作為請求體的內(nèi)容進(jìn)行發(fā)送。- 如果你的 POST 請求不需要請求體,可以將
request
參數(shù)設(shè)置為null
。
uriVariables
參數(shù):
uriVariables
參數(shù)表示可選的路徑參數(shù),用于替換 URL 中的占位符。- 它是一個(gè)可變參數(shù),可以傳遞多個(gè)參數(shù)值。參數(shù)值的順序必須與 URL 中占位符的順序一致。
- 在發(fā)送 POST 請求時(shí),將路徑參數(shù)與 URL 進(jìn)行替換,以獲得最終的請求 URL。
綜上所述,
request
和uriVariables
是兩個(gè)用于構(gòu)建 POST
請求不同參數(shù),分別代表請求體的內(nèi)容和路徑參數(shù)。需要根據(jù)具體的需求來使用它們。如果需要發(fā)送請求體,將內(nèi)容放在request
參數(shù)中;如果需要替換 URL 中的占位符,將參數(shù)值傳遞給uriVariables
參數(shù)。
?? postForObject
以下是 postForObject
方法的三種形式:
1. postForObject(String url, @Nullable Object request, Class<T> responseType,Object... uriVariables);
2. postForObject(String url, @Nullable Object request, Class<T> responseType,Map<String, ?> uriVariables);
3. postForObject(URI url, @Nullable Object request, Class<T> responseType);
這是 RestTemplate
類中關(guān)于 POST 請求的三個(gè) postForObject
方法的實(shí)現(xiàn)。下面將詳細(xì)解釋每個(gè)方法及其示例用法:
-
postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables)
- 通過傳遞 URL 字符串、請求體對象、響應(yīng)類型和路徑參數(shù)數(shù)組,發(fā)送一個(gè) POST 請求,并將響應(yīng)體轉(zhuǎn)換為指定的類型對象。
- 如果不需要發(fā)送請求體,可以將
request
參數(shù)設(shè)置為null
。 - 此方法使用占位符來替換 URL 中的路徑參數(shù)。
示例:
String url = "http://example.com/api/users/{id}"; User request = new User("John", "Doe"); Class<User> responseType = User.class; Object[] uriVariables = { 1 }; User user = restTemplate.postForObject(url, request, responseType, uriVariables);
-
postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables)
- 通過傳遞 URL 字符串、請求體對象、響應(yīng)類型和路徑參數(shù)映射,發(fā)送一個(gè) POST 請求,并將響應(yīng)體轉(zhuǎn)換為指定的類型對象。
- 如果不需要發(fā)送請求體,可以將
request
參數(shù)設(shè)置為null
。 - 此方法使用鍵-值對來替換 URL 中的路徑參數(shù)。
示例:
String url = "http://example.com/api/users/{id}"; User request = new User("John", "Doe"); Class<User> responseType = User.class; Map<String, Object> uriVariables = new HashMap<>(); uriVariables.put("id", 1); User user = restTemplate.postForObject(url, request, responseType, uriVariables);
-
postForObject(URI url, @Nullable Object request, Class<T> responseType)
- 通過傳遞完整的 URI 對象、請求體對象和響應(yīng)類型,發(fā)送一個(gè) POST 請求,并將響應(yīng)體轉(zhuǎn)換為指定的類型對象。
- 如果不需要發(fā)送請求體,可以將
request
參數(shù)設(shè)置為null
。 - 此方法不支持替換 URL 中的路徑參數(shù)。
示例:
URI url = new URI("http://example.com/api/users"); User request = new User("John", "Doe"); Class<User> responseType = User.class; User user = restTemplate.postForObject(url, request, responseType);
?? postForLocation
以下是 postForLocation
方法的三種形式:
1. postForLocation(String url, @Nullable Object request, Object... uriVariables);
2. postForLocation(String url, @Nullable Object request, Map<String, ?> uriVariables);
3. postForLocation(URI url, @Nullable Object request);
這是 RestTemplate
類中關(guān)于 POST 請求并獲取 Location 頭部信息的三個(gè) postForLocation
方法的實(shí)現(xiàn)。下面將詳細(xì)解釋每個(gè)方法及其示例用法:
-
postForLocation(String url, @Nullable Object request, Object... uriVariables)
- 通過傳遞 URL 字符串、請求體對象和路徑參數(shù)數(shù)組,發(fā)送一個(gè) POST 請求,并返回響應(yīng)頭部中的 Location 信息,作為一個(gè) URI 對象返回。
- 如果不需要發(fā)送請求體,可以將
request
參數(shù)設(shè)置為null
。 - 此方法使用占位符來替換 URL 中的路徑參數(shù)。
示例:
String url = "http://example.com/api/users"; User request = new User("John", "Doe"); Object[] uriVariables = { 1 }; URI location = restTemplate.postForLocation(url, request, uriVariables);
-
postForLocation(String url, @Nullable Object request, Map<String, ?> uriVariables)
- 通過傳遞 URL 字符串、請求體對象和路徑參數(shù)映射,發(fā)送一個(gè) POST 請求,并返回響應(yīng)頭部中的 Location 信息,作為一個(gè) URI 對象返回。
- 如果不需要發(fā)送請求體,可以將
request
參數(shù)設(shè)置為null
。 - 此方法使用鍵-值對來替換 URL 中的路徑參數(shù)。
示例:
String url = "http://example.com/api/users"; User request = new User("John", "Doe"); Map<String, Object> uriVariables = new HashMap<>(); uriVariables.put("id", 1); URI location = restTemplate.postForLocation(url, request, uriVariables);
-
postForLocation(URI url, @Nullable Object request)
- 通過傳遞完整的 URI 對象和請求體對象,發(fā)送一個(gè) POST 請求,并返回響應(yīng)頭部中的 Location 信息,作為一個(gè) URI 對象返回。
- 如果不需要發(fā)送請求體,可以將
request
參數(shù)設(shè)置為null
。 - 此方法不支持替換 URL 中的路徑參數(shù)。
示例:
URI url = new URI("http://example.com/api/users"); User request = new User("John", "Doe"); URI location = restTemplate.postForLocation(url, request);
?? postForEntity、postForObject和postForLocation的聯(lián)系
postForEntity
、postForObject
和 postForLocation
都是 RestTemplate
類中用于發(fā)送 POST 請求的方法,它們之間存在一些聯(lián)系和區(qū)別。
聯(lián)系:
- 參數(shù):這三個(gè)方法都接受相同的參數(shù):請求的 URL、請求體對象以及可選的路徑參數(shù)或路徑參數(shù)映射。
- HTTP 請求方法:這三個(gè)方法都使用 POST 方法發(fā)送請求。
區(qū)別:
-
返回值類型:
-
postForEntity
返回一個(gè)ResponseEntity
對象,包含完整的響應(yīng)信息,如響應(yīng)狀態(tài)碼、頭部信息和響應(yīng)體。 -
postForObject
返回一個(gè)指定的響應(yīng)體類型的對象,僅包含響應(yīng)體內(nèi)容。 -
postForLocation
僅返回響應(yīng)頭部中的 Location 信息作為一個(gè) URI 對象。
-
-
使用場景:
-
postForEntity
和postForObject
適用于需要處理完整響應(yīng)信息的情況,可以獲取響應(yīng)狀態(tài)碼、頭部信息和響應(yīng)體,并根據(jù)需要進(jìn)行處理。 -
postForLocation
適用于只關(guān)注響應(yīng)頭部中的 Location 信息的情況,常用于資源的創(chuàng)建和重定向場景。
-
總結(jié):
這三個(gè)方法都用于發(fā)送 POST 請求,根據(jù)需要返回不同的信息。如果需要完整的響應(yīng)信息,包括響應(yīng)狀態(tài)碼、頭部信息和響應(yīng)體,可以使用 postForEntity
;如果只需要響應(yīng)體內(nèi)容,可以使用 postForObject
;如果僅關(guān)注響應(yīng)頭部中的 Location 信息,可以使用 postForLocation
。
?? 方案三:使用Feign進(jìn)行消費(fèi)
Feign 是一個(gè)聲明式的、基于接口的 HTTP 客戶端,它簡化了使用 Spring Cloud 進(jìn)行遠(yuǎn)程服務(wù)調(diào)用的過程。通過 Feign,可以以聲明式的方式定義和調(diào)用遠(yuǎn)程服務(wù)接口,而無需手動編寫實(shí)現(xiàn)代碼。
在使用 Feign 進(jìn)行消費(fèi)時(shí),需要完成以下幾個(gè)步驟:
-
創(chuàng)建 Feign 客戶端接口:定義一個(gè)接口,使用
@FeignClient
注解指定服務(wù)名稱和服務(wù)地址。該接口中定義了需要調(diào)用的遠(yuǎn)程服務(wù)接口的方法及其相關(guān)信息,例如 HTTP 方法、URL 路徑、請求參數(shù)和請求體等。 -
啟用 Feign 客戶端:在 Spring Boot 應(yīng)用程序的啟動類或配置類上添加
@EnableFeignClients
注解,以啟用 Feign 客戶端功能。 -
使用 Feign 客戶端接口:通過注入 Feign 客戶端接口對象,即可使用該接口中定義的方法進(jìn)行遠(yuǎn)程服務(wù)調(diào)用。Feign 會根據(jù)接口定義自動實(shí)現(xiàn)具體的調(diào)用邏輯,并處理請求和響應(yīng)。
Feign 的工作原理如下:
- 根據(jù) Feign 客戶端接口的定義,在運(yùn)行時(shí)動態(tài)生成具體的代理類。
- 當(dāng)調(diào)用 Feign 客戶端接口的方法時(shí),代理類會負(fù)責(zé)根據(jù)方法的元數(shù)據(jù)(如 HTTP 方法、URL 路徑、請求參數(shù)等)組裝出一個(gè)完整的 HTTP 請求。
- 發(fā)送構(gòu)建好的 HTTP 請求到目標(biāo)服務(wù)端,進(jìn)行遠(yuǎn)程調(diào)用。
- 目標(biāo)服務(wù)端響應(yīng)請求后,將響應(yīng)結(jié)果返回給 Feign 客戶端。
- Feign 客戶端根據(jù)定義的返回類型,將響應(yīng)結(jié)果轉(zhuǎn)換為相應(yīng)的對象或數(shù)據(jù),并返回給調(diào)用方。
Feign 還具備以下特性:
- 內(nèi)置負(fù)載均衡:Feign 集成了 Ribbon 負(fù)載均衡器,可以在多個(gè)服務(wù)提供方之間自動進(jìn)行負(fù)載均衡,提高系統(tǒng)的可用性和性能。
- 自動服務(wù)發(fā)現(xiàn):Feign 可以與服務(wù)注冊中心(如 Eureka)集成,自動從服務(wù)注冊中心獲取服務(wù)地址,避免硬編碼服務(wù)地址。
- 可插拔的編解碼器:Feign 支持多種序列化和反序列化方式,如 JSON、XML 等,可以根據(jù)需求選擇適合的編解碼器。
- 客戶端日志記錄:Feign 具備日志記錄功能,可以方便地打印出請求和響應(yīng)的詳細(xì)信息,便于排查問題和監(jiān)控性能。
總而言之,F(xiàn)eign 提供了一種簡單且優(yōu)雅的方式來定義和調(diào)用遠(yuǎn)程服務(wù)接口,它屏蔽了底層的 HTTP 請求細(xì)節(jié),使得遠(yuǎn)程服務(wù)調(diào)用更加便捷和靈活。同時(shí),通過與 Spring Cloud 的集成,F(xiàn)eign 還可以享受到負(fù)載均衡、服務(wù)發(fā)現(xiàn)等分布式系統(tǒng)支持。
?? 具體實(shí)現(xiàn)
使用 Feign 進(jìn)行消費(fèi)時(shí),需要進(jìn)行以下步驟:
-
添加 Feign 依賴:在項(xiàng)目的構(gòu)建文件中添加 Feign 相關(guān)的依賴,例如 Maven 的 pom.xml 文件:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
-
啟用 Feign 客戶端:在 Spring Boot 應(yīng)用程序的啟動類或配置類上添加
@EnableFeignClients
注解,以啟用 Feign 客戶端功能。@SpringBootApplication @EnableFeignClients @ComponentScan(basePackages = {"com.definesys.mpaas", "com.xdap.*" ,"com.xdap.*"}) public class MobilecardApplication { public static void main(String[] args) { SpringApplication.run(MobilecardApplication.class, args); } }
-
創(chuàng)建 Feign 客戶端接口:創(chuàng)建一個(gè)接口,使用
@FeignClient
注解指定服務(wù)名稱和服務(wù)地址。定義需要調(diào)用的 HTTP 方法、URL 路徑、請求參數(shù)和請求體等信息。例如://此處name需要設(shè)置不為空,url需要在.properties中設(shè)置,也可直接寫url @FeignClient(name = "example-service",url = "${outSide.url}") public interface ExampleClient { @GetMapping("/api/users/{id}") User getUser(@PathVariable("id") Long id); @PostMapping("/api/users") User createUser(@RequestBody User user); }
-
調(diào)用 Feign 客戶端接口:通過注入 Feign 客戶端接口對象,即可使用其定義的方法進(jìn)行遠(yuǎn)程服務(wù)調(diào)用。例如:
@RestController public class ExampleController { private final ExampleClient exampleClient; public ExampleController(ExampleClient exampleClient) { this.exampleClient = exampleClient; } @GetMapping("/users/{id}") public User getUser(@PathVariable Long id) { return exampleClient.getUser(id); } @PostMapping("/users") public User createUser(@RequestBody User user) { return exampleClient.createUser(user); } }
-
配置 Feign 客戶端:可以通過配置文件來配置 Feign 客戶端的行為,例如設(shè)置連接超時(shí)時(shí)間、請求重試等。在
application.properties
或application.yml
文件中添加相關(guān)配置。
以上是使用 Feign 進(jìn)行消費(fèi)的基本步驟。Feign 可以根據(jù)接口定義自動生成符合服務(wù)提供方 API 規(guī)范的客戶端實(shí)現(xiàn),并且內(nèi)部集成了負(fù)載均衡和服務(wù)發(fā)現(xiàn)等功能,簡化了遠(yuǎn)程服務(wù)調(diào)用的過程。
?? 添加Header解決方法
在使用 Feign 進(jìn)行遠(yuǎn)程服務(wù)調(diào)用時(shí),可以通過添加 Header 來傳遞額外的請求信息。下面介紹兩種常見的方式來添加 Header。
-
使用
@RequestHeader
注解:在 Feign 客戶端接口的方法參數(shù)上使用@RequestHeader
注解,指定要添加的 Header 的名稱和值。例如:@GetMapping("/api/users/{id}") User getUser(@PathVariable("id") Long id, @RequestHeader("Authorization") String token);
在調(diào)用該方法時(shí),將會在請求頭中添加一個(gè)名為 “Authorization” 的 Header,其值為傳入的
token
參數(shù)的值。 -
使用
Interceptor
攔截器:可以自定義一個(gè) Interceptor 實(shí)現(xiàn)RequestInterceptor
接口,在apply()
方法中添加需要的 Header。例如:public class CustomHeaderInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { template.header("Authorization", "Bearer your_token"); } }
然后,在 Feign 客戶端接口上使用
@FeignClient
注解的configuration
屬性指定使用的攔截器類。例如:@FeignClient(name = "example-service", url = "http://example.com", configuration = CustomHeaderInterceptor.class) public interface ExampleClient { // ... }
這樣,在每次使用該 Feign 客戶端接口進(jìn)行遠(yuǎn)程調(diào)用時(shí),都會在請求頭中自動添加上述定義的 Header。
以上是兩種常見的添加 Header 的方法。根據(jù)實(shí)際需求和場景,可以選擇適合的方式來添加自定義的 Header 信息。
?? Spring Boot 調(diào)用外部接口的三種方式的聯(lián)系
Spring Boot 調(diào)用外部接口的方式有多種,常見的有以下三種方式:RestTemplate、Feign 和 WebClient。它們之間存在一些聯(lián)系和區(qū)別。
-
RestTemplate:
- RestTemplate 是 Spring Framework 提供的傳統(tǒng)的 HTTP 客戶端工具,在 Spring Boot 中也得到了支持。
- 通過 RestTemplate,可以發(fā)送 HTTP 請求并接收響應(yīng),支持同步調(diào)用。
- RestTemplate 具有廣泛的功能,可以處理各種請求和響應(yīng)內(nèi)容,支持自定義編解碼、攔截器等功能。
- RestTemplate 使用起來相對簡單,直接調(diào)用其方法即可,適用于簡單的接口調(diào)用場景。
-
Feign:
- Feign 是基于接口的聲明式的 HTTP 客戶端,是 Spring Cloud 提供的組件之一。
- Feign 在 Spring Boot 中通過
@FeignClient
注解定義和使用。 - 通過 Feign,可以以聲明式的方式定義遠(yuǎn)程服務(wù)接口,并且 Feign 會自動代理實(shí)現(xiàn)具體的調(diào)用邏輯,無需手動編寫實(shí)現(xiàn)代碼。
- Feign 集成了 Ribbon 負(fù)載均衡器和 Eureka 服務(wù)注冊中心,可以自動進(jìn)行負(fù)載均衡和服務(wù)發(fā)現(xiàn)。
- Feign 更加高級抽象和靈活,適用于需要更多功能和集成分布式系統(tǒng)環(huán)境的場景。
-
WebClient:
- WebClient 是 Spring WebFlux 提供的非阻塞的 HTTP 客戶端。
- WebClient 基于 Reactor 響應(yīng)式編程模型,能夠在異步非阻塞的情況下處理大量并發(fā)請求。
- WebClient 支持使用函數(shù)式編程風(fēng)格來定義請求和處理響應(yīng),可以使用 Mono 和 Flux 處理異步結(jié)果。
- WebClient 適用于高性能、高并發(fā)的場景,并且在 Spring Boot 2.x 中是推薦的方式。
這三種方式在實(shí)際使用中有一些聯(lián)系和區(qū)別:文章來源:http://www.zghlxwxcb.cn/news/detail-622898.html
- RestTemplate 是傳統(tǒng)的 HTTP 客戶端,使用較為簡單,適用于簡單的接口調(diào)用場景。
- Feign 是基于接口的聲明式客戶端,集成了負(fù)載均衡和服務(wù)發(fā)現(xiàn)等功能,適用于分布式系統(tǒng)下的服務(wù)調(diào)用。
- WebClient 是非阻塞的 HTTP 客戶端,支持異步、響應(yīng)式編程模型,適用于高并發(fā)、高性能的場景。
選擇使用哪種方式需要根據(jù)具體的需求和場景來決定。在 Spring Boot 中,可以根據(jù)項(xiàng)目的特點(diǎn)和要求,靈活選擇適合的方式進(jìn)行外部接口調(diào)用。文章來源地址http://www.zghlxwxcb.cn/news/detail-622898.html
到了這里,關(guān)于Spring Boot 中調(diào)用外部接口的 3 種方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!