竹简文档
Dubbo Triple

注解

@DubboPersistentContext 与 @TripleRequestCheck 注解驱动上下文传播与请求校验

注解

bamboo-triple 提供两个核心注解,分别用于声明式的上下文传播与请求参数校验。通过在 Dubbo 服务方法上标注注解,即可自动触发对应的 AOP 切面逻辑。

@DubboPersistentContext

@DubboPersistentContext 用于声明 Dubbo Triple 服务方法需要进行上下文传播。标注该注解后,DubboContextAspect 将自动从请求参数中提取 ctx 并初始化 ContextHolderMDC

定义

DubboPersistentContext.java
package com.xlf.utility.triple.annotations;

import java.lang.annotation.*;

// 可标注于方法或类型上
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DubboPersistentContext {
}

作用范围

标注位置效果
方法级别仅该方法触发上下文传播
类级别该类所有方法均触发上下文传播

使用示例

方法级别标注

UserTripleServiceImpl.java
@DubboService
public class UserTripleServiceImpl implements UserTripleService {

    // 仅 queryUser 方法触发上下文传播
    @DubboPersistentContext
    @Override
    public TripleResponse<UserDTO> queryUser(UserQueryRequest request) {
        UserDTO user = userService.getById(request.getUserId());
        return TripleResult.success(user);
    }

    // 此方法不触发上下文传播
    @Override
    public TripleResponse<Void> ping() {
        return TripleResult.success();
    }
}

类级别标注

OrderTripleServiceImpl.java
// 类级别标注,所有方法均触发上下文传播
@DubboPersistentContext
@DubboService
public class OrderTripleServiceImpl implements OrderTripleService {

    @Override
    public TripleResponse<OrderDTO> queryOrder(OrderQueryRequest request) {
        return TripleResult.success(orderService.getById(request.getOrderId()));
    }

    @Override
    public TripleResponse<Void> cancelOrder(OrderCancelRequest request) {
        orderService.cancel(request.getOrderId());
        return TripleResult.success();
    }
}

前置条件

使用 @DubboPersistentContext 时,方法参数需满足以下条件:

  • 至少有一个参数对象提供 getCtx() 方法
  • 通常该参数为 TripleRequest 的子类
  • ctx 字段需在调用方通过 init() 方法初始化

@TripleRequestCheck

@TripleRequestCheck 用于声明 Dubbo Triple 服务方法需要进行请求参数校验。标注该注解后,TripleRequestCheckAspect 将自动提取 TripleRequest 参数并调用其 validate() 方法。

定义

TripleRequestCheck.java
package com.xlf.utility.triple.annotations;

import com.xlf.utility.ErrorCode;
import java.lang.annotation.*;

// 可标注于方法或类上
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TripleRequestCheck {
    String message() default "";
    ErrorCode errorCode() default ErrorCode.PARAMETER_INVALID;
}

属性说明

字段

类型

使用示例

基本用法

BasicCheckExample.java
@DubboPersistentContext
// 使用默认错误消息与错误码
@TripleRequestCheck
@Override
public TripleResponse<UserDTO> queryUser(UserQueryRequest request) {
    return TripleResult.success(userService.getById(request.getUserId()));
}

自定义消息与错误码

CustomCheckExample.java
@DubboPersistentContext
// 自定义校验失败的错误消息与错误码
@TripleRequestCheck(message = "订单创建参数无效", errorCode = ErrorCode.PARAMETER_INVALID)
@Override
public TripleResponse<OrderDTO> createOrder(OrderCreateRequest request) {
    OrderDTO order = orderService.create(request);
    return TripleResult.success(order, "订单创建成功");
}

校验流程

方法调用


TripleRequestCheckAspect 拦截

    ├── 遍历方法参数,查找 TripleRequest 类型

    ├── 未找到 → 直接放行

    ├── 找到 → 调用 validate()
    │       │
    │       ├── true  → 放行,执行目标方法
    │       │
    │       └── false → 抛出 BusinessException
    │                    ├── message = @TripleRequestCheck.message()(为空则使用默认消息)
    │                    └── errorCode = @TripleRequestCheck.errorCode()


目标方法执行或异常抛出

组合使用

在实际业务中,通常将两个注解组合使用,确保上下文传播与参数校验同时生效:

CombinedExample.java
@DubboService
public class ProductTripleServiceImpl implements ProductTripleService {

    // 组合使用:先传播上下文,再校验请求参数
    @DubboPersistentContext
    @TripleRequestCheck(message = "商品查询参数无效", errorCode = ErrorCode.PARAMETER_INVALID)
    @Override
    public TripleResponse<ProductDTO> queryProduct(ProductQueryRequest request) {
        ProductDTO product = productService.getById(request.getProductId());
        if (product == null) {
            return TripleResult.error(ErrorCode.RESOURCE_NOT_FOUND, "商品不存在");
        }
        return TripleResult.success(product, "查询成功");
    }
}

调用方构建请求:

ProductClient.java
// 调用方需通过 init() 初始化请求元数据
ProductQueryRequest request = ProductQueryRequest.builder()
        .productId(20001L)
        .build()
        .init("gateway-service");

TripleResponse<ProductDTO> response = productTripleService.queryProduct(request);

下一步

On this page