Spring Boot 實(shí)現(xiàn)接口冪等性的 4 種方案!還有誰不會(huì)_第1頁
Spring Boot 實(shí)現(xiàn)接口冪等性的 4 種方案!還有誰不會(huì)_第2頁
Spring Boot 實(shí)現(xiàn)接口冪等性的 4 種方案!還有誰不會(huì)_第3頁
Spring Boot 實(shí)現(xiàn)接口冪等性的 4 種方案!還有誰不會(huì)_第4頁
Spring Boot 實(shí)現(xiàn)接口冪等性的 4 種方案!還有誰不會(huì)_第5頁
已閱讀5頁,還剩16頁未讀 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

SpringBoot實(shí)現(xiàn)接口冪等性的4種方案!還有誰不會(huì)?一、什么是冪等性冪等是一個(gè)數(shù)學(xué)與計(jì)算機(jī)學(xué)概念,在數(shù)學(xué)中某一元運(yùn)算為冪等時(shí),其作用在任一元素兩次后會(huì)和其作用一次的結(jié)果相同。在計(jì)算機(jī)中編程中,一個(gè)冪等操作的特點(diǎn)是其任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同。冪等函數(shù)或冪等方法是指可以使用相同參數(shù)重復(fù)執(zhí)行,并能獲得相同結(jié)果的函數(shù)。這些函數(shù)不會(huì)影響系統(tǒng)狀態(tài),也不用擔(dān)心重復(fù)執(zhí)行會(huì)對(duì)系統(tǒng)造成改變。二、什么是接口冪等性在HTTP/1.1中,對(duì)冪等性進(jìn)行了定義。它描述了一次和多次請(qǐng)求某一個(gè)資源對(duì)于資源本身應(yīng)該具有同樣的結(jié)果(網(wǎng)絡(luò)超時(shí)等問題除外),即第一次請(qǐng)求的時(shí)候?qū)Y源產(chǎn)生了副作用,但是以后的多次請(qǐng)求都不會(huì)再對(duì)資源產(chǎn)生副作用。這里的副作用是不會(huì)對(duì)結(jié)果產(chǎn)生破壞或者產(chǎn)生不可預(yù)料的結(jié)果。也就是說,其任意多次執(zhí)行對(duì)資源本身所產(chǎn)生的影響均與一次執(zhí)行的影響相同。三、為什么需要實(shí)現(xiàn)冪等性在接口調(diào)用時(shí)一般情況下都能正常返回信息不會(huì)重復(fù)提交,不過在遇見以下情況時(shí)可以就會(huì)出現(xiàn)問題,如:前端重復(fù)提交表單:

在填寫一些表格時(shí)候,用戶填寫完成提交,很多時(shí)候會(huì)因網(wǎng)絡(luò)波動(dòng)沒有及時(shí)對(duì)用戶做出提交成功響應(yīng),致使用戶認(rèn)為沒有成功提交,然后一直點(diǎn)提交按鈕,這時(shí)就會(huì)發(fā)生重復(fù)提交表單請(qǐng)求。用戶惡意進(jìn)行刷單:

例如在實(shí)現(xiàn)用戶投票這種功能時(shí),如果用戶針對(duì)一個(gè)用戶進(jìn)行重復(fù)提交投票,這樣會(huì)導(dǎo)致接口接收到用戶重復(fù)提交的投票信息,這樣會(huì)使投票結(jié)果與事實(shí)嚴(yán)重不符。接口超時(shí)重復(fù)提交:

很多時(shí)候HTTP客戶端工具都默認(rèn)開啟超時(shí)重試的機(jī)制,尤其是第三方調(diào)用接口時(shí)候,為了防止網(wǎng)絡(luò)波動(dòng)超時(shí)等造成的請(qǐng)求失敗,都會(huì)添加重試機(jī)制,導(dǎo)致一個(gè)請(qǐng)求提交多次。消息進(jìn)行重復(fù)消費(fèi):

當(dāng)使用MQ消息中間件時(shí)候,如果發(fā)生消息中間件出現(xiàn)錯(cuò)誤未及時(shí)提交消費(fèi)信息,導(dǎo)致發(fā)生重復(fù)消費(fèi)。使用冪等性最大的優(yōu)勢(shì)在于使接口保證任何冪等性操作,免去因重試等造成系統(tǒng)產(chǎn)生的未知的問題。四、引入冪等性后對(duì)系統(tǒng)的影響冪等性是為了簡(jiǎn)化客戶端邏輯處理,能放置重復(fù)提交等操作,但卻增加了服務(wù)端的邏輯復(fù)雜性和成本,其主要是:把并行執(zhí)行的功能改為串行執(zhí)行,降低了執(zhí)行效率。增加了額外控制冪等的業(yè)務(wù)邏輯,復(fù)雜化了業(yè)務(wù)功能;所以在使用時(shí)候需要考慮是否引入冪等性的必要性,根據(jù)實(shí)際業(yè)務(wù)場(chǎng)景具體分析,除了業(yè)務(wù)上的特殊要求外,一般情況下不需要引入的接口冪等性。五、RestfulAPI接口的冪等性現(xiàn)在流行的Restful推薦的幾種HTTP接口方法中,分別存在冪等行與不能保證冪等的方法,如下:√滿足冪等x不滿足冪等-可能滿足也可能不滿足冪等,根據(jù)實(shí)際業(yè)務(wù)邏輯有關(guān)六、如何實(shí)現(xiàn)冪等性方案一:數(shù)據(jù)庫(kù)唯一主鍵方案描述數(shù)據(jù)庫(kù)唯一主鍵的實(shí)現(xiàn)主要是利用數(shù)據(jù)庫(kù)中主鍵唯一約束的特性,一般來說唯一主鍵比較適用于“插入”時(shí)的冪等性,其能保證一張表中只能存在一條帶該唯一主鍵的記錄。使用數(shù)據(jù)庫(kù)唯一主鍵完成冪等性時(shí)需要注意的是,該主鍵一般來說并不是使用數(shù)據(jù)庫(kù)中自增主鍵,而是使用分布式ID充當(dāng)主鍵(可以參考Java中分布式ID的設(shè)計(jì)方案這篇文章),這樣才能能保證在分布式環(huán)境下ID的全局唯一性。適用操作:插入操作刪除操作使用限制:需要生成全局唯一主鍵ID;主要流程:主要流程:①客戶端執(zhí)行創(chuàng)建請(qǐng)求,調(diào)用服務(wù)端接口。②服務(wù)端執(zhí)行業(yè)務(wù)邏輯,生成一個(gè)分布式ID,將該ID充當(dāng)待插入數(shù)據(jù)的主鍵,然后執(zhí)數(shù)據(jù)插入操作,運(yùn)行對(duì)應(yīng)的SQL語句。③服務(wù)端將該條數(shù)據(jù)插入數(shù)據(jù)庫(kù)中,如果插入成功則表示沒有重復(fù)調(diào)用接口。如果拋出主鍵重復(fù)異常,則表示數(shù)據(jù)庫(kù)中已經(jīng)存在該條記錄,返回錯(cuò)誤信息到客戶端。方案二:數(shù)據(jù)庫(kù)樂觀鎖方案描述:數(shù)據(jù)庫(kù)樂觀鎖方案一般只能適用于執(zhí)行“更新操作”的過程,我們可以提前在對(duì)應(yīng)的數(shù)據(jù)表中多添加一個(gè)字段,充當(dāng)當(dāng)前數(shù)據(jù)的版本標(biāo)識(shí)。這樣每次對(duì)該數(shù)據(jù)庫(kù)該表的這條數(shù)據(jù)執(zhí)行更新時(shí),都會(huì)將該版本標(biāo)識(shí)作為一個(gè)條件,值為上次待更新數(shù)據(jù)中的版本標(biāo)識(shí)的值。適用操作:更新操作使用限制:需要數(shù)據(jù)庫(kù)對(duì)應(yīng)業(yè)務(wù)表中添加額外字段;描述示例:例如,存在如下的數(shù)據(jù)表中:idnameprice1小米手機(jī)10002蘋果手機(jī)25003華為手機(jī)1600為了每次執(zhí)行更新時(shí)防止重復(fù)更新,確定更新的一定是要更新的內(nèi)容,我們通常都會(huì)添加一個(gè)version字段記錄當(dāng)前的記錄版本,這樣在更新時(shí)候?qū)⒃撝祹?,那么只要?zhí)行更新操作就能確定一定更新的是某個(gè)對(duì)應(yīng)版本下的信息。idnamepriceversion1小米手機(jī)1000102蘋果手機(jī)2500213華為手機(jī)16005這樣每次執(zhí)行更新時(shí)候,都要指定要更新的版本號(hào),如下操作就能準(zhǔn)確更新version=5的信息:UPDATE

my_table

SET

price=price+50,version=version+1

WHERE

id=1

AND

version=5上面WHERE后面跟著條件id=1ANDversion=5被執(zhí)行后,id=1的version被更新為6,所以如果重復(fù)執(zhí)行該條SQL語句將不生效,因?yàn)閕d=1ANDversion=5的數(shù)據(jù)已經(jīng)不存在,這樣就能保住更新的冪等,多次更新對(duì)結(jié)果不會(huì)產(chǎn)生影響。方案三:防重Token令牌方案描述:針對(duì)客戶端連續(xù)點(diǎn)擊或者調(diào)用方的超時(shí)重試等情況,例如提交訂單,此種操作就可以用Token的機(jī)制實(shí)現(xiàn)防止重復(fù)提交。簡(jiǎn)單的說就是調(diào)用方在調(diào)用接口的時(shí)候先向后端請(qǐng)求一個(gè)全局ID(Token),請(qǐng)求的時(shí)候攜帶這個(gè)全局ID一起請(qǐng)求(Token最好將其放到Headers中),后端需要對(duì)這個(gè)Token作為Key,用戶信息作為Value到Redis中進(jìn)行鍵值內(nèi)容校驗(yàn),如果Key存在且Value匹配就執(zhí)行刪除命令,然后正常執(zhí)行后面的業(yè)務(wù)邏輯。如果不存在對(duì)應(yīng)的Key或Value不匹配就返回重復(fù)執(zhí)行的錯(cuò)誤信息,這樣來保證冪等操作。適用操作:插入操作更新操作刪除操作使用限制:需要生成全局唯一Token串;需要使用第三方組件Redis進(jìn)行數(shù)據(jù)效驗(yàn);主要流程:①服務(wù)端提供獲取Token的接口,該Token可以是一個(gè)序列號(hào),也可以是一個(gè)分布式ID或者UUID串。②客戶端調(diào)用接口獲取Token,這時(shí)候服務(wù)端會(huì)生成一個(gè)Token串。③然后將該串存入Redis數(shù)據(jù)庫(kù)中,以該Token作為Redis的鍵(注意設(shè)置過期時(shí)間)。④將Token返回到客戶端,客戶端拿到后應(yīng)存到表單隱藏域中。⑤客戶端在執(zhí)行提交表單時(shí),把Token存入到Headers中,執(zhí)行業(yè)務(wù)請(qǐng)求帶上該Headers。⑥服務(wù)端接收到請(qǐng)求后從Headers中拿到Token,然后根據(jù)Token到Redis中查找該key是否存在。⑦服務(wù)端根據(jù)Redis中是否存該key進(jìn)行判斷,如果存在就將該key刪除,然后正常執(zhí)行業(yè)務(wù)邏輯。如果不存在就拋異常,返回重復(fù)提交的錯(cuò)誤信息。注意,在并發(fā)情況下,執(zhí)行Redis查找數(shù)據(jù)與刪除需要保證原子性,否則很可能在并發(fā)下無法保證冪等性。其實(shí)現(xiàn)方法可以使用分布式鎖或者使用Lua表達(dá)式來注銷查詢與刪除操作。方案四、下游傳遞唯一序列號(hào)方案描述:所謂請(qǐng)求序列號(hào),其實(shí)就是每次向服務(wù)端請(qǐng)求時(shí)候附帶一個(gè)短時(shí)間內(nèi)唯一不重復(fù)的序列號(hào),該序列號(hào)可以是一個(gè)有序ID,也可以是一個(gè)訂單號(hào),一般由下游生成,在調(diào)用上游服務(wù)端接口時(shí)附加該序列號(hào)和用于認(rèn)證的ID。當(dāng)上游服務(wù)器收到請(qǐng)求信息后拿取該序列號(hào)和下游認(rèn)證ID進(jìn)行組合,形成用于操作Redis的Key,然后到Redis中查詢是否存在對(duì)應(yīng)的Key的鍵值對(duì),根據(jù)其結(jié)果:如果存在,就說明已經(jīng)對(duì)該下游的該序列號(hào)的請(qǐng)求進(jìn)行了業(yè)務(wù)處理,這時(shí)可以直接響應(yīng)重復(fù)請(qǐng)求的錯(cuò)誤信息。如果不存在,就以該Key作為Redis的鍵,以下游關(guān)鍵信息作為存儲(chǔ)的值(例如下游商傳遞的一些業(yè)務(wù)邏輯信息),將該鍵值對(duì)存儲(chǔ)到Redis中,然后再正常執(zhí)行對(duì)應(yīng)的業(yè)務(wù)邏輯即可。適用操作:插入操作更新操作刪除操作使用限制:要求第三方傳遞唯一序列號(hào);需要使用第三方組件Redis進(jìn)行數(shù)據(jù)效驗(yàn);主要流程:主要步驟:①下游服務(wù)生成分布式ID作為序列號(hào),然后執(zhí)行請(qǐng)求調(diào)用上游接口,并附帶“唯一序列號(hào)”與請(qǐng)求的“認(rèn)證憑據(jù)ID”。②上游服務(wù)進(jìn)行安全效驗(yàn),檢測(cè)下游傳遞的參數(shù)中是否存在“序列號(hào)”和“憑據(jù)ID”。③上游服務(wù)到Redis中檢測(cè)是否存在對(duì)應(yīng)的“序列號(hào)”與“認(rèn)證ID”組成的Key,如果存在就拋出重復(fù)執(zhí)行的異常信息,然后響應(yīng)下游對(duì)應(yīng)的錯(cuò)誤信息。如果不存在就以該“序列號(hào)”和“認(rèn)證ID”組合作為Key,以下游關(guān)鍵信息作為Value,進(jìn)而存儲(chǔ)到Redis中,然后正常執(zhí)行接來來的業(yè)務(wù)邏輯。上面步驟中插入數(shù)據(jù)到Redis一定要設(shè)置過期時(shí)間。這樣能保證在這個(gè)時(shí)間范圍內(nèi),如果重復(fù)調(diào)用接口,則能夠進(jìn)行判斷識(shí)別。如果不設(shè)置過期時(shí)間,很可能導(dǎo)致數(shù)據(jù)無限量的存入Redis,致使Redis不能正常工作。七、實(shí)現(xiàn)接口冪等示例這里使用防重Token令牌方案,該方案能保證在不同請(qǐng)求動(dòng)作下的冪等性,實(shí)現(xiàn)邏輯可以看上面寫的”防重Token令牌”方案,接下來寫下實(shí)現(xiàn)這個(gè)邏輯的代碼。1、Maven引入相關(guān)依賴這里使用Maven工具管理依賴,這里在pom.xml中引入SpringBoot、Redis、lombok相關(guān)依賴。

<project

xmlns="/POM/4.0.0"

xmlns:xsi="/2001/XMLSchema-instance"

xsi:schemaLocation="/POM/4.0.0

/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0modelVersion>

<parent>

<groupId>org.springframework.bootgroupId>

<artifactId>spring-boot-starter-parentartifactId>

<version>2.3.4.RELEASEversion>

parent>

<groupId>mydlq.clubgroupId>

<artifactId>springboot-idempotent-tokenartifactId>

<version>0.0.1version>

<name>springboot-idempotent-tokenname>

<description>Idempotent

Demodescription>

<properties>

<java.version>1.8java.version>

properties>

<dependencies>

<dependency>

<groupId>org.springframework.bootgroupId>

<artifactId>spring-boot-starter-webartifactId>

dependency>

<dependency>

<groupId>org.springframework.bootgroupId>

<artifactId>spring-boot-starter-data-redisartifactId>

dependency>

<dependency>

<groupId>monsgroupId>

<artifactId>commons-pool2artifactId>

dependency>

<dependency>

<groupId>jectlombokgroupId>

<artifactId>lombokartifactId>

dependency>

dependencies>

<build>

<plugins>

<plugin>

<groupId>org.springframework.bootgroupId>

<artifactId>spring-boot-maven-pluginartifactId>

plugin>

plugins>

build>

project>2、配置連接Redis的參數(shù)在application配置文件中配置連接Redis的參數(shù)。SpringBoot基礎(chǔ)就不介紹了,最新教程推薦看下面的教程。在公眾號(hào)后端頂級(jí)架構(gòu)師后臺(tái)回復(fù)“架構(gòu)整潔”,獲取一份驚喜禮包。/javastacks/spring-boot-best-practice如下:spring:

redis:

ssl:

false

host:

port:

6379

database:

0

timeout:

1000

password:

lettuce:

pool:

max-active:

100

max-wait:

-1

min-idle:

0

max-idle:

203、創(chuàng)建與驗(yàn)證Token工具類創(chuàng)建用于操作Token相關(guān)的Service類,里面存在Token創(chuàng)建與驗(yàn)證方法,其中:Token創(chuàng)建方法:

使用UUID工具創(chuàng)建Token串,設(shè)置以“idempotent_token:“+“Token串”作為Key,以用戶信息當(dāng)成Value,將信息存入Redis中。Token驗(yàn)證方法:

接收Token串參數(shù),加上Key前綴形成Key,再傳入value值,執(zhí)行Lua表達(dá)式(Lua表達(dá)式能保證命令執(zhí)行的原子性)進(jìn)行查找對(duì)應(yīng)Key與刪除操作。執(zhí)行完成后驗(yàn)證命令的返回結(jié)果,如果結(jié)果不為空且非0,則驗(yàn)證成功,否則失敗。import

java.util.Arrays;

import

java.util.UUID;

import

java.util.concurrent.TimeUnit;

import

lombok.extern.slf4j.Slf4j;

import

org.springframework.beans.factory.annotation.Autowired;

import

org.springframework.data.redis.core.StringRedisTemplate;

import

org.springframework.data.redis.core.script.DefaultRedisScript;

import

org.springframework.data.redis.core.script.RedisScript;

import

org.springframework.stereotype.Service;

@Slf4j

@Service

public

class

TokenUtilService

{

@Autowired

private

StringRedisTemplate

redisTemplate;

/**

*

存入

Redis

Token

鍵的前綴

*/

private

static

final

String

IDEMPOTENT_TOKEN_PREFIX

=

"idempotent_token:";

/**

*

創(chuàng)建

Token

存入

Redis,并返回該

Token

*

*

@param

value

用于輔助驗(yàn)證的

value

*

@return

生成的

Token

*/

public

String

generateToken(String

value)

{

//

實(shí)例化生成

ID

工具對(duì)象

String

token

=

UUID.randomUUID().toString();

//

設(shè)置存入

Redis

Key

String

key

=

IDEMPOTENT_TOKEN_PREFIX

+

token;

//

存儲(chǔ)

Token

Redis,且設(shè)置過期時(shí)間為5分鐘

redisTemplate.opsForValue().set(key,

value,

5,

TimeUnit.MINUTES);

//

返回

Token

return

token;

}

/**

*

驗(yàn)證

Token

正確性

*

*

@param

token

token

字符串

*

@param

value

value

存儲(chǔ)在Redis中的輔助驗(yàn)證信息

*

@return

驗(yàn)證結(jié)果

*/

public

boolean

validToken(String

token,

String

value)

{

//

設(shè)置

Lua

腳本,其中

KEYS[1]

key,KEYS[2]

value

String

script

=

"if

redis.call('get',

KEYS[1])

==

KEYS[2]

then

return

redis.call('del',

KEYS[1])

else

return

0

end";

RedisScript

redisScript

=

new

DefaultRedisScript<>(script,

Long.class);

//

根據(jù)

Key

前綴拼接

Key

String

key

=

IDEMPOTENT_TOKEN_PREFIX

+

token;

//

執(zhí)行

Lua

腳本

Long

result

=

redisTemplate.execute(redisScript,

Arrays.asList(key,

value));

//

根據(jù)返回結(jié)果判斷是否成功成功匹配并刪除

Redis

鍵值對(duì),若果結(jié)果不為空和0,則驗(yàn)證通過

if

(result

!=

null

&&

result

!=

0L)

{

("驗(yàn)證

token={},key={},value={}

成功",

token,

key,

value);

return

true;

}

("驗(yàn)證

token={},key={},value={}

失敗",

token,

key,

value);

return

false;

}

}4、創(chuàng)建測(cè)試的Controller類創(chuàng)建用于測(cè)試的Controller類,里面有獲取Token與測(cè)試接口冪等性的接口,內(nèi)容如下:import

lombok.extern.slf4j.Slf4j;

import

mydlq.club.example.service.TokenUtilService;

import

org.springframework.beans.factory.annotation.Autowired;

import

org.springframework.web.bind.annotation.*;

@Slf4j

@RestController

public

class

TokenController

{

@Autowired

private

TokenUtilService

tokenService;

/**

*

獲取

Token

接口

*

*

@return

Token

*/

@GetMapping("/token")

public

String

getToken()

{

//

獲取用戶信息(這里使用模擬數(shù)據(jù))

//

注:這里存儲(chǔ)該內(nèi)容只是舉例,其作用為輔助驗(yàn)證,使其驗(yàn)證邏輯更安全,如這里存儲(chǔ)用戶信息,其目的為:

//

-

1)、使用"token"驗(yàn)證

Redis

中是否存在對(duì)應(yīng)的

Key

//

-2)、使用"用戶信息"驗(yàn)證Redis的Value是否匹配。

String

userInfo

=

"mydlq";

//

獲取

Token

字符串,并返回

return

tokenService.generateToken(userInfo);

}

/**

*

接口冪等性測(cè)試接口

*

*

@param

token

冪等

Token

*

@return

執(zhí)行結(jié)果

*/

@PostMapping("/test")

public

String

test(@RequestHeader(value

=

"token")

String

token)

{

//

獲取用戶信息(這里使用模擬數(shù)據(jù))

String

userInfo

=

"mydlq";

//

根據(jù)

Token

和與用戶相關(guān)的信息到

Redis

驗(yàn)證是否存在對(duì)應(yīng)的信息

boolean

result

=

tokenService.validToken(token,

userInfo);

//

根據(jù)驗(yàn)證結(jié)果響應(yīng)不同信息

return

result

?

"正常調(diào)用"

:

"重復(fù)調(diào)用";

}

}5、創(chuàng)建SpringBoot啟動(dòng)類創(chuàng)建啟動(dòng)類,用于啟動(dòng)SpringBoot應(yīng)用。基礎(chǔ)教程就不介紹了,建議看下下面的教程,很全了。/javastacks/spring-boot-best-practiceimport

org.springframework.boot.SpringApplication;

import

org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public

class

Application

{

public

static

void

main(String[]

args)

{

SpringApplication.run(Application.class,

args);

}

}6、寫測(cè)試類進(jìn)行測(cè)試寫個(gè)測(cè)試類進(jìn)行測(cè)試,多次訪問同一個(gè)接口,測(cè)試是否只有第一次能否執(zhí)行成功。import

org.junit.Assert;

import

org.junit.Test;

import

org.junit.runner.RunWith;

import

lombok.extern.slf4j.Slf4j;

import

org.springframework.beans.factory.annotation.Autowired;

import

org.springframework.boot.test.context.SpringBootTest;

import

org.springframework.http.MediaType;

import

org.springframework.test.context.junit4.SpringRunner;

import

org.springframework.test.web.servlet.MockMvc;

import

org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import

org.springframework.test.web.servlet.setup.MockMvcBuilders;

import

org.springframework.web.context.WebApplicationContext;

@Slf4j

@SpringBootTest

@RunWith(SpringRunner.class)

public

class

IdempotenceTest

{

@Autowired

private

WebApplicationContext

webApplicationContext;

@Test

public

void

interfaceIdempotenceTest()

throws

Exception

{

//

初始化

MockMvc

MockMvc

mockMvc

=

MockMvcBuilders.webAppContextSetup(webApplicationContext).build();

//

調(diào)用獲取

Token

接口

String

token

=

mockMvc.perform(MockMvcRequestBuilders.get("/token")

.accept(MediaType.TEXT_HTML))

.andReturn()

.getResponse().getContentAsString();

("獲取的Token串:{}",

token);

//

循環(huán)調(diào)用

5

次進(jìn)行測(cè)試

for

(int

i

=

1;

i

<=

5;

i++)

{

("第{}次調(diào)用測(cè)試接口",

i);

//

調(diào)用驗(yàn)證接口并打印結(jié)果

Str

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論