dubbo的SPI扩展是有关于参数校验的SP扩展,校难的原理其实也是用的拦截器原理。dubbo包有一个
ValidationFilter的拦截器实现。dubbo是有自己的校验器实现的JValidator,如果需要自定义的话,则需要实现
Validation接口
@SPI("jvalidation")
public interface Validation {
@Adaptive({"validation"})
Validator getValidator(URL var1);
}
首先编写自定义的校验器。实现Validation接口。再编写自己的校验者。让自定义的校验器指定检验者为自定义的校验者。我这里检验者继承了原生的JValidator校验。也可以自己实现Validator进行自己完全的自定义。当有检验异常的时候,报出自定义的异常。再使用dubbo的的拦截器机制捕捉自定义异常。就进行自定义异常结果处理了。
public class FlashValidation implements Validation {
@Override
public Validator getValidator(URL url) {
return new FlashValidator(url);
}
}
public class FlashValidator extends JValidator {
public FlashValidator(URL url) {
super(url);
}
@Override
public void validate(String s, Class<?>[] classes, Object[] objects) throws Exception {
try {
super.validate(s, classes, objects);
} catch (Exception e) {
if (e instanceof ConstraintViolationException) {
ConstraintViolation constraintViolation = ((ConstraintViolationException) e).getConstraintViolations().stream().findFirst().get();
throw new ParamValidationException(constraintViolation.getMessageTemplate());
} else {
throw e;
}
}
}
}
还需要创建文件META-INF/dubbo/com.alibaba.dubbo.validation.Validation, 编辑内容为自己拦截器
xxxValidation=com.xxx.xxx.validation.FlashValidation
那么在服务注册的时候指定校验器,同理消费者进行校验的话,需要在service注入的时候指定validation。
这里建议是消费方开启参数校验就行了。这样还没有进行网络传输的时候进行校验,如果失败了。也减少了不必要的网络传输。
//@Service(group = "order", version = "1.0", timeout = 60000,validation = "true")
//validation = "true" 这里如果写true则调用的就是dubbo默认的参数校验处理JValidator
@Service(group = "order", version = "1.0", timeout = 60000,validation = "ParamValidation")
public class OrderServiceImpl implements OrderService {
//...
}
@Reference(group = "order", version = "1.0.0", timeout = 30000,validation = "ParamValidation")
OrderService orderService;
被校验的实体对象需要加上注解validation
//实体对象
public class Order{
//这里指定校验的所属组。
@NotNull(groups = {AppService.AddAppInfo.class}, message = "责任人名称为空")
private String liableUserName;
}
//服务接口
public interface OrderService {
//这里用interface注解指定一个接口当作参数校验的一个接口。那么标注了这个组的validation注解。调用此方式就会进行校验
@interface AddAppInfo {}
SystemAppInfo addAppInfo(Order order);
@interface GetAppList {}
List<SystemAppInfo> getAppList();
}