
1.前言
https://mp.weixin.qq.com/s/o3SqNXO8BFEq2YsrlcEixA
https://blog.csdn.net/qq_34905631/article/details/137821646?spm=1001.2014.3001.5501
2.代码示例
2.1版本
org.apache.dubbo.rpc.Filter
2.2校验依赖
方式一;<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-validationartifactId><version>2.3.12.RELEASEversion>dependency>方式二;<dependency><groupId>javax.validationgroupId><artifactId>validation-apiartifactId><version>2.0.1.Finalversion>dependency><dependency><groupId>org.hibernategroupId><artifactId>hibernate-validatorartifactId><version>6.2.0.Finalversion>dependency>
2.3自定义DubboValidationFilter
org.apache.dubbo.rpc.Filter
dubboValidationFilter=xx.xx.xxxx.config.DubboValidationFilter
package xxxx.config;import cn.hutool.core.collection.CollectionUtil;import xxxx.RestResponse;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.common.extension.Activate;import org.apache.dubbo.common.utils.ConfigUtils;import org.apache.dubbo.rpc.AsyncRpcResult;import org.apache.dubbo.rpc.Filter;import org.apache.dubbo.rpc.Invocation;import org.apache.dubbo.rpc.Invoker;import org.apache.dubbo.rpc.Result;import org.apache.dubbo.rpc.RpcException;import org.apache.dubbo.validation.Validation;import org.apache.dubbo.validation.Validator;import javax.validation.ConstraintViolation;import javax.validation.ConstraintViolationException;import javax.validation.ValidationException;import java.util.ArrayList;import java.util.List;import java.util.Set;import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;import static org.apache.dubbo.common.constants.FilterConstants.VALIDATION_KEY;/*** zlf*/@Slf4j@Activate(group = {CONSUMER, PROVIDER}, value = VALIDATION_KEY, order = -1)public class DubboValidationFilter implements Filter {private Validation validation;/*** Sets the validation instance for DubboValidationFilter** @param validation Validation instance injected by dubbo framework based on "validation" attribute value.*/public void setValidation(Validation validation) {this.validation = validation;}/*** Perform the validation of before invoking the actual method based on validation attribute value.** @param invoker service* @param invocation invocation.* @return Method invocation result* @throws RpcException Throws RpcException if validation failed or any other runtime exception occurred.*/@Overridepublic Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {if (validation != null && !invocation.getMethodName().startsWith("$")&& ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), VALIDATION_KEY))) {try {Validator validator = validation.getValidator(invoker.getUrl());if (validator != null) {validator.validate(invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());}} catch (RpcException e) {log.error("DubboValidationFilter.RpcException:{}", e.getMessage());throw e;} catch (ValidationException e) {// only use exception's message to avoid potential serialization issueString message = e.getMessage();if (e instanceof ConstraintViolationException) {ConstraintViolationException ex = (ConstraintViolationException) e;// 可能存在多个验证结果 因此组装返回List<String> messageArray = new ArrayList<String>();Set<ConstraintViolation>> constraintViolations = ex.getConstraintViolations();if (CollectionUtil.isNotEmpty(constraintViolations)) {constraintViolations.forEach(constraintViolation -> {messageArray.add(constraintViolation.getMessage());});}message = messageArray.size() == 1 ? messageArray.get(0) : String.join(",", messageArray);}//return AsyncRpcResult.newDefaultAsyncResult(new ValidationException(message), invocation);//这里的RestResponse是业务自己定义的一个响应的类,可以根据自己的需求去新建一个RestResponse类或这个是使用上面注释的代码放开即可,直接抛接口异常给调用方也是可以的return AsyncRpcResult.newDefaultAsyncResult(RestResponse.fail(message), invocation);} catch (Throwable t) {log.error("DubboValidationFilter.Throwable:{}", t.getMessage());return AsyncRpcResult.newDefaultAsyncResult(t, invocation);}}return invoker.invoke(invocation);}}
2.4分组校验
public class ValidationGroups {public interface Update {}public interface Insert {}public interface Detail {}public interface Delete{}}
import org.apache.dubbo.validation.MethodValidated;import javax.validation.constraints.NotNull;public interface xxxApi {//新增接口只校验新增接口的参数RestResponse add( xxxDto dto);//编辑接口校验插入接口的参数和编辑接口的参数RestResponse edit( xxxDto dto);}
package xxx.dto;import com.fasterxml.jackson.databind.annotation.JsonSerialize;import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;import lombok.Data;import javax.validation.constraints.NotBlank;import javax.validation.constraints.NotNull;import java.io.Serializable;@Datapublic class xxxDto implements Serializable {private static final long serialVersionUID = 2328308931670082723L;/*** 主键*/@NotNull(message = "id不为空", groups = {ValidationGroups.Update.class})@JsonSerialize(using = ToStringSerializer.class)private Long id;/*** 登录账号*/@NotBlank(message = "账号不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})private String account;}
package xxx.service.dubbo;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboService;import org.springframework.beans.factory.annotation.Value;import java.util.Objects;@Slf4j@DubboService(version = "${dubbo.application.version}", timeout = 3000, delay = -1, retries = 0, validation = "true", filter = "-validation,dubboValidationFilter")@RequiredArgsConstructorpublic class xxxApiImpl implements xxxApi {@Overridepublic RestResponse add(xxxDto dto) {,,,,,,,,,,,,,,,,,,,,,,return RestResponse.success();}@Overridepublic RestResponse edit(xxxDto dto) {,,,,,,,,,,,,,,,,,,,,,,,,return RestResponse.success();}}
2.5嵌套校验
@Valid
@NotEmpty(message = "List不为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
private ListxDtos;
xxxx2Dto类的字段上也是加参数校验的注解的,实体上的字段都是可以使用validation的校验注解的,根据自己的需求来使用即可。
2.6校验生效的方式
2.6.1yaml配置
dubbo:provider:filter: -validation #排除自带的那个validationFilter,-表示排除validation: true # 服务提供者开启校验consumer:check: falsevalidation: true # 消费者开启校验cloud:: ''scan:: xxx.service.dubboprotocol:name: dubboport: -1registry:address: spring-cloud://localhostapplication:version: 1.0.0
2.6.2服务提供者接口配置
(version = "${dubbo.application.version}", timeout = 3000, delay = -1, retries = 0, validation = "true", filter = "-validation,dubboValidationFilter")public class xxxApiImpl implements xxxApi {}
2.6.3消费调用接口设置
private XxxxApi xxxxApi;