国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

SpringBoot——SpringBoot訪問外部接口

這篇具有很好參考價值的文章主要介紹了SpringBoot——SpringBoot訪問外部接口。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

摘要

在SpringBoot接口開發(fā)中,存在著本模塊的代碼需要訪問外面模塊接口或外部url鏈接的需求, 比如調用外部的地圖API或者天氣API。那么有哪些方式可以調用外部接口呢?本博文將介紹SpringBoot常見的訪問外部接口方式。幫助大家更好的使用SpringBoot訪問外部接口。

一、需要訪問外部接口背景

調用其它模塊的API,或者其它三方服務,比如調用外部的地圖API或者天氣API等。

二、訪問外部接口的常見方案

2.1 采用原生的Http請求

在代碼中采用原生的http請求,代碼參考如下:

@RequestMapping("/doPostGetJson")
public String doPostGetJson() throws ParseException {
   //此處將要發(fā)送的數據轉換為json格式字符串
   String jsonText = "{id: 1}";
   JSONObject json = (JSONObject) JSONObject.parse(jsonText);
   JSONObject sr = this.doPost(json);
   System.out.println("返回參數: " + sr);
   return sr.toString();
}

public static JSONObject doPost(JSONObject date) {
   HttpClient client = HttpClients.createDefault();
   // 要調用的接口方法
   String url = "http://192.168.1.101:8080/getJson";
   HttpPost post = new HttpPost(url);
   JSONObject jsonObject = null;
   try {
      StringEntity s = new StringEntity(date.toString());
      s.setContentEncoding("UTF-8");
      s.setContentType("application/json");
      post.setEntity(s);
      post.addHeader("content-type", "text/xml");
      HttpResponse res = client.execute(post);
      String response1 = EntityUtils.toString(res.getEntity());
      System.out.println(response1);
      if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
         String result = EntityUtils.toString(res.getEntity());// 返回json格式: 
         jsonObject = JSONObject.parseObject(result);
      }
   } catch (Exception e) {
      throw new RuntimeException(e);
   }
   return jsonObject;
}

2.2? 采用Feign進行消費(PRC通信)

在maven項目中添加依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.2.2.RELEASE</version>
</dependency>

編寫接口,放置在service層。這里的decisionEngine.url 是配置在properties中的 是ip地址和端口號 decisionEngine.url=http://10.2.1.148:3333/decision/person 是接口名字。

@FeignClient(url = "${decisionEngine.url}",name="engine")
public interface DecisionEngineService {
  @RequestMapping(value="/decision/person",method= RequestMethod.POST)
  public JSONObject getEngineMesasge(@RequestParam("uid") String uid,@RequestParam("productCode") String productCode);

}

在Java的啟動類上加上@EnableFeignClients

@EnableFeignClients //參見此處
@EnableDiscoveryClient
@SpringBootApplication
@EnableResourceServer
public class Application   implements CommandLineRunner {
    private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
    @Autowired
    private AppMetricsExporter appMetricsExporter;

    @Autowired
    private AddMonitorUnitService addMonitorUnitService;

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).web(true).run(args);
    }    
}

在代碼中調用接口即可

@Autowired
private DecisionEngineService decisionEngineService ;
// ...
decisionEngineService.getEngineMesasge("uid" ,  "productCode");

2.3 采用RestTemplate方法

在Spring-Boot開發(fā)中,RestTemplate同樣提供了對外訪問的接口API,這里主要介紹Get和Post方法的使用。Get請求提供了兩種方式的接口getForObject 和 getForEntity,getForEntity提供如下三種方法的實現(xiàn)。

2.3.1 Get請求之——getForEntity(Stringurl,Class responseType,Object…urlVariables)

該方法提供了三個參數,其中url為請求的地址,responseType為請求響應body的包裝類型,urlVariables為url中的參數綁定,該方法的參考調用如下:

// http://USER-SERVICE/user?name={name)
RestTemplate restTemplate=new RestTemplate();
Map<String,String> params=new HashMap<>();
params.put("name","dada");  //
ResponseEntity<String> responseEntity=restTemplate.getForEntity("http://USERSERVICE/user?name={name}",String.class,params);

2.3.2 Get請求之——getForEntity(URI url,Class responseType)

該方法使用URI對象來替代之前的url和urlVariables參數來指定訪問地址和參數綁定。URI是JDK java.net包下的一個類,表示一個統(tǒng)一資源標識符(Uniform Resource Identifier)引用。參考如下:

RestTemplate restTemplate=new RestTemplate();
UriComponents uriComponents=UriComponentsBuilder.fromUriString("http://USER-SERVICE/user?name={name}")
    .build()
    .expand("dodo")
    .encode();
URI uri=uriComponents.toUri();
ResponseEntity<String> responseEntity=restTemplate.getForEntity(uri,String.class).getBody();

2.3.3 Get請求之——getForObject

getForObject方法可以理解為對getForEntity的進一步封裝,它通過HttpMessageConverterExtractor對HTTP的請求響應體body內容進行對象轉換,實現(xiàn)請求直接返回包裝好的對象內容。getForObject方法有如下:

getForObject(String url,Class responseType,Object...urlVariables)
getForObject(String url,Class responseType,Map urlVariables)
getForObject(URI url,Class responseType)

2.3.4 Post 請求

Post請求提供有三種方法,postForEntity、postForObject和postForLocation。其中每種方法都存在三種方法,postForEntity方法使用如下:

RestTemplate restTemplate=new RestTemplate();
User user=newUser("didi",30);
ResponseEntity<String> responseEntity=restTemplate.postForEntity("http://USER-SERVICE/user",user,String.class); //提交的body內容為user對象,請求的返回的body類型為String
String body=responseEntity.getBody();

postForEntity存在如下三種方法的重載

postForEntity(String url,Object request,Class responseType,Object... uriVariables)
postForEntity(String url,Object request,Class responseType,Map uriVariables)
postForEntity(URI url,Object request,Class responseType)

postForEntity中的其它參數和getForEntity的參數大體相同在此不做介紹。

2.4 在接口調用中需要注意什么?

需要注意兩點:

  1. 需要設置超時時間
  2. 需要自行處理異常

三、SpringBoot保證接口冪等

3.1 什么是冪等

當我們討論接口的冪等性時一般是在說:以相同的請求調用這個接口一次和調用這個接口多次,對系統(tǒng)產生的影響是相同的。如果一個接口滿足這個特性,那么我們就說這個 接口是一個冪等接口。

  • 接口冪等和防止重復提交是一回事嗎?

嚴格來說,并不是。

  1. 冪等: 更多的是在重復請求已經發(fā)生,或是無法避免的情況下,采取一定的技術手段讓這些重復請求不給系統(tǒng)帶來副作用。
  2. 防止重復: 提交更多的是不讓用戶發(fā)起多次一樣的請求。比如說用戶在線購物下單時點了提交訂單按鈕,但是由于網絡原因響應很慢,此時用戶比較心急多次點擊了訂單提交按鈕。 這種情況下就可能會造成多次下單。一般防止重復提交的方案有:將訂單按鈕置灰,跳轉到結果頁等。主要還是從客戶端的角度來解決這個問題。
  • 哪些情況下客戶端是防止不了重復提交的?

雖然我們可在客戶端做一些防止接口重復提交的事(比如將訂單按鈕置灰,跳轉到結果頁等), 但是如下情況依然客戶端是很難控制接口重復提交到后臺的,這也進一步表明了接口冪等和防止重復提交不是一回事以及后端接口保證接口冪等的必要性所在。

  1. 接口超時重試:接口可能會因為某些原因而調用失敗,出于容錯性考慮會加上失敗重試的機制。如果接口調用一半,再次調用就會因為臟數據的存在而出現(xiàn)異常。
  2. 消息重復消費:在使用消息中間件來處理消息隊列,且手動ack確認消息被正常消費時。如果消費者突然斷開連接,那么已經執(zhí)行了一半的消息會重新放回隊列。被其他消費者重新消費時就會導致結果異常,如數據庫重復數據,數據庫數據沖突,資源重復等。
  3. 請求重發(fā):網絡抖動引發(fā)的nginx重發(fā)請求,造成重復調用;

3.2 什么是接口冪等?

在HTTP/1.1中,對冪等性進行了定義。它描述了一次和多次請求某一個資源對于資源本身應該具有同樣的結果(網絡超時等問題除外),即第一次請求的時候對資源產生了副作用,但是以后的多次請求都不會再對資源產生副作用。

這里的副作用是不會對結果產生破壞或者產生不可預料的結果。也就是說,其任意多次執(zhí)行對資源本身所產生的影響均與一次執(zhí)行的影響相同。

  • 對哪些類型的接口需要保證接口冪等?

我們看下標準的restful請求,冪等情況是怎么樣的:

  1. SELECT查詢操作
    1. GET:只是獲取資源,對資源本身沒有任何副作用,天然的冪等性。
    2. HEAD:本質上和GET一樣,獲取頭信息,主要是探活的作用,具有冪等性。
    3. OPTIONS:獲取當前URL所支持的方法,因此也是具有冪等性的。
  2. DELETE刪除操作
    1. 刪除的操作,如果從刪除的一次和刪除多次的角度看,數據并不會變化,這個角度看它是冪等的
    2. 但是如果,從另外一個角度,刪除數據一般是返回受影響的行數,刪除一次和多次刪除返回的受影響行數是不一樣的,所以從這個角度它需要保證冪等。(折中而言DELETE操作通常也會被納入保證接口冪等的要求)
  3. ADD/EDIT操作
    1. PUT:用于更新資源,有副作用,但是它應該滿足冪等性,比如根據id更新數據,調用多次和N次的作用是相同的(根據業(yè)務需求而變)。
    2. POST:用于添加資源,多次提交很可能產生副作用,比如訂單提交,多次提交很可能產生多筆訂單。

3.3 保證冪等的方式

3.3.1 數據庫層面

典型的數據庫悲觀鎖:for update

select * from t_order where order_id = trade_no for update;

為什么加for update就可以?

  1. 當線程A執(zhí)行for update,數據會對當前記錄加鎖,其他線程執(zhí)行到此行代碼的時候,會等待線程A釋放鎖之后,才可以獲取鎖,繼續(xù)后續(xù)操作。
  2. 事物提交時,for update獲取的鎖會自動釋放。

PS:這種方式很少被使用,因為如果業(yè)務處理比較耗時,并發(fā)情況下,后面線程會長期處于等待狀態(tài),占用了很多線程,讓這些線程處于無效等待狀態(tài),我們的web服務中的線程數量一般都是有限的,如果大量線程由于獲取for update鎖處于等待狀態(tài),不利于系統(tǒng)并發(fā)操作。

3.3.2 唯一ID/索引

針對的是插入操作。數據庫唯一主鍵的實現(xiàn)主要是利用數據庫中主鍵唯一約束的特性,一般來說唯一主鍵比較適用于“插入”時的冪等性,其能保證一張表中只能存在一條帶該唯一主鍵的記錄。

使用數據庫唯一主鍵完成冪等性時需要注意的是,該主鍵一般來說并不是使用數據庫中自增主鍵,而是使用分布式 ID 充當主鍵,這樣才能能保證在分布式環(huán)境下 ID 的全局唯一性。

  • 去重表

去重表本質上也是一種唯一索引方案。

這種方法適用于在業(yè)務中有唯一標的插入場景中,比如在以上的支付場景中,如果一個訂單只會支付一次,所以訂單ID可以作為唯一標識。這時,我們就可以建一張去重表,并且把唯一標識作為唯一索引,在我們實現(xiàn)時,把創(chuàng)建支付單據和寫入去去重表,放在一個事務中,如果重復創(chuàng)建,數據庫會拋出唯一約束異常,操作就會回滾。

3.3.3 樂觀鎖(基于版本號或者時間戳)

針對更新操作。

  • 使用版本號或者時間戳

這種方法適合在更新的場景中,比如我們要更新商品的名字,這時我們就可以在更新的接口中增加一個版本號,來做冪等

boolean updateGoodsName(int id,String newName,int version);

在實現(xiàn)時可以如下

update goods set name=#{newName},version=#{version} where id=#{id} and version<${version}
  • 狀態(tài)機

本質上也是樂觀鎖,這種方法適合在有狀態(tài)機流轉的情況下,比如就會訂單的創(chuàng)建和付款,訂單的付款肯定是在之前,這時我們可以通過在設計狀態(tài)字段時,使用int類型,并且通過值類型的大小來做冪等,比如訂單的創(chuàng)建為0,付款成功為100。付款失敗為99

在做狀態(tài)機更新時,我們就這可以這樣控制

update `order` set status=#{status} where id=#{id} and status<#{status}

3.3.4 分布式鎖

分布式鎖實現(xiàn)冪等性的邏輯是,在每次執(zhí)行方法之前判斷,是否可以獲取到分布式鎖,如果可以,則表示為第一次執(zhí)行方法,否則直接舍棄請求即可。需要注意的是分布式鎖的key必須為業(yè)務的唯一標識,通常用redis分布式鎖或者zookeeper來實現(xiàn)分布式鎖。文章來源地址http://www.zghlxwxcb.cn/news/detail-733098.html

博文參考

到了這里,關于SpringBoot——SpringBoot訪問外部接口的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【SpringBoot3】--03.數據訪問、基礎特性(外部化和內部外配置、整合JUnit)

    【SpringBoot3】--03.數據訪問、基礎特性(外部化和內部外配置、整合JUnit)

    學習視頻: 尚硅谷SpringBoot3視頻 SpringBoot 整合 Spring 、 SpringMVC 、 MyBatis 進行 數據訪問場景 開發(fā) 勾選之后會導入以下包 安裝 MyBatisX 插件,幫我們生成Mapper接口的xml文件即可 在接口處 : Alt + 回車 必須把mapper的xml文件映射位置在配置文件定義! 而駝峰命名轉換建議也開啟 編

    2024年02月16日
    瀏覽(43)
  • Springboot之把外部依賴包納入Spring容器管理的兩種方式

    Springboot之把外部依賴包納入Spring容器管理的兩種方式

    在Spring boot項目中,凡是標記有@Component、@Controller、@Service、@Configuration、@Bean等注解的類,Spring boot都會在容器啟動的時候,自動創(chuàng)建bean并納入到Spring容器中進行管理,這樣就可以使用@Autowired等注解,在需要使用bean的業(yè)務類中進行注入。這里起到關鍵作用的就是@ComponentScan,

    2024年02月14日
    瀏覽(21)
  • SpringBoot訪問靜態(tài)資源和jar外部靜態(tài)資源,部署前端打包后的vue項目放入靜態(tài)資源里

    SpringBoot訪問靜態(tài)資源和jar外部靜態(tài)資源,部署前端打包后的vue項目放入靜態(tài)資源里

    記錄一下使用SpringBoot訪問靜態(tài)資源和SpringBoot打包之后的jar外部靜態(tài)資源,在開發(fā)的時候,一般選擇前后端分離的方式,前端使用vue 后端使用SpringBoot,通常情況下,部署都是前端通過http去請求后端資源,涉及到http請求,那么肯定需要資源的目標地址IP,一般云端部署給到I

    2024年02月09日
    瀏覽(23)
  • SpringBoot項目啟動成功但接口訪問404

    SpringBoot項目啟動成功但接口訪問404

    問題描述:SpringBoot項目啟動成功,但使用postman調接口時報404 分析:找不到路徑,controller未生效。 解決:將com.local.coupon.template.templateimpl改為com.local.coupon.template。SpringBoot會掃描到com.local.coupon.template包及其子包下面的內容,掃描路徑也無需指定(即可以去掉@ComponentScan注解)

    2024年02月17日
    瀏覽(22)
  • Springboot項目啟動后瀏覽器不能直接訪問接口,而postman可以訪問?

    Springboot項目啟動后瀏覽器不能直接訪問接口,而postman可以訪問?

    在云服務器上部署springboot后端時,項目啟動后瀏覽器不能直接訪問接口,而postman可以訪問。這是當時困擾了我大半天的小問題,在我打開防火墻和阿里云安全組之后還是沒解決。然后在網上搜了很多很多資料,以為是瀏覽器訪問權限或者是https什么證書問題,到頭來通過簡單

    2024年02月21日
    瀏覽(24)
  • Python中如何編寫接口,以及如何請求外部接口

    Python是一種既簡單又強大的編程語言,也是現(xiàn)代軟件開發(fā)的重要工具之一。在開發(fā)過程中,我們通常需要編寫接口,并且從外部接口獲取數據。本文將介紹如何在Python中編寫接口,以及如何請求外部接口。 在Python中,可以使用Flask和Django等框架來編寫接口。本文以Flask為例,

    2024年02月03日
    瀏覽(23)
  • SpringBoot限制接口訪問頻率 - 這些錯誤千萬不能犯

    最近在基于SpringBoot做一個面向普通用戶的系統(tǒng),為了保證系統(tǒng)的穩(wěn)定性,防止被惡意攻擊,我想控制用戶訪問每個接口的頻率。為了實現(xiàn)這個功能,可以設計一個annotation,然后借助AOP在調用方法之前檢查當前ip的訪問頻率,如果超過設定頻率,直接返回錯誤信息。 在開始介

    2024年02月05日
    瀏覽(17)
  • SpringBoot 如何使用 Spring Data MongoDB 訪問 MongoDB

    SpringBoot 如何使用 Spring Data MongoDB 訪問 MongoDB

    在現(xiàn)代應用程序開發(fā)中,許多應用都依賴于數據庫來存儲和檢索數據。MongoDB 是一個流行的 NoSQL 數據庫,而 Spring Boot 是一個廣泛使用的 Java 開發(fā)框架。本文將介紹如何使用 Spring Boot 和 Spring Data MongoDB 來訪問和操作 MongoDB 數據庫。 MongoDB 是一個開源的 NoSQL 數據庫,它以文檔的

    2024年02月07日
    瀏覽(20)
  • 超詳細!完整版!基于spring對外開放接口的簽名認證方案(攔截器方式)

    由于項目需要開發(fā)第三方接口給多個供應商,為保證Api接口的安全性,遂采用Api接口簽名驗證。 請求發(fā)起時間得在限制范圍內 請求的用戶是否真實存在 是否存在重復請求 請求參數是否被篡改 1、服務端生成一對 accessKey/secretKey密鑰對,將 accessKey公開給客戶端,將 secretKey 保

    2024年01月22日
    瀏覽(41)
  • Spring Security的API Key實現(xiàn)SpringBoot 接口安全

    Spring Security的API Key實現(xiàn)SpringBoot 接口安全

    Spring Security 提供了各種機制來保護我們的 REST API。其中之一是 API 密鑰。API 密鑰是客戶端在調用 API 調用時提供的令牌。 在本教程中,我們將討論如何在Spring Security中實現(xiàn)基于API密鑰的身份驗證。 API Keys 一些REST API使用API密鑰進行身份驗證。API密鑰是一個標記,用于向API客戶

    2024年03月15日
    瀏覽(15)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包