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
相关产品推荐
相关产品推荐

