Quarkus带参数注解拦截器问题:无法接收自定义角色参数
解决Quarkus拦截器无法获取方法自定义角色参数的问题
核心问题分析
你遇到的问题根源有两个:
- CDI拦截器绑定的参数匹配机制:默认情况下,带参数的拦截器绑定注解会把参数值作为匹配条件——只有目标方法/类上的注解参数和拦截器类上的完全一致时,才会触发拦截。
- 错误的注解参数获取方式:当前代码从拦截器类本身获取
@RolesRequired的参数,而不是从被拦截的目标方法/类上提取。
解决方案
步骤1:修改@RolesRequired注解,标记参数为非绑定匹配
给注解的rolesRequired参数添加@Nonbinding,让CDI在匹配拦截器时忽略该参数的值,只要目标有@RolesRequired注解就触发拦截:
import jakarta.annotation.Priority import jakarta.interceptor.* import jakarta.ws.rs.core.HttpHeaders import java.lang.annotation.Inherited @Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) @Retention(AnnotationRetention.RUNTIME) @InterceptorBinding @Inherited annotation class RolesRequired( @Nonbinding // 添加该注解,忽略参数匹配条件 val rolesRequired: Array<String> = [] // 设置默认值,避免必填报错 )
步骤2:调整拦截器类的绑定与参数获取逻辑
拦截器类上的@RolesRequired使用空参数即可(满足IDE绑定要求),同时修改逻辑从被拦截的目标方法/类上提取注解参数:
@Interceptor @RolesRequired() // 空参数即可,参数值不再影响拦截匹配 @Priority(Interceptor.Priority.PLATFORM_BEFORE + 1) class RolesRequiredInterceptor( private val header: HttpHeaders ) { @AroundInvoke fun intercept(context: InvocationContext): Any? { println("[check-role]") // 优先从方法上获取注解,方法无注解则从类上获取 val rolesAnnotation = context.method.getAnnotation(RolesRequired::class.java) ?: context.target.javaClass.getAnnotation(RolesRequired::class.java) val rolesRequired = rolesAnnotation?.rolesRequired ?: emptyArray() println("[roles]: ${rolesRequired.size} - ${rolesRequired.joinToString(", ")}") // TODO 在这里实现角色校验逻辑,比如从请求头提取用户角色进行比对 return context.proceed() } }
步骤3:验证业务方法
现在不管业务方法上的@RolesRequired参数是什么,拦截器都会触发并获取对应参数:
@RolesRequired(rolesRequired = ["role1"]) fun login(input: LoginData): LoginResponse {...} @RolesRequired(rolesRequired = ["role2"]) fun login(input: LoginData): LoginResponse {...} @RolesRequired(rolesRequired = ["role2", "role1"]) fun login(input: LoginData): LoginResponse {...}
调用第一个方法时,拦截器会输出:
[check-role] [roles]: 1 - role1
关键原理说明
@Nonbinding:标记注解参数为非绑定条件,CDI仅检查目标是否存在该注解,不再校验参数值是否匹配。InvocationContext:通过该上下文对象可获取被拦截的方法、目标类信息,从而动态提取目标上的注解参数,满足自定义角色的需求。
内容的提问来源于stack exchange,提问作者Prixii
相关产品推荐
相关产品推荐

