启动时检查

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>

dubbo高级配置学习(上)的更多相关文章

  1. dubbo高级配置学习

    启动时检查 可以通过check="false"关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动. 关闭某个服务的启动时检查:(没有提供者时报错) < ...

  2. DUBBO高级配置:多注册中心配置

    有时候我们需要的服务不在同一个 zookeeper 注册中心上,此时我们需要在 DUBBO 配置文件中配置多个注册中心. 下面我们在之前创建项目的基础上在 provider 模块中增加一个 IBook ...

  3. MySQL学习笔记_9_MySQL高级操作(上)

    MySQL高级操作(上) 一.MySQL表复制 create table t2 like t1;               #复制表结构,t2可以学习到t1所有的表结构 insert into t2 ...

  4. ASP.NET Aries 高级开发教程:Excel导入之单表配置(上)

    前言: 随着ASP.NET Aries的普及,刚好也有点闲空,赶紧把Excel导入功能的教程补上. Excel导入功能,分为四篇:单表配置(上).多表高级配置(中).配置规则(下).代码编写(番外篇) ...

  5. [转]JEXUS的高级配置

    转自:http://www.cnblogs.com/xiaodiejinghong/archive/2013/04/14/3019660.html 前一回合,我们对服务器软件Jexus作了简单的介绍, ...

  6. Cisco ASA 高级配置

    Cisco ASA 高级配置 一.防范IP分片攻击 1.Ip分片的原理: 2.Ip分片的安全问题: 3.防范Ip分片. 这三个问题在之前已经详细介绍过了,在此就不多介绍了.详细介绍请查看上一篇文章:I ...

  7. 【Dubbo&&Zookeeper】5、dubbo总结和学习资料汇总

    Dubbo学习资料 阿里巴巴分布式服务框架 Dubbo 团队成员梁飞专访 RPC介绍 什么是RPC? RPC(Remote Procedure Call)远程过程调用.见名知意 - 从远程主机调用一个 ...

  8. Tomcat基础配置和高级配置

    **********  第一部分 Tomcat基础配置   *********** 一.Apatch Tomcat 在win下配置 大部分转载自:http://blog.csdn.net/liuhao ...

  9. dubbo框架设计学习

    1.整体设计 (1)架构图 图例说明: 图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口. 图中从下至上分为十层,各层均为单向依赖,右 ...

随机推荐

  1. 限制EditText必须输入中文的方法

    给EditText做限制时,我们想要输入的字符串必须都是中文,不出现任何其他字符,下面的类可以很好的实现这个要求. InputLenLimit.java package com.kale.button ...

  2. linux 7z 命令编译安装,mac安装p7zip

    linux 7z 命令编译安装 7zip是一个开源的压缩软件  7z格式是压缩率最高的格式 服务器备份 数据几个g 要是tar压缩下载的话 时间太长  7zip压缩出来体积很小 首先安装 我这是 ce ...

  3. Spring Test, JUnit, Mockito, Hamcrest 集成 Web 测试

    关于Spring 3.2 1. Spring 3.2 及以上版本自动开启检测URL后缀,设置Response content-type功能, 如果不手动关闭这个功能,当url后缀与accept头不一致 ...

  4. IDEA 快速将spring boot项目打包成jar包,简单快速有效

    原文地址;https://blog.csdn.net/chen846262292/article/details/80701101  https://www.cnblogs.com/chrischen ...

  5. Error:(13, 60) java: 程序包com.sun.tools.internal.xjc.reader.xmlschema.bindinfo不存在

    我在import maven项目时,pom.xml报错Missing artifact com.sun:tools:jar:1.5.0,经过盘查发现是pom引入的struts2相关jar包导致报错. ...

  6. JUnit 入门

    JUNIT了解学习 转自:关于Java单元测试,你需要知道的一切 转自:JUnit 入门教程 JUnit高级用法之@RunWith @RunWith 关于@RunWith注解,官方文档是这么描述的: ...

  7. 怎样修改SQL Server 2005/2008的系统存储过程(转)

    我们知道,SQL Server 2005/2008的系统存储过程在正常情况下是无法直接修改的. 尽管本文是介绍怎样修改它的,但在这里,我还是建议大家尽量不要去修改它.(好像有点绕哈...) OK,闲话 ...

  8. Pycharm安装详细教程

    今天小编给大家分享如何在本机上下载和安装Pycharm,具体的教程如下: 1.首先去Pycharm官网,或者直接输入网址:http://www.jetbrains.com/pycharm/downlo ...

  9. Android -- com.android.providers.media,external.db

    external.db android是管理多媒体文件(音频.视频.图片)的信息是在/data/data/com.android.providers.media下的数据库文件external.db. ...

  10. 推荐系统resys小组线下活动见闻2009-08-22

    http://www.tuicool.com/articles/vUvQVn 时间2009-08-30 15:13:22  不周山原文  http://www.wentrue.net/blog/?p= ...