Spring?Boot中調(diào)用外部接口的3種方式步驟
簡(jiǎn)介
SpringBoot不僅繼承了Spring框架原有的優(yōu)秀特性,而且還通過(guò)簡(jiǎn)化配置來(lái)進(jìn)一步簡(jiǎn)化了Spring應(yīng)用的整個(gè)搭建和開(kāi)發(fā)過(guò)程。在Spring-Boot項(xiàng)目開(kāi)發(fā)中,存在著本模塊的代碼需要訪(fǎng)問(wèn)外面模塊接口,或外部url鏈接的需求。
調(diào)用外部接口是指在應(yīng)用程序中與其他系統(tǒng)、服務(wù)或服務(wù)端點(diǎn)進(jìn)行通信,以獲取數(shù)據(jù)或執(zhí)行某些操作。這種通信可以通過(guò) HTTP、HTTPS、SOAP、gRPC 等協(xié)議來(lái)實(shí)現(xiàn)。
調(diào)用外部接口通常涉及以下幾個(gè)步驟:
創(chuàng)建請(qǐng)求:根據(jù)接口文檔或約定,構(gòu)造請(qǐng)求的 URL、請(qǐng)求方法(如 GET、POST、PUT、DELETE 等)、請(qǐng)求頭、請(qǐng)求參數(shù)等信息。
發(fā)送請(qǐng)求:使用合適的客戶(hù)端工具(如 RestTemplate、WebClient、Feign 等)發(fā)送請(qǐng)求。這些工具提供了便捷的 API 來(lái)發(fā)送請(qǐng)求并將響應(yīng)結(jié)果返回給你。
處理響應(yīng):根據(jù)接口的響應(yīng)格式(如 JSON、XML 等),解析響應(yīng)內(nèi)容并提取需要的數(shù)據(jù)。你可以使用解析庫(kù)(如 Jackson、Gson、JAXB 等)來(lái)處理響應(yīng)內(nèi)容。
錯(cuò)誤處理:在調(diào)用外部接口時(shí),可能會(huì)遇到各種錯(cuò)誤情況,如網(wǎng)絡(luò)連接失敗、接口返回錯(cuò)誤碼等。你需要適當(dāng)處理這些錯(cuò)誤情況,例如進(jìn)行重試、回退、記錄日志等操作。
在調(diào)用外部接口時(shí),還需要注意以下事項(xiàng):
接口安全性:如果接口需要身份驗(yàn)證或授權(quán),你需要提供相應(yīng)的憑據(jù)(如 API 密鑰、令牌)或配置安全設(shè)置,以確保請(qǐng)求能夠被正確處理。
異步調(diào)用和并發(fā)性:如果你的應(yīng)用程序需要高并發(fā)或異步處理,你可以考慮使用基于消息隊(duì)列、異步任務(wù)或多線(xiàn)程等技術(shù),在后臺(tái)進(jìn)行接口調(diào)用,以提高系統(tǒng)的性能和可伸縮性。
監(jiān)控和日志記錄:對(duì)于重要的接口調(diào)用,建議設(shè)置適當(dāng)?shù)谋O(jiān)控和日志記錄,以便及時(shí)發(fā)現(xiàn)問(wè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請(qǐng)求
/** 1. 跨域請(qǐng)求工具類(lèi) */ public class HttpClientUtils { public static String doGet(String url, Map<String, String> param) { // 創(chuàng)建Httpclient對(duì)象 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請(qǐng)求 HttpGet httpGet = new HttpGet(uri); // 執(zhí)行請(qǐng)求 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對(duì)象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 創(chuàng)建Http Post請(qǐng)求 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請(qǐng)求 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對(duì)象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { // 創(chuàng)建Http Post請(qǐng)求 HttpPost httpPost = new HttpPost(url); // 創(chuàng)建請(qǐng)求內(nèi)容 StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); httpPost.setEntity(entity); // 執(zhí)行http請(qǐng)求 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 框架提供的用于訪(fǎng)問(wèn) RESTful 服務(wù)的客戶(hù)端工具類(lèi)。它封裝了常見(jiàn)的 HTTP 請(qǐng)求操作,提供了簡(jiǎn)單易用的 API,這里主要介紹Get和Post方法的使用。
Get請(qǐng)求
在 RestTemplate 中,getForEntity 方法有多個(gè)重載形式,可以根據(jù)需要選擇合適的方法進(jìn)行 GET 請(qǐng)求。提供了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);
以下是對(duì)每個(gè)方法的說(shuō)明和示例:
getForEntity(String url, Class<T> responseType, Object... uriVariables)
:
該方法提供了三個(gè)參數(shù),其中url為請(qǐng)求的地址,responseType為請(qǐng)求響應(yīng)body的包裝類(lèi)型,urlVariables為url中的參數(shù)綁定- 此方法發(fā)送帶有路徑參數(shù)的 GET 請(qǐng)求,并以可變參數(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 請(qǐng)求,并以鍵值對(duì)的形式傳遞路徑參數(shù)。
- 路徑參數(shù)通過(guò)鍵值對(duì)映射進(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 請(qǐng)求,并通過(guò)
URI
對(duì)象來(lái)指定請(qǐng)求的完整 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 請(qǐng)求,并通過(guò)
或者
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
類(lèi)中的 getForObject
方法的重寫(xiě)實(shí)現(xiàn)。它用于發(fā)送 GET 請(qǐng)求,并返回一個(gè)指定類(lèi)型的對(duì)象,而不是完整的響應(yīng)實(shí)體。
以下是對(duì)每個(gè)方法的說(shuō)明和示例:
getForObject(String url, Class<T> responseType, Object... uriVariables)
:- 此方法發(fā)送帶有路徑參數(shù)的 GET 請(qǐng)求,并以可變參數(shù)的形式傳遞路徑參數(shù)。
- 路徑參數(shù)將按順序替換 URL 中的占位符
{}
。 - 最后,返回響應(yīng)體中轉(zhuǎn)換為指定類(lèi)型的對(duì)象。
示例:
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 請(qǐng)求,并以鍵值對(duì)的形式傳遞路徑參數(shù)。
- 路徑參數(shù)通過(guò)鍵值對(duì)映射進(jìn)行替換。
- 最后,返回響應(yīng)體中轉(zhuǎn)換為指定類(lèi)型的對(duì)象。
示例:
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 請(qǐng)求,并通過(guò)
URI
對(duì)象來(lái)指定請(qǐng)求的完整 URL。 - 最后,返回響應(yīng)體中轉(zhuǎn)換為指定類(lèi)型的對(duì)象。
示例:
RestTemplate restTemplate = new RestTemplate(); URI url = new URI("http://example.com/api/users/1"); User user = restTemplate.getForObject(url, User.class);
- 此方法發(fā)送 GET 請(qǐng)求,并通過(guò)
getForEntity和getForObject的聯(lián)系
getForObject
和 getForEntity
是 RestTemplate
類(lèi)中用于發(fā)送 GET 請(qǐng)求并獲取響應(yīng)的兩個(gè)方法。它們?cè)诠δ苌嫌幸恍┫嗨浦?,但也有一些區(qū)別。
相同點(diǎn):
- 都用于發(fā)送 GET 請(qǐng)求,并接收服務(wù)器返回的響應(yīng)。
- 都支持傳遞 URL、路徑參數(shù)和查詢(xún)參數(shù)來(lái)構(gòu)建完整的請(qǐng)求 URL。
- 都可以指定響應(yīng)的期望類(lèi)型,并進(jìn)行自動(dòng)的類(lèi)型轉(zhuǎn)換。
區(qū)別:
getForObject
方法返回的是服務(wù)器響應(yīng)體中的內(nèi)容,并將其轉(zhuǎn)換為指定類(lèi)型的對(duì)象。這意味著你直接獲取到了響應(yīng)體的內(nèi)容。getForEntity
方法返回的是一個(gè)ResponseEntity
對(duì)象,包含了完整的響應(yīng)信息,包括響應(yīng)頭、響應(yīng)狀態(tài)碼和響應(yīng)體。可以通過(guò)ResponseEntity
對(duì)象來(lái)獲取更多的響應(yīng)信息。
選擇使用哪個(gè)方法取決于你對(duì)響應(yīng)的需求:
- 如果你只需要獲得響應(yīng)體的內(nèi)容,并將其轉(zhuǎn)換為指定類(lèi)型的對(duì)象,可以使用
getForObject
方法。這樣可以簡(jiǎn)化代碼,僅關(guān)注響應(yīng)體的內(nèi)容。 - 如果你還需要獲取更多的響應(yīng)信息,例如響應(yīng)頭或狀態(tài)碼,或者需要對(duì)響應(yīng)進(jìn)行更細(xì)粒度的處理,那么可以使用
getForEntity
方法。它提供了更多的靈活性,可以訪(fǎng)問(wèn)完整的響應(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 請(qǐng)求并獲取響應(yīng)的方法,選擇使用哪個(gè)方法取決于你對(duì)響應(yīng)的需求。
Post請(qǐng)求
Post請(qǐng)求提供有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
類(lèi)中的 postForEntity
方法的重寫(xiě)實(shí)現(xiàn)。它用于發(fā)送 POST 請(qǐng)求,并返回一個(gè)包含完整響應(yīng)信息的 ResponseEntity
對(duì)象,而不僅僅是響應(yīng)體內(nèi)容。
下面是對(duì)每個(gè)重寫(xiě)方法的詳細(xì)說(shuō)明和示例:
postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables)
:- 此方法發(fā)送帶有路徑參數(shù)的 POST 請(qǐng)求,并以可變參數(shù)的形式傳遞路徑參數(shù)。
request
參數(shù)用于發(fā)送 POST 請(qǐng)求時(shí)的請(qǐng)求體內(nèi)容。- 最后,返回一個(gè)包含完整響應(yīng)信息的
ResponseEntity
對(duì)象,其中包括響應(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 請(qǐng)求,并以鍵值對(duì)的形式傳遞路徑參數(shù)。
request
參數(shù)用于發(fā)送 POST 請(qǐng)求時(shí)的請(qǐng)求體內(nèi)容。- 最后,返回一個(gè)包含完整響應(yīng)信息的
ResponseEntity
對(duì)象。
示例:
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 請(qǐng)求,并通過(guò)
URI
對(duì)象來(lái)指定請(qǐng)求的完整 URL。 request
參數(shù)用于發(fā)送 POST 請(qǐng)求時(shí)的請(qǐng)求體內(nèi)容。- 最后,返回一個(gè)包含完整響應(yīng)信息的
ResponseEntity
對(duì)象。
示例:
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 請(qǐng)求,并通過(guò)
注
:
request
和uriVariables
是用于構(gòu)造 POST 請(qǐng)求的兩個(gè)不同的參數(shù),它們?cè)诓煌淖饔糜蛑衅鹱饔谩?/p>
request
參數(shù):
request
參數(shù)表示發(fā)送 POST 請(qǐng)求時(shí)的請(qǐng)求體內(nèi)容。- 它可以是任意類(lèi)型的對(duì)象,根據(jù)實(shí)際的請(qǐng)求需求來(lái)決定具體的類(lèi)型。通常情況下,
request
參數(shù)會(huì)作為請(qǐng)求體的內(nèi)容進(jìn)行發(fā)送。- 如果你的 POST 請(qǐng)求不需要請(qǐng)求體,可以將
request
參數(shù)設(shè)置為null
。
uriVariables
參數(shù):
uriVariables
參數(shù)表示可選的路徑參數(shù),用于替換 URL 中的占位符。- 它是一個(gè)可變參數(shù),可以傳遞多個(gè)參數(shù)值。參數(shù)值的順序必須與 URL 中占位符的順序一致。
- 在發(fā)送 POST 請(qǐng)求時(shí),將路徑參數(shù)與 URL 進(jìn)行替換,以獲得最終的請(qǐng)求 URL。
綜上所述,
request
和uriVariables
是兩個(gè)用于構(gòu)建 POST
請(qǐng)求不同參數(shù),分別代表請(qǐng)求體的內(nèi)容和路徑參數(shù)。需要根據(jù)具體的需求來(lái)使用它們。如果需要發(fā)送請(qǐng)求體,將內(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
類(lèi)中關(guān)于 POST 請(qǐng)求的三個(gè) postForObject
方法的實(shí)現(xiàn)。下面將詳細(xì)解釋每個(gè)方法及其示例用法:
postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables)
- 通過(guò)傳遞 URL 字符串、請(qǐng)求體對(duì)象、響應(yīng)類(lèi)型和路徑參數(shù)數(shù)組,發(fā)送一個(gè) POST 請(qǐng)求,并將響應(yīng)體轉(zhuǎn)換為指定的類(lèi)型對(duì)象。
- 如果不需要發(fā)送請(qǐng)求體,可以將
request
參數(shù)設(shè)置為null
。 - 此方法使用占位符來(lái)替換 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)
- 通過(guò)傳遞 URL 字符串、請(qǐng)求體對(duì)象、響應(yīng)類(lèi)型和路徑參數(shù)映射,發(fā)送一個(gè) POST 請(qǐng)求,并將響應(yīng)體轉(zhuǎn)換為指定的類(lèi)型對(duì)象。
- 如果不需要發(fā)送請(qǐng)求體,可以將
request
參數(shù)設(shè)置為null
。 - 此方法使用鍵-值對(duì)來(lái)替換 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)
- 通過(guò)傳遞完整的 URI 對(duì)象、請(qǐng)求體對(duì)象和響應(yīng)類(lèi)型,發(fā)送一個(gè) POST 請(qǐng)求,并將響應(yīng)體轉(zhuǎn)換為指定的類(lèi)型對(duì)象。
- 如果不需要發(fā)送請(qǐng)求體,可以將
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
類(lèi)中關(guān)于 POST 請(qǐng)求并獲取 Location 頭部信息的三個(gè) postForLocation
方法的實(shí)現(xiàn)。下面將詳細(xì)解釋每個(gè)方法及其示例用法:
postForLocation(String url, @Nullable Object request, Object... uriVariables)
- 通過(guò)傳遞 URL 字符串、請(qǐng)求體對(duì)象和路徑參數(shù)數(shù)組,發(fā)送一個(gè) POST 請(qǐng)求,并返回響應(yīng)頭部中的 Location 信息,作為一個(gè) URI 對(duì)象返回。
- 如果不需要發(fā)送請(qǐng)求體,可以將
request
參數(shù)設(shè)置為null
。 - 此方法使用占位符來(lái)替換 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)
- 通過(guò)傳遞 URL 字符串、請(qǐng)求體對(duì)象和路徑參數(shù)映射,發(fā)送一個(gè) POST 請(qǐng)求,并返回響應(yīng)頭部中的 Location 信息,作為一個(gè) URI 對(duì)象返回。
- 如果不需要發(fā)送請(qǐng)求體,可以將
request
參數(shù)設(shè)置為null
。 - 此方法使用鍵-值對(duì)來(lái)替換 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)
- 通過(guò)傳遞完整的 URI 對(duì)象和請(qǐng)求體對(duì)象,發(fā)送一個(gè) POST 請(qǐng)求,并返回響應(yīng)頭部中的 Location 信息,作為一個(gè) URI 對(duì)象返回。
- 如果不需要發(fā)送請(qǐng)求體,可以將
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
類(lèi)中用于發(fā)送 POST 請(qǐng)求的方法,它們之間存在一些聯(lián)系和區(qū)別。
聯(lián)系:
- 參數(shù):這三個(gè)方法都接受相同的參數(shù):請(qǐng)求的 URL、請(qǐng)求體對(duì)象以及可選的路徑參數(shù)或路徑參數(shù)映射。
- HTTP 請(qǐng)求方法:這三個(gè)方法都使用 POST 方法發(fā)送請(qǐng)求。
區(qū)別:
返回值類(lèi)型:
postForEntity
返回一個(gè)ResponseEntity
對(duì)象,包含完整的響應(yīng)信息,如響應(yīng)狀態(tài)碼、頭部信息和響應(yīng)體。postForObject
返回一個(gè)指定的響應(yīng)體類(lèi)型的對(duì)象,僅包含響應(yīng)體內(nèi)容。postForLocation
僅返回響應(yīng)頭部中的 Location 信息作為一個(gè) URI 對(duì)象。
使用場(chǎng)景:
postForEntity
和postForObject
適用于需要處理完整響應(yīng)信息的情況,可以獲取響應(yīng)狀態(tài)碼、頭部信息和響應(yīng)體,并根據(jù)需要進(jìn)行處理。postForLocation
適用于只關(guān)注響應(yīng)頭部中的 Location 信息的情況,常用于資源的創(chuàng)建和重定向場(chǎng)景。
總結(jié):
這三個(gè)方法都用于發(fā)送 POST 請(qǐng)求,根據(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 客戶(hù)端,它簡(jiǎn)化了使用 Spring Cloud 進(jìn)行遠(yuǎn)程服務(wù)調(diào)用的過(guò)程。通過(guò) Feign,可以以聲明式的方式定義和調(diào)用遠(yuǎn)程服務(wù)接口,而無(wú)需手動(dòng)編寫(xiě)實(shí)現(xiàn)代碼。
在使用 Feign 進(jìn)行消費(fèi)時(shí),需要完成以下幾個(gè)步驟:
創(chuàng)建 Feign 客戶(hù)端接口:定義一個(gè)接口,使用
@FeignClient
注解指定服務(wù)名稱(chēng)和服務(wù)地址。該接口中定義了需要調(diào)用的遠(yuǎn)程服務(wù)接口的方法及其相關(guān)信息,例如 HTTP 方法、URL 路徑、請(qǐng)求參數(shù)和請(qǐng)求體等。啟用 Feign 客戶(hù)端:在 Spring Boot 應(yīng)用程序的啟動(dòng)類(lèi)或配置類(lèi)上添加
@EnableFeignClients
注解,以啟用 Feign 客戶(hù)端功能。使用 Feign 客戶(hù)端接口:通過(guò)注入 Feign 客戶(hù)端接口對(duì)象,即可使用該接口中定義的方法進(jìn)行遠(yuǎn)程服務(wù)調(diào)用。Feign 會(huì)根據(jù)接口定義自動(dòng)實(shí)現(xiàn)具體的調(diào)用邏輯,并處理請(qǐng)求和響應(yīng)。
Feign 的工作原理如下:
- 根據(jù) Feign 客戶(hù)端接口的定義,在運(yùn)行時(shí)動(dòng)態(tài)生成具體的代理類(lèi)。
- 當(dāng)調(diào)用 Feign 客戶(hù)端接口的方法時(shí),代理類(lèi)會(huì)負(fù)責(zé)根據(jù)方法的元數(shù)據(jù)(如 HTTP 方法、URL 路徑、請(qǐng)求參數(shù)等)組裝出一個(gè)完整的 HTTP 請(qǐng)求。
- 發(fā)送構(gòu)建好的 HTTP 請(qǐng)求到目標(biāo)服務(wù)端,進(jìn)行遠(yuǎn)程調(diào)用。
- 目標(biāo)服務(wù)端響應(yīng)請(qǐng)求后,將響應(yīng)結(jié)果返回給 Feign 客戶(hù)端。
- Feign 客戶(hù)端根據(jù)定義的返回類(lèi)型,將響應(yīng)結(jié)果轉(zhuǎn)換為相應(yīng)的對(duì)象或數(shù)據(jù),并返回給調(diào)用方。
Feign 還具備以下特性:
- 內(nèi)置負(fù)載均衡:Feign 集成了 Ribbon 負(fù)載均衡器,可以在多個(gè)服務(wù)提供方之間自動(dòng)進(jìn)行負(fù)載均衡,提高系統(tǒng)的可用性和性能。
- 自動(dòng)服務(wù)發(fā)現(xiàn):Feign 可以與服務(wù)注冊(cè)中心(如 Eureka)集成,自動(dòng)從服務(wù)注冊(cè)中心獲取服務(wù)地址,避免硬編碼服務(wù)地址。
- 可插拔的編解碼器:Feign 支持多種序列化和反序列化方式,如 JSON、XML 等,可以根據(jù)需求選擇適合的編解碼器。
- 客戶(hù)端日志記錄:Feign 具備日志記錄功能,可以方便地打印出請(qǐng)求和響應(yīng)的詳細(xì)信息,便于排查問(wèn)題和監(jiān)控性能。
總而言之,F(xiàn)eign 提供了一種簡(jiǎn)單且優(yōu)雅的方式來(lái)定義和調(diào)用遠(yuǎn)程服務(wù)接口,它屏蔽了底層的 HTTP 請(qǐng)求細(xì)節(jié),使得遠(yuǎn)程服務(wù)調(diào)用更加便捷和靈活。同時(shí),通過(guò)與 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 依賴(lài):在項(xiàng)目的構(gòu)建文件中添加 Feign 相關(guān)的依賴(lài),例如 Maven 的 pom.xml 文件:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
啟用 Feign 客戶(hù)端:在 Spring Boot 應(yīng)用程序的啟動(dòng)類(lèi)或配置類(lèi)上添加
@EnableFeignClients
注解,以啟用 Feign 客戶(hù)端功能。@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 客戶(hù)端接口:創(chuàng)建一個(gè)接口,使用
@FeignClient
注解指定服務(wù)名稱(chēng)和服務(wù)地址。定義需要調(diào)用的 HTTP 方法、URL 路徑、請(qǐng)求參數(shù)和請(qǐng)求體等信息。例如://此處name需要設(shè)置不為空,url需要在.properties中設(shè)置,也可直接寫(xiě)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 客戶(hù)端接口:通過(guò)注入 Feign 客戶(hù)端接口對(duì)象,即可使用其定義的方法進(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 客戶(hù)端:可以通過(guò)配置文件來(lái)配置 Feign 客戶(hù)端的行為,例如設(shè)置連接超時(shí)時(shí)間、請(qǐng)求重試等。在
application.properties
或application.yml
文件中添加相關(guān)配置。
以上是使用 Feign 進(jìn)行消費(fèi)的基本步驟。Feign 可以根據(jù)接口定義自動(dòng)生成符合服務(wù)提供方 API 規(guī)范的客戶(hù)端實(shí)現(xiàn),并且內(nèi)部集成了負(fù)載均衡和服務(wù)發(fā)現(xiàn)等功能,簡(jiǎn)化了遠(yuǎn)程服務(wù)調(diào)用的過(guò)程。
添加Header解決方法
在使用 Feign 進(jìn)行遠(yuǎn)程服務(wù)調(diào)用時(shí),可以通過(guò)添加 Header 來(lái)傳遞額外的請(qǐng)求信息。下面介紹兩種常見(jiàn)的方式來(lái)添加 Header。
使用
@RequestHeader
注解:在 Feign 客戶(hù)端接口的方法參數(shù)上使用@RequestHeader
注解,指定要添加的 Header 的名稱(chēng)和值。例如:@GetMapping("/api/users/{id}") User getUser(@PathVariable("id") Long id, @RequestHeader("Authorization") String token);
在調(diào)用該方法時(shí),將會(huì)在請(qǐng)求頭中添加一個(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 客戶(hù)端接口上使用
@FeignClient
注解的configuration
屬性指定使用的攔截器類(lèi)。例如:@FeignClient(name = "example-service", url = "http://example.com", configuration = CustomHeaderInterceptor.class) public interface ExampleClient { // ... }
這樣,在每次使用該 Feign 客戶(hù)端接口進(jìn)行遠(yuǎn)程調(diào)用時(shí),都會(huì)在請(qǐng)求頭中自動(dòng)添加上述定義的 Header。
以上是兩種常見(jiàn)的添加 Header 的方法。根據(jù)實(shí)際需求和場(chǎng)景,可以選擇適合的方式來(lái)添加自定義的 Header 信息。
Spring Boot 調(diào)用外部接口的三種方式的聯(lián)系
Spring Boot 調(diào)用外部接口的方式有多種,常見(jiàn)的有以下三種方式:RestTemplate、Feign 和 WebClient。它們之間存在一些聯(lián)系和區(qū)別。
RestTemplate:
- RestTemplate 是 Spring Framework 提供的傳統(tǒng)的 HTTP 客戶(hù)端工具,在 Spring Boot 中也得到了支持。
- 通過(guò) RestTemplate,可以發(fā)送 HTTP 請(qǐng)求并接收響應(yīng),支持同步調(diào)用。
- RestTemplate 具有廣泛的功能,可以處理各種請(qǐng)求和響應(yīng)內(nèi)容,支持自定義編解碼、攔截器等功能。
- RestTemplate 使用起來(lái)相對(duì)簡(jiǎn)單,直接調(diào)用其方法即可,適用于簡(jiǎn)單的接口調(diào)用場(chǎng)景。
Feign:
- Feign 是基于接口的聲明式的 HTTP 客戶(hù)端,是 Spring Cloud 提供的組件之一。
- Feign 在 Spring Boot 中通過(guò)
@FeignClient
注解定義和使用。 - 通過(guò) Feign,可以以聲明式的方式定義遠(yuǎn)程服務(wù)接口,并且 Feign 會(huì)自動(dòng)代理實(shí)現(xiàn)具體的調(diào)用邏輯,無(wú)需手動(dòng)編寫(xiě)實(shí)現(xiàn)代碼。
- Feign 集成了 Ribbon 負(fù)載均衡器和 Eureka 服務(wù)注冊(cè)中心,可以自動(dòng)進(jìn)行負(fù)載均衡和服務(wù)發(fā)現(xiàn)。
- Feign 更加高級(jí)抽象和靈活,適用于需要更多功能和集成分布式系統(tǒng)環(huán)境的場(chǎng)景。
WebClient:
- WebClient 是 Spring WebFlux 提供的非阻塞的 HTTP 客戶(hù)端。
- WebClient 基于 Reactor 響應(yīng)式編程模型,能夠在異步非阻塞的情況下處理大量并發(fā)請(qǐng)求。
- WebClient 支持使用函數(shù)式編程風(fēng)格來(lái)定義請(qǐng)求和處理響應(yīng),可以使用 Mono 和 Flux 處理異步結(jié)果。
- WebClient 適用于高性能、高并發(fā)的場(chǎng)景,并且在 Spring Boot 2.x 中是推薦的方式。
這三種方式在實(shí)際使用中有一些聯(lián)系和區(qū)別:
- RestTemplate 是傳統(tǒng)的 HTTP 客戶(hù)端,使用較為簡(jiǎn)單,適用于簡(jiǎn)單的接口調(diào)用場(chǎng)景。
- Feign 是基于接口的聲明式客戶(hù)端,集成了負(fù)載均衡和服務(wù)發(fā)現(xiàn)等功能,適用于分布式系統(tǒng)下的服務(wù)調(diào)用。
- WebClient 是非阻塞的 HTTP 客戶(hù)端,支持異步、響應(yīng)式編程模型,適用于高并發(fā)、高性能的場(chǎng)景。
選擇使用哪種方式需要根據(jù)具體的需求和場(chǎng)景來(lái)決定。在 Spring Boot 中,可以根據(jù)項(xiàng)目的特點(diǎn)和要求,靈活選擇適合的方式進(jìn)行外部接口調(diào)用。
總結(jié)
到此這篇關(guān)于Spring Boot中調(diào)用外部接口的3種方式步驟的文章就介紹到這了,更多相關(guān)Spring Boot調(diào)用外部接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IntelliJ IDEA Project窗口的一些設(shè)置詳解
這篇文章主要介紹了IntelliJ IDEA Project窗口的一些設(shè)置詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08springboot攔截器過(guò)濾token,并返回結(jié)果及異常處理操作
這篇文章主要介紹了springboot攔截器過(guò)濾token,并返回結(jié)果及異常處理操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09windows系統(tǒng)配置Java開(kāi)發(fā)環(huán)境變量
這篇文章主要介紹了windows系統(tǒng)配置Java開(kāi)發(fā)環(huán)境變量,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2021-12-12Java實(shí)現(xiàn)刪除排序鏈表中的重復(fù)元素的方法
這篇文章主要介紹了Java實(shí)現(xiàn)刪除排序鏈表中的重復(fù)元素的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02分析講解SpringMVC注解配置如何實(shí)現(xiàn)
這篇文章主要介紹了本文要介紹用注解方式代替web.xml與SpringMVC的配置文件,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05Java使用itextpdf找出PDF中文字的坐標(biāo)
這篇文章主要為大家詳細(xì)介紹了Java如果使用itextpdf找出PDF中文字的坐標(biāo),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-01-01java編程實(shí)現(xiàn)楊輝三角兩種輸出結(jié)果實(shí)例代碼
這篇文章主要介紹了java編程實(shí)現(xiàn)楊輝三角兩種輸出結(jié)果實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12