You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus复杂对象处理之自定义参数注入方案求助

在Quarkus中实现自定义参数注入(类似Spring HandlerMethodArgumentResolver)

Quarkus基于JAX-RS(RESTEasy)和CDI生态,有几种优雅的方式实现自定义参数注入,对应Spring的HandlerMethodArgumentResolver能力,以下是三种常用方案:

方案1:自定义注解 + CDI生产者方法

适合从请求上下文(Header、Cookie、请求属性等)提取数据并封装成自定义对象注入到资源方法参数中。

步骤1:定义自定义注解

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
}

步骤2:实现CDI生产者,解析请求上下文生成对象

@RequestScoped
public class CurrentUserProducer {

    @Context
    HttpServletRequest request;

    @Produces
    @CurrentUser
    public User getCurrentUser() {
        // 示例:从Authorization头解析JWT获取用户信息
        String authHeader = request.getHeader("Authorization");
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring(7);
            // 此处省略JWT解析逻辑,返回自定义User对象
            return new User("user-123", "john.doe@example.com");
        }
        throw new NotAuthorizedException("无效或缺失认证令牌");
    }
}

步骤3:在资源方法中使用

@Path("/api/users")
public class UserResource {

    @GET
    @Path("/me")
    public Response getCurrentUser(@CurrentUser User user) {
        return Response.ok(user).build();
    }
}

方案2:利用RESTEasy的ParamConverterProvider

适合将字符串类型的请求参数(PathParam、QueryParam等)转换成自定义对象。

步骤1:定义自定义参数类

public class UserId {
    private final String value;

    public UserId(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

步骤2:实现ParamConverter和ParamConverterProvider

@Provider
public class UserIdParamConverterProvider implements ParamConverterProvider {

    @Override
    public <T> ParamConverter<T> getConverter(Class<T> clazz, Type type, Annotation[] annotations) {
        if (clazz.equals(UserId.class)) {
            return (ParamConverter<T>) new ParamConverter<UserId>() {
                @Override
                public UserId fromString(String value) {
                    // 添加参数校验逻辑
                    if (value == null || value.isBlank()) {
                        throw new BadRequestException("用户ID不能为空");
                    }
                    return new UserId(value);
                }

                @Override
                public String toString(UserId userId) {
                    return userId.getValue();
                }
            };
        }
        return null;
    }
}

步骤3:在资源方法中使用

@Path("/api/users")
public class UserResource {

    @GET
    @Path("/{userId}")
    public Response getUser(@PathParam("userId") UserId userId) {
        return Response.ok("查询用户ID:" + userId.getValue()).build();
    }
}

方案3:高级场景 - 自定义ValueInjector

适合实现复杂的参数注入逻辑(比如结合多种请求数据、调用外部服务获取参数)。

步骤1:实现ValueInjector

public class CustomUserInjector implements ValueInjector {

    private final HttpServletRequest request;

    public CustomUserInjector(HttpServletRequest request) {
        this.request = request;
    }

    @Override
    public Object inject(boolean unwrapAsync) {
        // 示例:从请求属性中获取用户ID,再查询数据库返回完整用户信息
        String userId = request.getAttribute("user-id").toString();
        // 此处省略数据库查询逻辑
        return new User(userId, "user@example.com");
    }

    @Override
    public Object inject() {
        return inject(false);
    }
}

步骤2:实现InjectorFactory

@Provider
public class CustomInjectorFactory extends InjectorFactoryImpl {

    @Context
    HttpServletRequest request;

    @Override
    public ValueInjector createParameterExtractor(Class<?> type, Type genericType, Annotation[] annotations,
                                                   HttpRequest request, HttpResponse response,
                                                   PropertyHandling propertyHandling, String parameterName) {
        // 检查参数是否带有自定义注解
        for (Annotation ann : annotations) {
            if (ann.annotationType().equals(CurrentUser.class)) {
                return new CustomUserInjector(this.request);
            }
        }
        return super.createParameterExtractor(type, genericType, annotations, request, response, propertyHandling, parameterName);
    }
}

步骤3:在资源方法中使用

与方案1一致,直接在参数上标注@CurrentUser即可。


内容的提问来源于stack exchange,提问作者Ayume

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 07:10:33