Quarkus中如何在@ApplicationScoped服务类中注入HttpServerRequest
问题核心原因
@Context是JAX-RS专属的上下文注入注解,仅能在JAX-RS管理的组件(比如@Path标注的资源类、@Provider标注的拦截器/过滤器)中生效,普通CDI Bean(比如自定义的Service)使用@Context注入本身就不被支持,所以会拿到null。- HttpServerRequest是请求级别的对象,和单例作用域的
@ApplicationScopedBean生命周期不匹配,直接注入也会出现作用域不兼容的问题。
可行实现方案
方案1:使用Provider延迟获取(推荐,不改变Service单例特性)
通过CDI提供的Provider包装HttpServerRequest,实现延迟加载,每次调用get()方法时会自动获取当前请求对应的实例,无需修改Service的作用域。
示例代码:
import jakarta.inject.Inject; import jakarta.inject.Provider; import io.vertx.core.http.HttpServerRequest; @Slf4j @ApplicationScoped public class TokenService { // 注意此处用@Inject注入,不要用@Context @Inject Provider<HttpServerRequest> requestProvider; public SysUser getUser() { HttpServerRequest request = requestProvider.get(); String authorization = request.getHeader("Authorization"); log.info(authorization); // 后续业务逻辑 return null; } }
如果使用的是旧版Quarkus(基于Java EE),将jakarta.inject替换为javax.inject即可。
方案2:调整Service为请求作用域
将TokenService的作用域从@ApplicationScoped改为@RequestScoped,每个请求对应一个Service实例,此时可以直接注入HttpServerRequest。
示例代码:
import jakarta.enterprise.context.RequestScoped; import jakarta.inject.Inject; import io.vertx.core.http.HttpServerRequest; @Slf4j @RequestScoped public class TokenService { // 注意此处用@Inject注入,不要用@Context @Inject HttpServerRequest request; public SysUser getUser() { String authorization = request.getHeader("Authorization"); log.info(authorization); // 后续业务逻辑 return null; } }
该方案适合业务逻辑较轻的Service,如果Service中存在较重的初始化逻辑,会产生额外的性能开销。
内容的提问来源于stack exchange,提问作者JaveysWuu
相关产品推荐
相关产品推荐

