dubbo高級配置學習(上)


啟動時檢查

Dubbo缺省會在啟動時檢查依賴的服務是否可用,不可用時會拋出異常,阻止Spring初始化完成,以便上線時,能及早發現問題,默認check=true

如果你的Spring容器是懶加載的,或者通過API編程延遲引用服務,請關閉check,否則服務臨時不可用時,會拋出異常,拿到null引用,如果check=false,總是會返回引用,當服務恢復時,能自動連上。

可以通過check="false"關閉檢查,比如,測試時,有些服務不關心,或者出現了循環依賴,必須有一方先啟動。

關閉某個服務的啟動時檢查:(沒有提供者時報錯)

<dubbo:reference

interface="com.foo.BarService"

check="false"

/>

關閉所有服務的啟動時檢查:(沒有提供者時報錯)


<dubbo:consumer

check="false"

/>

關閉注冊中心啟動時檢查:(注冊訂閱失敗時報錯)

<dubbo:registry

check="false"

/>

也可以用dubbo.properties配置:

dubbo.reference.com.foo.BarService.check=false


dubbo.reference.check=false
dubbo.consumer.check=false
dubbo.registry.check=false

也可以用-D參數:

java
 -Ddubbo.reference.com.foo.BarService.check=false
java
 -Ddubbo.reference.check=false
java
 -Ddubbo.consumer.check=false 
java
 -Ddubbo.registry.check=false

注意區別

dubbo.reference.check=false,強制改變所有reference的check值,就算配置中有聲明,也會被覆蓋。

dubbo.consumer.check=false,是設置check的缺省值,如果配置中有顯式的聲明,如:<dubbo:reference check="true"/>,不會受影響。

dubbo.registry.check=false,前面兩個都是指訂閱成功,但提供者列表是否為空是否報錯,如果注冊訂閱失敗時,也允許啟動,需使用此選項,將在后台定時重試。

引用缺省是延遲初始化的,只有引用被注入到其它Bean,或被getBean()獲取,才會初始化。

如果需要飢餓加載,即沒有人引用也立即生成動態代理,可以配置:

<dubbo:reference

interface="com.foo.BarService"

init="true"

/>

集群容錯

在集群調用失敗時,Dubbo提供了多種容錯方案,缺省為failover重試。

各節點關系:

這里的Invoker是Provider的一個可調用Service的抽象,Invoker封裝了Provider地址及Service接口信息。

Directory代表多個Invoker,可以把它看成List<Invoker>,但與List不同的是,它的值可能是動態變化的,比如注冊中心推送變更。

Cluster將Directory中的多個Invoker偽裝成一個Invoker,對上層透明,偽裝過程包含了容錯邏輯,調用失敗后,重試另一個。

Router負責從多個Invoker中按路由規則選出子集,比如讀寫分離,應用隔離等。

LoadBalance負責從多個Invoker中選出具體的一個用於本次調用,選的過程包含了負載均衡算法,調用失敗后,需要重選。

集群容錯模式:

Failover Cluster

失敗自動切換,當出現失敗,重試其它服務器。(缺省)

通常用於讀操作,但重試會帶來更長延遲。

可通過retries="2"來設置重試次數(不含第一次)。

Failfast Cluster

快速失敗,只發起一次調用,失敗立即報錯。

通常用於非冪等性的寫操作,比如新增記錄。

Failsafe Cluster

失敗安全,出現異常時,直接忽略。

通常用於寫入審計日志等操作。

Failback Cluster

失敗自動恢復,后台記錄失敗請求,定時重發。

通常用於消息通知操作。

Forking Cluster

並行調用多個服務器,只要一個成功即返回。

通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。

可通過forks="2"來設置最大並行數。

Broadcast Cluster

廣播調用所有提供者,逐個調用,任意一台報錯則報錯。(2.1.0開始支持)

通常用於通知所有提供者更新緩存或日志等本地資源信息。

重試次數配置如:(failover集群模式生效)


<dubbo:service

retries="2"

/>

或:

<dubbo:reference

retries="2"

/>

或:


<dubbo:reference>


<dubbo:method

name="findFoo"

retries="2"

/>
</dubbo:reference>

集群模式配置如:

<dubbo:service

cluster="failsafe"

/>

或:

<dubbo:reference

cluster="failsafe"

/>

負載均衡

在集群負載均衡時,Dubbo提供了多種均衡策略,缺省為random隨機調用。

Random LoadBalance

隨機,按權重設置隨機概率。

在一個截面上碰撞的概率高,但調用量越大分布越均勻,而且按概率使用權重后也比較均勻,有利於動態調整提供者權重。

RoundRobin LoadBalance

輪循,按公約后的權重設置輪循比率。

存在慢的提供者累積請求問題,比如:第二台機器很慢,但沒掛,當請求調到第二台時就卡在那,久而久之,所有請求都卡在調到第二台上。

LeastActive LoadBalance

最少活躍調用數,相同活躍數的隨機,活躍數指調用前后計數差。

使慢的提供者收到更少請求,因為越慢的提供者的調用前后計數差會越大。

ConsistentHash LoadBalance

一致性Hash,相同參數的請求總是發到同一提供者。

當某一台提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動。

算法參見:http://en.wikipedia.org/wiki/Consistent_hashing。

缺省只對第一個參數Hash,如果要修改,請配置<dubbo:parameter key="hash.arguments" value="0,1" />

缺省用160份虛擬節點,如果要修改,請配置<dubbo:parameter key="hash.nodes" value="320" />

配置如:

<dubbo:service

interface="..."

loadbalance="roundrobin"

/>

或:

<dubbo:reference

interface="..."

loadbalance="roundrobin"

/>

或:

<dubbo:service

interface="...">


<dubbo:method

name="..."

loadbalance="roundrobin"/>


</dubbo:service>

或:

<dubbo:reference

interface="...">


<dubbo:method

name="..."

loadbalance="roundrobin"/>


</dubbo:reference>

線程模型

件處理線程說明

如果事件處理的邏輯能迅速完成,並且不會發起新的IO請求,比如只是在內存中記個標識,則直接在IO線程上處理更快,因為減少了線程池調度。

但如果事件處理邏輯較慢,或者需要發起新的IO請求,比如需要查詢數據庫,則必須派發到線程池,否則IO線程阻塞,將導致不能接收其它請求。

如果用IO線程處理事件,又在事件處理過程中發起新的IO請求,比如在連接事件中發起登錄請求,會報“可能引發死鎖”異常,但不會真死鎖。

Dispatcher

all 所有消息都派發到線程池,包括請求,響應,連接事件,斷開事件,心跳等。

direct 所有消息都不派發到線程池,全部在IO線程上直接執行。

message 只有請求響應消息派發到線程池,其它連接斷開事件,心跳等消息,直接在IO線程上執行。

execution 只請求消息派發到線程池,不含響應,響應和其它連接斷開事件,心跳等消息,直接在IO線程上執行。

connection 在IO線程上,將連接斷開事件放入隊列,有序逐個執行,其它消息派發到線程池。

ThreadPool

fixed 固定大小線程池,啟動時建立線程,不關閉,一直持有。(缺省)

cached 緩存線程池,空閑一分鍾自動刪除,需要時重建。

limited 可伸縮線程池,但池中的線程數只會增長不會收縮。(為避免收縮時突然來了大流量引起的性能問題)。

配置如:

<dubbo:protocol

name="dubbo"

dispatcher="all"

threadpool="fixed"

threads="100"

/>

直連提供者

在開發及測試環境下,經常需要繞過注冊中心,只測試指定服務提供者,這時候可能需要點對點直連,點對點直聯方式,將以服務接口為單位,忽略注冊中心的提供者列表,A接口配置點對點,不影響B接口從注冊中心獲取列表。

(1) 如果是線上需求需要點對點,可在<dubbo:reference>中配置url指向提供者,將繞過注冊中心,多個地址用分號隔開,配置如下:(1.0.6及以上版本支持)

<dubbo:reference
id="xxxService"

interface="com.alibaba.xxx.XxxService"

url="dubbo://localhost:20890"

/>

(2) 在JVM啟動參數中加入-D參數映射服務地址,如:

(key為服務名,value為服務提供者url,此配置優先級最高,1.0.15及以上版本支持)

java
-Dcom.alibaba.xxx.XxxService=dubbo://localhost:20890

注意

為了避免復雜化線上環境,不要在線上使用這個功能,只應在測試階段使用。

(3) 如果服務比較多,也可以用文件映射,如:

(用-Ddubbo.resolve.file指定映射文件路徑,此配置優先級高於<dubbo:reference>中的配置,1.0.15及以上版本支持)

(2.0以上版本自動加載${user.home}/dubbo-resolve.properties文件,不需要配置)

java
-Ddubbo.resolve.file=xxx.properties

然后在映射文件xxx.properties中加入:(key為服務名,value為服務提供者url)

com.alibaba.xxx.XxxService=dubbo://localhost:20890

注意

為了避免復雜化線上環境,不要在線上使用這個功能,只應在測試階段使用。

只訂閱

問題

為方便開發測試,經常會在線下共用一個所有服務可用的注冊中心,這時,如果一個正在開發中的服務提供者注冊,可能會影響消費者不能正常運行。

解決方案

可以讓服務提供者開發方,只訂閱服務(開發的服務可能依賴其它服務),而不注冊正在開發的服務,通過直連測試正在開發的服務。

禁用注冊配置:

<dubbo:registry

address="10.20.153.10:9090"

register="false"

/>

或者:

<dubbo:registry

address="10.20.153.10:9090?register=false"

/>

只注冊

問題

如果有兩個鏡像環境,兩個注冊中心,有一個服務只在其中一個注冊中心有部署,另一個注冊中心還沒來得及部署,而兩個注冊中心的其它應用都需要依賴此服務,所以需要將服務同時注冊到兩個注冊中心,但卻不能讓此服務同時依賴兩個注冊中心的其它服務。

解決方案

可以讓服務提供者方,只注冊服務到另一注冊中心,而不從另一注冊中心訂閱服務。

禁用訂閱配置:

<dubbo:registry

id="hzRegistry"

address="10.20.153.10:9090"

/>
<dubbo:registry

id="qdRegistry"

address="10.20.141.150:9090"

subscribe="false"

/>

或者:

<dubbo:registry

id="hzRegistry"

address="10.20.153.10:9090"

/>
<dubbo:registry

id="qdRegistry"

address="10.20.141.150:9090?subscribe=false"

/>

靜態服務

有時候希望人工管理服務提供者的上線和下線,此時需將注冊中心標識為非動態管理模式。

<dubbo:registry

address="10.20.141.150:9090"

dynamic="false"

/>

或者:

<dubbo:registry

address="10.20.141.150:9090?dynamic=false"

/>

服務提供者初次注冊時為禁用狀態,需人工啟用,斷線時,將不會被自動刪除,需人工禁用。

如果是一個第三方獨立提供者,比如memcached等,可以直接向注冊中心寫入提供者地址信息,消費者正常使用:(通常由腳本監控中心頁面等調用)

RegistryFactory
registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry
registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf

("memcached://10.20.153.11/com.foo.BarService?category=providers&dynamic=false&application=foo"));

多協議

(1) 不同服務不同協議

比如:不同服務在性能上適用不同協議進行傳輸,比如大數據用短連接協議,小數據大並發用長連接協議。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd">

<dubbo:application name="world" />
<dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" />

<!-- 多協議配置 -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="rmi" port="1099" />

<!-- 使用dubbo協議暴露服務 -->
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" protocol="dubbo" />
<!-- 使用rmi協議暴露服務 -->
<dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" protocol="rmi" />

</beans>

(2) 多協議暴露服務

比如:需要與http客戶端互操作

consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <dubbo:application name="world" />
<dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" />

<!-- 多協議配置 -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="hessian" port="8080" />

<!-- 使用多個協議暴露服務 -->
<dubbo:service id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" protocol="dubbo,hessian" />

</beans>

多注冊中心

(1) 多注冊中心注冊

比如:中文站有些服務來不及在青島部署,只在杭州部署,而青島的其它應用需要引用此服務,就可以將服務同時注冊到兩個注冊中心。

consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <dubbo:application name="world" />

<!-- 多注冊中心配置 -->
<dubbo:registry id="hangzhouRegistry" address="10.20.141.150:9090" />
<dubbo:registry id="qingdaoRegistry" address="10.20.141.151:9010" default="false" />

<!-- 向多個注冊中心注冊 -->
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="hangzhouRegistry,qingdaoRegistry" />

</beans>

(2) 不同服務使用不同注冊中心

比如:CRM有些服務是專門為國際站設計的,有些服務是專門為中文站設計的。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <dubbo:application name="world" />

<!-- 多注冊中心配置 -->
<dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" />
<dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" />

<!-- 向中文站注冊中心注冊 -->
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="chinaRegistry" />

<!-- 向國際站注冊中心注冊 -->
<dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" registry="intlRegistry" />

</beans>

(3) 多注冊中心引用

比如:CRM需同時調用中文站和國際站的PC2服務,PC2在中文站和國際站均有部署,接口及版本號都一樣,但連的數據庫不一樣。

consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <dubbo:application name="world" />

<!-- 多注冊中心配置 -->
<dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" />
<dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" />

<!-- 引用中文站服務 -->
<dubbo:reference id="chinaHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="chinaRegistry" />

<!-- 引用國際站站服務 -->
<dubbo:reference id="intlHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="intlRegistry" />

</beans>

如果只是測試環境臨時需要連接兩個不同注冊中心,使用豎號分隔多個不同注冊中心地址:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd">

<dubbo:application name="world" />

<!-- 多注冊中心配置,豎號分隔表示同時連接多個不同注冊中心, 同一注冊中心的多個集群地址用逗號分隔 -->
<dubbo:registry address="10.20.141.150:9090|10.20.154.177:9010" />

<!-- 引用服務 -->
<dubbo:reference id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" />

</beans>

服務分組

當一個接口有多種實現時,可以用group區分。

<dubbo:service

group="feedback"

interface="com.xxx.IndexService"

/>
<dubbo:service

group="member"

interface="com.xxx.IndexService"

/>

任意組:(2.2.0以上版本支持,總是只調一個可用組的實現)

<dubbo:reference

id="feedbackIndexService"

group="feedback"

interface="com.xxx.IndexService"

/>
<dubbo:reference

id="memberIndexService"

group="member"

interface="com.xxx.IndexService"

/>

 

多版本

當一個接口實現,出現不兼容升級時,可以用版本號過渡,版本號不同的服務相互間不引用。

在低壓力時間段,先升級一半提供者為新版本

再將所有消費者升級為新版本

然后將剩下的一半提供者升級為新版本

<dubbo:service

interface="com.foo.BarService"

version="1.0.0"

/>

 

<dubbo:service

interface="com.foo.BarService"

version="2.0.0"

/>

 

<dubbo:reference

id="barService"

interface="com.foo.BarService"

version="1.0.0"

/>

 

<dubbo:reference

id="barService"

interface="com.foo.BarService"

version="2.0.0"

/>

不區分版本:(2.2.0以上版本支持)

<dubbo:reference

id="barService"

interface="com.foo.BarService"

version="*"

/>

分組聚合

按組合並返回結果,比如菜單服務,接口一樣,但有多種實現,用group區分,現在消費方需從每種group中調用一次返回結果,合並結果返回,這樣就可以實現聚合菜單項。

從2.1.0版本開始支持

代碼參見:https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/merge

配置如:(搜索所有分組)

<dubbo:reference

interface="com.xxx.MenuService"

group="*"

merger="true"

/>

或:(合並指定分組)

<dubbo:reference

interface="com.xxx.MenuService"

group="aaa,bbb"

merger="true"

/>

或:(指定方法合並結果,其它未指定的方法,將只調用一個Group)

<dubbo:reference

interface="com.xxx.MenuService"

group="*">
<dubbo:method

name="getMenuItems"

merger="true"

/>
</dubbo:service>

或:(某個方法不合並結果,其它都合並結果)

<dubbo:reference

interface="com.xxx.MenuService"

group="*"

merger="true">
<dubbo:method

name="getMenuItems"

merger="false"

/>
</dubbo:service>

或:(指定合並策略,缺省根據返回值類型自動匹配,如果同一類型有兩個合並器時,需指定合並器的名稱)

參見:[合並結果擴展]

<dubbo:reference

interface="com.xxx.MenuService"

group="*">
<dubbo:method

name="getMenuItems"

merger="mymerge"

/>
</dubbo:service>

或:(指定合並方法,將調用返回結果的指定方法進行合並,合並方法的參數類型必須是返回結果類型本身)

<dubbo:reference

interface="com.xxx.MenuService"

group="*">
<dubbo:method

name="getMenuItems"

merger=".addAll"

/>
</dubbo:service>

參數驗證

參數驗證功能是基於JSR303實現的,用戶只需標識JSR303標准的驗證Annotation,並通過聲明filter來實現驗證。

2.1.0以上版本支持

完整示例代碼參見:https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/validation

驗證方式可擴展,參見:Validation擴展點

參數標注示例:

import

java.io.Serializable;
import

java.util.Date;
import

javax.validation.constraints.Future;
import

javax.validation.constraints.Max;
import

javax.validation.constraints.Min;
import

javax.validation.constraints.NotNull;
import

javax.validation.constraints.Past;
import

javax.validation.constraints.Pattern;
import

javax.validation.constraints.Size;
public

class 
ValidationParameter implements

Serializable {
private

static 
final 
long 
serialVersionUID = 7158911668568000392L;
@NotNull

// 不允許為空
@Size(min
= 1,
max = 20)
//
長度或大小范圍
private

String name;
@NotNull(groups
= ValidationService.Save.class)
//
保存時不允許為空,更新時允許為空 ,表示不更新該字段
@Pattern(regexp
= "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$")
private

String email;
@Min(18)
//
最小值
@Max(100)
//
最大值
private

int 
age;
@Past

// 必須為一個過去的時間
private

Date loginDate;
@Future

// 必須為一個未來的時間
private

Date expiryDate;
public

String getName() {
return

name;
}
public

void 
setName(String name) {
this.name
= name;
}
public

String getEmail() {
return

email;
}
public

void 
setEmail(String email) {
this.email
= email;


}
public

int 
getAge() {
return

age;
}
public

void 
setAge(int

age) {
this.age
= age;
}
public

Date getLoginDate() {
return

loginDate;
}
public

void 
setLoginDate(Date loginDate) {
this.loginDate
= loginDate;
}
public

Date getExpiryDate() {
return

expiryDate;
}
public

void 
setExpiryDate(Date expiryDate) {
this.expiryDate
= expiryDate;
}
}

分組驗證示例:

public

interface 
ValidationService { //
缺省可按服務接口區分驗證場景,如:@NotNull(groups = ValidationService.class)
@interface

Save{} //
與方法同名接口,首字母大寫,用於區分驗證場景,如:@NotNull(groups = ValidationService.Save.class),可選
void

save(ValidationParameter parameter);
void

update(ValidationParameter parameter);
}

分組驗證示例:

import

javax.validation.GroupSequence;

public

interface 
ValidationService {

@GroupSequence(Update.class)
//
同時驗證Update組規則

@interface

Save{}


void

save(ValidationParameter parameter);

@interface

Update{}


void

update(ValidationParameter parameter);

}

參數驗證示例:

import

javax.validation.constraints.Min;
import

javax.validation.constraints.NotNull;
public

interface 
ValidationService {
void

save(@NotNull

ValidationParameter parameter); //
驗證參數不為空
void

delete(@Min(1)
int

id); //
直接對基本類型參數驗證
}

在客戶端驗證參數:

<dubbo:reference

id="validationService"

interface="com.alibaba.dubbo.examples.validation.api.ValidationService"

validation="true"

/>

在服務器端驗證參數:

<dubbo:service

interface="com.alibaba.dubbo.examples.validation.api.ValidationService"

ref="validationService"

validation="true"

/>

驗證異常信息:

import

javax.validation.ConstraintViolationException;
import

javax.validation.ConstraintViolationException;
import

org.springframework.context.support.ClassPathXmlApplicationContext;
import

com.alibaba.dubbo.examples.validation.api.ValidationParameter;
import

com.alibaba.dubbo.examples.validation.api.ValidationService;
import

com.alibaba.dubbo.rpc.RpcException;
public

class 
ValidationConsumer {
public

static 
void 
main(String[] args) throws

Exception {
String
config = ValidationConsumer.class.getPackage().getName().replace('.',
'/')
+ "/validation-consumer.xml";


ClassPathXmlApplicationContext
context = new

ClassPathXmlApplicationContext(config);
context.start();
ValidationService
validationService = (ValidationService)context.getBean("validationService");


//
Error
try

{
parameter
= new

ValidationParameter();
validationService.save(parameter);
System.out.println("Validation
ERROR");
}
catch

(RpcException e) { //
拋出的是RpcException
ConstraintViolationException
ve = (ConstraintViolationException) e.getCause(); //
里面嵌了一個ConstraintViolationException
Set<ConstraintViolation<?>>
violations = ve.getConstraintViolations(); //
可以拿到一個驗證錯誤詳細信息的集合
System.out.println(violations);
}
}
}

需要加入依賴:

 

<dependency>

<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM