首页 > 其他分享 >自己实现dubbo参数校验(类似RestFul 参数校验)

自己实现dubbo参数校验(类似RestFul 参数校验)

时间:2024-05-30 14:56:19浏览次数:22  
标签:dubbo return 校验 参数 invoker invocation import

1. 场景:

因为工作中经常需要做参数校验,在springboot项目中使用@Valid+@NotNull、@NotBlank…注解开发API接口非常丝滑,相反在开发RPC接口时却还是需要编写大量的参数判断,严重影响主业务流程的开发(公司目前用的是Dubbo2.7.2)且代码整洁度、风格都受到了挑战。基于以上原因萌生了写一个PRC接口的验证,当然新版的dubbo已经支持了调用参数校验。

2. 原理:

因为我们要在consumer调用provider的过程中实现参数校验,而这个逻辑可以做为一个逻辑层,是否联想到AOP?而dubbo提供的filter机制刚好符合我们的要求。校验逻辑可以使用目前主流的校验框架hibernate-validator(省时省力又完善)。

3. 自定义实现:

DubboServiceParameterFilter类是我定义的dubbo filer类,当然作为filter需要使用dubbo的spi机制,在

/META-INF/dubbo/com.alibaba.rpc.Filter文件中添加:

dubboServiceParameterFilter=com.xxxx.filter.DubboServiceParameterFilter

Filter代码:

package com.example.api.demo.config.filter;

import com.google.common.collect.Maps;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.executable.ExecutableValidator;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.rpc.*;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

@Slf4j
@Activate(group = {Constants.PROVIDER}, order = 1)
public class DubboServiceParameterFilter implements Filter {

    // 这段代码创建了一个静态的 ExecutableValidator 实例,用于执行验证操作。它通过 Validation 工具类的 buildDefaultValidatorFactory 方法
    // 获取默认的验证器工厂,并从中获取验证器实例。然后,使用 forExecutables 方法为执行体(executable)创建验证器。
    private static ExecutableValidator executableValidator = Validation.buildDefaultValidatorFactory().getValidator().forExecutables();

    private static final String VALIDATOR_MESSAGE = "参数验证失败";

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) {

        log.info("===================== param filter ========================");
        Method method = getMethod(invoker, invocation);
        if (Objects.nonNull(method)) {
            Class inf = invoker.getInterface();
            Object object = ServiceBean.getSpringContext().getBean(inf);
            Object[] paramList = invocation.getArguments();
            Set<ConstraintViolation<Object>> constraintViolations = executableValidator.validateParameters(object, method, paramList);
            Response response = getValidationResult(constraintViolations);
            if (Objects.nonNull(response.getData())) {
                return new RpcResult(response);
            }
        }
        return invoker.invoke(invocation);
    }

    /**
     * 获取校验方法
     */
    private static Method getMethod(Invoker<?> invoker, Invocation invocation) {

        Method[] methods = invoker.getInterface().getDeclaredMethods();
        for (Method m : methods) {
            boolean needCheck = m.getName().equals(invocation.getMethodName()) && invocation.getArguments().length == m.getParameterCount();
            if (needCheck) {
                if (matchMethod(invocation.getParameterTypes(), m.getParameterTypes())) {
                    return m;
                }
            }
        }
        return null;
    }

    //获取匹配的方法
    private static boolean matchMethod(Class[] invokerMethodParamClassList, Class[] matchMethodParamClassList) {
        for (int i = 0; i < invokerMethodParamClassList.length; i++) {
            if (!invokerMethodParamClassList[i].equals(matchMethodParamClassList[i])) {
                return false;
            }
        }
        return true;
    }

    /**
     * 校验结果转换返回对象
     */
    private static <T> Response getValidationResult(Set<ConstraintViolation<T>> set) {
        if (set != null && !set.isEmpty()) {
            Map<String, String> errorMsg = Maps.newHashMap();
            for (ConstraintViolation<T> violation : set) {
                errorMsg.put(violation.getPropertyPath().toString(), violation.getMessage());
            }
            return Response.createError(VALIDATOR_MESSAGE, errorMsg);
        }
        return Response.createError(VALIDATOR_MESSAGE);
    }
}

 

标签:dubbo,return,校验,参数,invoker,invocation,import
From: https://www.cnblogs.com/lgg20/p/18222334

相关文章

  • Postman秘籍:掌握Query、Path和Body参数的艺术
    在当今的网络开发领域,API(应用程序编程接口)测试已成为确保软件质量和功能性的关键环节。Postman,作为一个功能强大的API测试工具,已经成为许多开发者和测试人员日常工作的一部分。本文将深入探讨如何使用Postman传递请求参数,包括Query、Path和Body参数,并通过实际示例来加强理解......
  • dubbo~javax.validation和jakarta.validation的介绍与排雷
    javax.validation和jakarta.validation都是用于Java中进行数据验证(validation)的相关API,它们提供了一套标准的验证框架,用于验证Java对象的属性是否符合指定的约束条件。这两个API的作用类似,只是在JavaEE平台的演进过程中发生了一些变化。javax.validation:javax.validation是最......
  • 机器学习_参数调优
    参数调优(HyperparameterTuning)是机器学习模型优化过程的重要部分,通过调整模型的超参数来提升其性能。以下详细讲解如何进行参数调优,并提供相应的代码实例。1.什么是超参数?超参数是在训练之前设置的参数,不同于模型训练过程中学到的参数(如权重)。决策树和随机森林的超参数......
  • for循环外创建一个http请求对象,循环内赋值参数多次请求返回数据相同定位及解决(共用一
    一次项目线上问题定位,发现多次不同参数请求值相同,直接上代码List<String>list=newArrayList<>();list.add("85657218,上海奉贤恒盛湖畔豪庭xxx号xxx");list.add("85657219,上海虹口虬江支路xxx弄xxx室");if(CollectionUtil.isNotEmpty(list))......
  • 成为MySQL DBA后,再看ORACLE数据库(三、参数管理)
    一、参数文件在ORACLE11g及以后的版本中,ORACLE使用spfile作为数据库的参数文件,这是一个二进制文件,不能通过手工修改。SPFILE的引入使得对于参数的修改都可以在命令行完成,不需要手工修改,这也是为了减少了人为错误的发生。而在MySQL中,需要去手工维护my.cnf参数文件,主要原因是在MyS......
  • SAP:观察I_CALLBACK_USER_COMMAND 参数(按钮点击事件)
    1、从函数级SLVC_FULLSCREEN里复制 一个在”GUI状态“ 下的“STANDARD_FULLSCREEN”标准全屏幕到 程序Z16_04里。 标准工具添加 定义按钮(关闭、保存)主程序代码:*&---------------------------------------------------------------------**&ReportZ16_04*&利用......
  • filebeat配置参数add_kubernetes_metadata
    在Kubernetes集群中,我们可以使用Filebeat来从容器中收集日志,并为每个日志事件添加Kubernetes相关的元数据信息,例如Pod名称、命名空间、标签等。这样我们就可以更好地分析和理解日志数据。filebeat.inputs:-type:containerpaths:-/var/log/containers/*.log......
  • Dockerfile - 参数与详解
    只有FROM时必须的#在当前路径下构建test镜像,执行Dockerfile文件dockerbuild-ttest.1.FROM制定基于那个镜像进行构建FROMalpine:latest2.WORKDIR指定工作目录,执行shell脚本的工作目录WORKDIR/app3.COPYADD复制文件,将宿主机文件拷贝到镜像中ADD可以是网络资......
  • anova 的替代非参数方法
    Kruskal-Wallis测试是一种非参数方法,用于比较三个或更多个独立样本的中位数是否存在显著差异。在R语言中,你可以使用kruskal.test()函数来执行Kruskal-Wallis测试。以下是使用kruskal.test()函数的基本步骤:准备数据:确保你的数据是向量或因子形式,并且每个向量代表一个组。......
  • ts拯救前端:优雅的在运行时校验后端接口返回数据类型 typescript-json-schema+ ajv
    包管理器:pnpm环境:node依赖:typescript-json-schema、ajv准备工作1、安装依赖pnpmaddtypescript-json-schemapnpmaddajv2、准备需要校验的数据类型//userType.tsexportinterfaceUser{id:string;token:string;nick?:string;}3、使用typescrip......