zoukankan      html  css  js  c++  java
  • dubbo源码阅读-Filter默认实现(十一)之ValidationFilter

    API文档

    http://dubbo.apache.org/zh-cn/docs/user/demos/parameter-validation.html

    ValidationFilter

    /**
     * ValidationFilter consumer和Provider使用 含有validation 排序10000
     */
    @Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, value = Constants.VALIDATION_KEY, order = 10000)
    public class ValidationFilter implements Filter {
    
        /**
         * SPI扩展
         * 通过 Dubbo SPI 机制,调用 {@link #setValidation(Validation)} 方法,进行注入
         * 注入时机:https://www.cnblogs.com/LQBlog/p/12453900.html#autoid-8-14-0
         */
        private Validation validation;
    
        public void setValidation(Validation validation) {
            this.validation = validation;
        }
    
        @Override
        public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
            //含有validation 参数
            if (validation != null && !invocation.getMethodName().startsWith("$")
                    && ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.VALIDATION_KEY))) {
                try {
                    //或缺的Validator
                    Validator validator = validation.getValidator(invoker.getUrl());
                    if (validator != null) {
                        //执行验证
                        validator.validate(invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
                    }
                } catch (RpcException e) {
                    throw e;//注意都是抛出的PRCException
                } catch (Throwable t) {
                    //注意抛出的都是RPCException
                    return new RpcResult(t);
                }
            }
            return invoker.invoke(invocation);
        }
    
    }

    Validation

    接口定义

    /**
     * Validation
     */
    @SPI("jvalidation")
    public interface Validation {
    
        /**
         * 缺省值为jvalidation
         * @param url
         * @return
         */
        @Adaptive(Constants.VALIDATION_KEY)
        Validator getValidator(URL url);
    
    }

    AbstractValidation

    /**
     * AbstractValidation
     */
    public abstract class AbstractValidation implements Validation {
    
        private final ConcurrentMap<String, Validator> validators = new ConcurrentHashMap<String, Validator>();
    
        @Override
        public Validator getValidator(URL url) {
            //从缓存获取Validator
            String key = url.toFullString();
            Validator validator = validators.get(key);
            if (validator == null) {
                validators.put(key, createValidator(url));
                validator = validators.get(key);
            }
            return validator;
        }
    
        /**
         * 模板方法模式 由子类创建
         * @param url
         * @return
         */
        protected abstract Validator createValidator(URL url);
    
    }

    JValidation

    /**
     * JValidation
     */
    public class JValidation extends AbstractValidation {
    
        @Override
        protected Validator createValidator(URL url) {
            //返回JValidator
            return new JValidator(url);
        }
    
    }

    JValidator

     @Override
        public void validate(String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Exception {
            List<Class<?>> groups = new ArrayList<Class<?>>();
            String methodClassName = clazz.getName() + "$" + toUpperMethoName(methodName);
            Class<?> methodClass = null;
            try {
                // 验证分组集合
                methodClass = Class.forName(methodClassName, false, Thread.currentThread().getContextClassLoader());
                groups.add(methodClass);
            } catch (ClassNotFoundException e) {
            }
            Set<ConstraintViolation<?>> violations = new HashSet<ConstraintViolation<?>>();
            //反射获得对应的方法
            Method method = clazz.getMethod(methodName, parameterTypes);
            Class<?>[] methodClasses = null;
            //是否含有MethodValidated 注解 表示我们可以通过MethodValidated 设置验证的group
            if (method.isAnnotationPresent(MethodValidated.class)){
                methodClasses = method.getAnnotation(MethodValidated.class).value();
                //添加group
                groups.addAll(Arrays.asList(methodClasses));
            }
            // add into default group
            groups.add(0, Default.class);
            groups.add(1, clazz);
    
            // convert list to array
            Class<?>[] classgroups = groups.toArray(new Class[0]);
    
            //貌似是自定义校验注解 https://blog.csdn.net/lwg_1540652358/article/details/84193759
            Object parameterBean = getMethodParameterBean(clazz, method, arguments);
            if (parameterBean != null) {
                //进行验证
                violations.addAll(validator.validate(parameterBean, classgroups ));
            }
            //验证参数
            for (Object arg : arguments) {
                validate(violations, arg, classgroups);
            }
    
            if (!violations.isEmpty()) {
                logger.error("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations);
                throw new ConstraintViolationException("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations, violations);
            }
        }

    使用例子 

    我这里采用的是属性配置

    1.pom依赖

       <dependencies>
            <dependency>
                <groupId>javax.validation</groupId>
                <artifactId>validation-api</artifactId>
                <version>1.1.0.Final</version>
            </dependency>
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>5.1.1.Final</version>
            </dependency>
            <dependency>
                <groupId>javax.el</groupId>
                <artifactId>javax.el-api</artifactId>
                <version>3.0.0</version>
            </dependency>
    
    
            <dependency>
                <groupId>org.glassfish</groupId>
                <artifactId>javax.el</artifactId>
                <version>3.0.0</version>
            </dependency>
    
        </dependencies>

    2.vo配置 更多配置看文档

    public class TestVo implements Serializable {
        @NotNull(message = "名字不能为空")
        @Min(value = 6, message = "昵称不能太短")
        public java.lang.String name;
    
        public java.lang.String password;
    
    
    }

    3.propertis配置

    dubbo.application.parameters['validation']=jvalidation

    4.校验不过打印

  • 相关阅读:
    MongoDB查询修改操作语句命令大全
    SpringBoot读取war包jar包Resource资源文件解决办法
    linux lsof命令详解
    taskset
    POI导出excel,本地测试没问题,linux测试无法导出
    js中文乱码
    处理Account locked due to 217 failed logins的问题
    普通用户无法su到root用户
    gp数据库停止
    eclipse导入maven工程missing artifact(实际是存在的)错误解决
  • 原文地址:https://www.cnblogs.com/LQBlog/p/12504399.html
Copyright © 2011-2022 走看看