最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

dubbo參數(shù)校驗ValidationFilter使用與說明

 更新時間:2025年10月20日 10:08:31   作者:hello_zzw  
本文介紹了Dubbo框架中Filter的核心功能和實現(xiàn)機制,Filter用于攔截RPC調(diào)用流程,支持自定義攔截邏輯,并通過SPI擴展機制動態(tài)加載,形成鏈式調(diào)用結(jié)構(gòu),文中還說明了內(nèi)置和自定義Filter的實現(xiàn)方式及ValidationFilter參數(shù)校驗功能

org.apache.dubbo.rpc.Filter

核心功能

  • 攔截RPC調(diào)用流程

Filter是Dubbo框架中實現(xiàn)攔截邏輯的核心接口,作用于服務(wù)消費者和提供者的作業(yè)鏈路,支持在方法調(diào)用前后插入自定義邏輯。如參數(shù)校驗、異常處理、日志記錄等。

  • 擴展性機制

Dubbo通過SPI擴展機制動態(tài)加載Filter實現(xiàn)類,構(gòu)建鏈式調(diào)用結(jié)構(gòu),每個Filter通過Invoke方案傳遞調(diào)用上下文,最終執(zhí)行目標方法。

實現(xiàn)機制

  • 責任鏈模式

Provider端Filter鏈在服務(wù)暴露時通過FilterChainBuilder#buildInvokerChain方法構(gòu)建,基于SPI配置按優(yōu)先級排序,形成多層攔截邏輯。

  • SPI加載規(guī)則

Filter實現(xiàn)類需要在META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter文件中聲明,并通過@Activate注解配置激活條件(如服務(wù)端/消費端)

  • 動態(tài)加載

Filter鏈在服務(wù)初始化階段動態(tài)生成,通過ExtensionLoader加載所有激活的Filter實例,并按順序包裝成調(diào)用鏈。

常見內(nèi)置Filter實現(xiàn)

Filter名稱功能描述適用端
ExceptionFilter統(tǒng)一處理服務(wù)端異常,將非受檢異常封裝為RuntimeException返回客戶端Provider
ValidationFilter基于JSR303標準校驗接口參數(shù)合法性Both
AccessLogFilter記錄服務(wù)調(diào)用日志,指定輸出到指定文件Provider
TimeoutFilter監(jiān)控方法執(zhí)行超時,觸發(fā)超時中斷邏輯Provider
GenericFilter處理泛化調(diào)用的序列化與反序列化Both

自定義Filter實現(xiàn)步驟

  • 實現(xiàn)Filter接口
import com.alibaba.fastjson2.JSON;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// 使用@Activate注解指定Filter生效場景
// order屬性控制執(zhí)行順序,值越小,優(yōu)先級越高
@Activate(group = {CommonConstants.CONSUMER, CommonConstants.PROVIDER}, order = 10001)
public class CustomFilter implements Filter {
    private Logger logger = LoggerFactory.getLogger(CustomFilter.class);
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        logger.info("invoker invoked method {} {} {} {}",
                invocation.getMethodName(),
                JSON.toJSONString(invocation.getObjectAttachments()),
                invocation.getAttributes(),
                JSON.toJSONString(invocation.getArguments()));
        Result result = invoker.invoke(invocation);
        logger.info("invoker invoked result {}", JSON.toJSONString(result));
        return result;
    }
}
  • ‌聲明SPI擴展‌

在resources/META-INF/dubbo目錄下創(chuàng)建配置文件org.apache.dubbo.rpc.Filter,添加自定義Filter類路徑:

consumer=com.doudou.demo.filter.CustomFilter

ValidationFilter

Dubbo的ValidationFilter是基于JSR303標準實現(xiàn)的參數(shù)校驗組件,主要用于服務(wù)消費者和服務(wù)提供者兩端,確保接口調(diào)用時參數(shù)的合法性。

核心特性

作用機制

  • 通過@Activate注解激活,默認作用于消費者和服務(wù)者兩端,執(zhí)行順序為10000。
  • 在請求處理前攔截參數(shù),利用JSR303標準的注解進行校驗,校驗失敗時拋出異常中斷流程。

依賴配置

需要引入validation-apihibernate-validator依賴包

 <!-- Bean Validation API -->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>
<!-- Hibernate Validator實現(xiàn) -->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.2.5.Final</version>
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>jakarta.el</artifactId> <!-- 適配EL表達式 -->
    <version>5.0.0-M1</version>
</dependency>

使用

API

@Setter
@Getter
public class UserDTO implements Serializable {
    @NotBlank(message = "用戶名不能為空")
    private String username;

    @Min(value = 18, message = "年齡必須大于18歲")
    private Integer age;

    @Email(message = "郵箱格式不合法")
    private String email;
}
public class BaseResult<T> {
    // 處理是否正確結(jié)束
    private boolean success;
    // 異常編碼
    private Integer errorCode;
    // 異常描述
    private String errorMsg;
    // dubbo接口返回的結(jié)果
    private T data;
}    
public interface UserService {
    BaseResult<String> registerUser(UserDTO userDTO);
}

服務(wù)提供者

@DubboService(validation = "true")
public class UserServiceImpl implements UserService {

    @Override
    public BaseResult<String> registerUser(UserDTO userDTO) {
        return BaseResult.success("用戶注冊成功:" + userDTO.getUsername());
    }
}
public class ParameterVerificationResultFilter implements Filter {
    private Logger logger = LoggerFactory.getLogger(ParameterVerificationResultFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        Result result = invoker.invoke(invocation);
        // 處理出現(xiàn)異常
        if (result.hasException()) {
            Throwable exception = result.getException();
            // 是由參數(shù)校驗失敗拋出的異常
            if (exception instanceof ConstraintViolationException) {
                List<String> errors = ((ConstraintViolationException) exception).getConstraintViolations().stream()
                        .map(v -> v.getPropertyPath() + ": " + v.getMessage())
                        .collect(Collectors.toList());
                logger.info("---------------2---------------");
                logger.error(errors.toString());
                logger.info("---------------3---------------");
                // 將錯誤信息封裝到返回結(jié)果中
                return AsyncRpcResult.newDefaultAsyncResult(BaseResult.fail(400, errors.toString()), invocation);
            }
        }
        return result;
    }
}

META-INF/dubbo/org.apache.dubbo.rpc.Filter

# 參數(shù)校驗過濾器
validation=org.apache.dubbo.validation.filter.ValidationFilter
# 校驗結(jié)果處理過濾器
parameterVerification=com.doudou.filter.ParameterVerificationResultFilter

application.yml

dubbo:
	provider:
		filter: validation,parameterVerification

服務(wù)消費方

@RestController
public class UserServiceController {
    @DubboReference(validation = "true")
    private UserService userService;

    @PostMapping("/test")
    public BaseResult<String> test(@RequestBody UserDTO userDTO) {
        return userService.registerUser(userDTO);
    }
}
@RestControllerAdvice
public class GlobalExceptionHandler {

    // 處理RpcException異常
    @ExceptionHandler(RpcException.class)
    public ResponseEntity<BaseResult> handleValidationException(RpcException rpcException) {
        return ResponseEntity.badRequest().body(BaseResult.fail(403, rpcException.getLocalizedMessage()));
    }
}

源碼解析

org.apache.dubbo.validation.filter.ValidationFilter

public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
   // 判斷是否需要進行參數(shù)驗證
    if (needValidate(invoker.getUrl(), invocation.getMethodName())) {
        try {
            // 通過url中的validation屬性值獲取驗證器
            Validator validator = validation.getValidator(invoker.getUrl());
            if (validator != null) {
                // 獲取到驗證器時,進行參數(shù)驗證
                validator.validate(
                        invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
            }
        } catch (RpcException e) {
            // RpcException 異常直接拋出
            throw e;
        } catch (Throwable t) {
            // 非RpcException,封裝到結(jié)果中返回
            return AsyncRpcResult.newDefaultAsyncResult(t, invocation);
        }
    }
    // 執(zhí)行下一個過濾器的處理
    return invoker.invoke(invocation);
}

 /**
  * 是否需要進行參數(shù)驗證
  */
 private boolean needValidate(URL url, String methodName) {
     return validation != null
             && !methodName.startsWith("$")
             && ConfigUtils.isNotEmpty(url.getMethodParameter(methodName, VALIDATION_KEY))
             && !"false".equalsIgnoreCase(url.getParameter(VALIDATION_KEY));
 }

org.apache.dubbo.validation.support.AbstractValidation

@Override
public Validator getValidator(URL url) {
    // 使用url作為存儲驗證器map集合的的key
    String key = url.toFullString();
    // 從容器中獲取驗證器
    Validator validator = validators.get(key);
    // 判斷驗證器是否已經(jīng)存在
    if (validator == null) {
        // 如果不存在,則創(chuàng)建
        validators.put(key, createValidator(url));
        validator = validators.get(key);
    }
    return validator;
}

org.apache.dubbo.validation.support.jvalidation.JValidation

@Activate(onClass = "javax.validation.Validation")
public class JValidation extends AbstractValidation {

    /**
     * Return new instance of {@link JValidator}
     * @param url Valid URL instance
     * @return Instance of JValidator
     */
    @Override
    protected Validator createValidator(URL url) {
        // 創(chuàng)建一個Dubbo框架默認的校驗器
        return new JValidator(url);
    }
}

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論

昭平县| 饶平县| 新巴尔虎左旗| 通化市| 义马市| 醴陵市| 安塞县| 法库县| 余江县| 瑞昌市| 山东省| 集贤县| 崇仁县| 南岸区| 雷山县| 大埔区| 乌兰浩特市| 普宁市| 鹤岗市| 昌吉市| 伽师县| 蕉岭县| 黄梅县| 方山县| 承德县| 南丹县| 藁城市| 中宁县| 清流县| 汕头市| 观塘区| 海门市| 连平县| 铁力市| 固镇县| 肃北| 闵行区| 依兰县| 视频| 枣强县| 宝清县|