Dubbo是阿里開源的一個高效能的RPC服務框架,我平時接觸Dubbo介面極多,並且也會為不同業務需求開發Dubbo介面。專案有用到Dubbo作為RPC呼叫的同學可以看看我這篇文章,做到簡單高效的呼叫測試任意Dubbo介面。

最開始我測試Dubbo介面的時候是啟動整個專案後透過postman等呼叫Controller介面來間接測試Dubbo介面,或者使用別人提供的Dubbo介面時,由於有時候對介面返回的資料結構不夠清楚,因此也得透過像前面那樣啟動專案來間接呼叫檢視返回結果,這樣及其浪費時間,且效率低下。

後面我開始寫單元測試來測Dubbo介面,這樣效率稍微高些,但是也有個弊端,就是每次修改請求引數時都得重新執行單元測試,由於現在專案一般都不會很小,所有每次執行單元測試時也挺消耗時間的,大專案的話簡直考驗人的耐心。為了解決這些問題,我深入研究了Dubbo,並找了不少資料,終於讓我找到一個簡便的方法來測試。

只需要兩個類:

測試類DubboTest:

/**

* @author yudong

* @date 2019/6/13

*/

public

class

DubboTest

{

@AfterClass

public

static

void

exit

()

{

System

exit

0

);

}

@Test

public

void

test

()

{

// UserDubboService是已經註冊到zookeeper註冊中心的Dubbo服務,這裡不指定呼叫特定服務例項

UserDubboService

service

=

DubboUtils

getService

UserDubboService

class

“1。0。0”

);

UserBaseDto

userBaseDto

=

service

getByUsername

“1050106266”

);

System

out

println

userBaseDto

);

// 如果是呼叫測試本地Dubbo介面,只需要把專案啟動起來,然後就可以在這裡隨意修改請求引數測試,非常方便

// 這裡指定呼叫此127。0。0。1地址提供的Dubbo服務

service

=

DubboUtils

getService

UserDubboService

class

“1。0。0”

“127。0。0。1:21899”

);

userBaseDto

=

service

getByUsername

“1050106266”

);

System

out

println

userBaseDto

);

}

}

其中DubboUtils類的定義:

/**

* @author yudong

* @date 2019/6/13

*/

public

class

DubboUtils

{

/**

* dubbo服務的zookeeper註冊中心地址

*/

private

static

final

String

ZOOKEEPER_ADDRESS

=

“zookeeper://127。0。0。1:2181”

public

static

<

T

>

T

getService

Class

<

T

>

dubboServiceClass

String

version

{

return

getService

dubboServiceClass

version

null

);

}

@SuppressWarnings

“ALL”

public

static

<

T

>

T

getService

Class

<

T

>

dubboServiceClass

String

version

String

host

{

Enhancer

enhancer

=

new

Enhancer

();

enhancer

setSuperclass

dubboServiceClass

);

enhancer

setCallback

((

MethodInterceptor

obj

method

args

proxy

->

{

ReferenceConfig

<

GenericService

>

reference

=

getReferenceConfig

dubboServiceClass

version

host

);

GenericService

genericService

=

reference

get

();

return

genericService

$invoke

method

getName

(),

getMethodParamType

method

),

args

);

});

Object

service

=

enhancer

create

();

return

T

service

}

private

static

<

T

>

ReferenceConfig

<

T

>

getReferenceConfig

Class

<?>

interfaceClass

String

version

String

host

{

String

referenceKey

=

interfaceClass

getName

();

ReferenceConfig

<

T

>

referenceConfig

=

new

ReferenceConfig

<>();

referenceConfig

setApplication

getApplicationConfig

());

referenceConfig

setRegistry

getRegistryConfig

());

referenceConfig

setInterface

interfaceClass

);

referenceConfig

setVersion

version

);

referenceConfig

setTimeout

8000

);

referenceConfig

setGeneric

true

);

if

StringUtils

isNotBlank

host

))

{

String

url

=

String

format

“dubbo://%s/%s”

host

referenceKey

);

referenceConfig

setUrl

url

);

}

return

referenceConfig

}

private

static

RegistryConfig

getRegistryConfig

()

{

RegistryConfig

registryConfig

=

new

RegistryConfig

();

registryConfig

setAddress

DubboUtils

ZOOKEEPER_ADDRESS

);

return

registryConfig

}

private

static

ApplicationConfig

getApplicationConfig

()

{

ApplicationConfig

application

=

new

ApplicationConfig

();

application

setName

“b2c-test”

);

return

application

}

private

static

String

[]

getMethodParamType

Method

method

{

Class

<?>[]

paramClassList

=

method

getParameterTypes

();

String

[]

paramTypeList

=

new

String

paramClassList

length

];

for

int

i

=

0

i

<

paramClassList

length

i

++)

{

paramTypeList

i

=

paramClassList

i

]。

getTypeName

();

}

return

paramTypeList

}

}

這樣子就能夠方便呼叫任意Dubbo介面啦

下面我分析下是怎麼實現的,核心方法是這個:

@SuppressWarnings

“ALL”

public

static

<

T

>

T

getService

Class

<

T

>

dubboServiceClass

String

group

String

version

String

host

{

Enhancer

enhancer

=

new

Enhancer

();

enhancer

setSuperclass

dubboServiceClass

);

enhancer

setCallback

((

MethodInterceptor

obj

method

args

proxy

->

{

ReferenceConfig

<

GenericService

>

reference

=

getReferenceConfig

dubboServiceClass

group

version

host

);

GenericService

genericService

=

reference

get

();

Object

result

=

genericService

$invoke

method

getName

(),

getMethodParamType

method

),

args

);

String

resJsonStr

=

OMUtils

objectMapper

()。

writeValueAsString

result

);

return

OMUtils

objectMapper

()。

readValue

resJsonStr

method

getReturnType

());

});

Object

service

=

enhancer

create

();

return

T

service

}

GenericService

是dubbo官方提供的通用服務介面,裡面有個方法:

$invoke(String method, String[] parameterTypes, Object[] args)可用來做泛化呼叫。這個方法比較難用,所以我使用cglib(Enhancer)建立了一個代理來簡化這個泛化呼叫操作,就像我們正常呼叫dubbo API那樣的寫法,詳細用法請看DubboTest類。

原始碼github地址和gitee地址(程式碼同步):