写在前面

本文在这篇文章 基础上改造进行测试。

dubbo的参数验证基于JSR303规范就是定义了校验注解,错误信息如何提示等的规范,我们只需要使用规定的注解,并声明Filter就可以了。
源码

1:改造rpc-service-api

1.1:引入依赖

1 <dependencies>
 2     <!-- 参数校验相关依赖 -->
 3     <!-- JSR303参数校验相关对应规范API -->
 4     <dependency>
 5         <groupId>javax.validation</groupId>
 6         <artifactId>validation-api</artifactId>
 7         <version>2.0.1.Final</version>
 8     </dependency>
 9     <!-- JSR 参数校验规范实现,我们使用 hibernate-validator,注意:仅仅是个实现,不要被hibernate关键字干扰了,即不操作数据库!!! -->
10     <dependency>
11         <groupId>org.hibernate.validator</groupId>
12         <artifactId>hibernate-validator</artifactId>
13         <version>6.0.18.Final</version>
14     </dependency>
15     <!-- 可能涉及到 EL 表达,所以引入,否则 hibernate-validator 在初始化会报错 -->
16     <dependency>
17         <groupId>org.glassfish</groupId>
18         <artifactId>javax.el</artifactId>
19         <version>3.0.1-b11</version>
20     </dependency>
21 </dependencies>

1.2:UserAddDTO

1 public class UserAddDTO implements Serializable {
 2     /**
 3      * 昵称
 4      */
 5     @NotEmpty(message = "昵称不能为空")
 6     @Length(min = 5, max = 16, message = "账号长度为 5-16 位")
 7     private String name;
 8     /**
 9      * 性别
10      */
11     @NotNull(message = "性别不能为空")
12     private Integer gender;
13 
14     // getter setter tostring
15 }

1.3:UserRpcService

1 public interface UserRpcService {
 2 
 3     /**
 4      * 根据指定用户编号,获得用户信息
 5      *
 6      * @param id 用户编号
 7      * @return 用户信息
 8      */
 9     UserDTO get(@NotNull(message = "用户编号不能为空") Integer id)
10             throws ConstraintViolationException;
11 
12     /**
13      * 添加新用户,返回新添加的用户编号
14      *
15      * @param addDTO 添加的用户信息
16      * @return 用户编号
17      */
18     Integer add(UserAddDTO addDTO)
19             throws ConstraintViolationException;
20 }

注意在方法中抛出ConstraintViolationException的原因是参数校验不通过时会抛出该异常,所以这里抛出提供给用户查看错误信息。

2:改造rpc-service-provider

2.1:UserRpcServiceImpl

1 @Service
 2 public class UserRpcServiceImpl implements UserRpcService {
 3 
 4     @Override
 5     public UserDTO get(Integer id) {
 6         /*return new UserDTO().setId(id)
 7                 .setName("没有昵称:" + id)
 8                 .setGender(id % 2 + 1); // 1 - 男;2 - 女*/
 9         UserDTO userDTO = new UserDTO();
10         userDTO.setId(id);
11         userDTO.setName("没有昵称:" + id);
12         userDTO.setGender(id % 2 + 1);
13         return userDTO;
14     }
15 
16     @Override
17     public Integer add(UserAddDTO addDTO) {
18         return (int) (System.currentTimeMillis() / 1000); // 嘿嘿,随便返回一个 id
19     }
20 
21 }

2.2:dubbo.xml

<!-- 服务提供者暴露服务配置 -->
<dubbo:service ref="userRpcServiceImpl" interface="dongshi.daddy.api.UserRpcService"
               version="${dubbo.provider.UserRpcService.version}" validation="true"/>

增加了validation="true"开启服务提供者端的参数校验,如果是参数校验不通过则抛出ConstraintViolationException。

可以通过在application.yml中配置dubbo.provider.validation = true开启服务提供者所有service的参数校验。

3:改造rpc-service-consumer

3.1:dubbo.xml

<!-- 服务消费者引用服务配置 -->
<dubbo:reference id="userService" interface="dongshi.daddy.api.UserRpcService"
                 version="${dubbo.consumer.UserRpcService.version}" validation="true"/>

通过validation="true"开启服务消费者的参数校验。

3.2:触发异常执行类

1 @Component
 2 public class UserRpcServiceTest02 implements CommandLineRunner {
 3 
 4     private final Logger logger = LoggerFactory.getLogger(getClass());
 5 
 6     @Resource
 7     private UserRpcService userRpcService;
 8 
 9     @Override
10     public void run(String... args) throws Exception {
11         // 获得用户
12         try {
13             // 发起调用
14             UserDTO user = userRpcService.get(null); // 故意传入空的编号,为了校验编号不通过
15             logger.info("[run][发起一次 Dubbo RPC 请求,获得用户为({})]", user);
16         } catch (Exception e) {
17             logger.error("[run][获得用户发生异常,信息为:[{}]", e.getMessage());
18         }
19 
20         // 添加用户
21         try {
22             // 创建 UserAddDTO
23             UserAddDTO addDTO = new UserAddDTO();
24             // 故意把名字打的特别长,为了校验名字不通过
25             addDTO.setName("dongshidaddydongshidaddydongshidaddydongshidaddy");
26             // 不传递性别,为了校验性别不通过
27             addDTO.setGender(null);
28             // 发起调用
29             userRpcService.add(addDTO);
30             logger.info("[run][发起一次 Dubbo RPC 请求,添加用户为({})]", addDTO);
31         } catch (Exception e) {
32             logger.error("[run][添加用户发生异常,信息为:[{}]", e.getMessage());
33         }
34     }
35 
36 }

3.3:执行

如下红框中是错误执行触发的异常信息,蓝色框是正常的调用:

dubbo支持python dubbo parameter_dubbo

 

注:

validation也可以直接在统一provider(dubbo.provider.validation)的配置中加,这样全局的provider就可以了。