从RestEasy迁移到RestEasyReactive:ResteasyContext替代方案咨询
替代ResteasyContext.pushContext在RestEasyReactive中的实现方案
针对多自定义对象场景,推荐以下两种贴合原@Context注入体验的方案,比setProperty/getProperty更简洁高效:
方案1:CDI RequestScoped Holder + 自定义注解注入
这是最贴近原用法的实现,能直接在端点通过注入获取对象:
步骤1:定义请求级别的上下文Holder
创建一个RequestScoped的Bean,用来存储需要传递的所有自定义对象:
import jakarta.enterprise.context.RequestScoped; @RequestScoped public class RequestContextHolder { private CustomUser currentUser; private RequestMetadata requestMeta; // Getter & Setter public CustomUser getCurrentUser() { return currentUser; } public void setCurrentUser(CustomUser currentUser) { this.currentUser = currentUser; } public RequestMetadata getRequestMeta() { return requestMeta; } public void setRequestMeta(RequestMetadata requestMeta) { this.requestMeta = requestMeta; } }
步骤2:在Filter中填充Holder
在ContainerRequestFilter中注入Holder,初始化并设置自定义对象:
import jakarta.ws.rs.container.ContainerRequestContext; import jakarta.ws.rs.container.ContainerRequestFilter; import jakarta.ws.rs.ext.Provider; import jakarta.inject.Inject; @Provider public class RequestInitFilter implements ContainerRequestFilter { @Inject RequestContextHolder contextHolder; @Override public void filter(ContainerRequestContext requestContext) { // 模拟创建自定义对象 CustomUser user = new CustomUser("user123", "John"); RequestMetadata meta = new RequestMetadata(requestContext.getHeaderString("X-Request-ID")); // 存入上下文Holder contextHolder.setCurrentUser(user); contextHolder.setRequestMeta(meta); } }
步骤3:在端点直接注入(可选:自定义注解优化)
如果想更贴近原@Context的直观性,可以给每个对象加自定义限定注解:
import jakarta.inject.Qualifier; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Qualifier @Target({FIELD, PARAMETER}) @Retention(RUNTIME) public @interface CurrentUser { }
然后在Holder类中添加生产者方法:
@CurrentUser @Produces public CustomUser produceCurrentUser() { return this.getCurrentUser(); }
之后在REST端点就能直接注入对象:
import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.inject.Inject; @Path("/user") public class UserResource { @Inject @CurrentUser private CustomUser currentUser; @Inject @RequestMeta // 同理给RequestMetadata添加对应注解后也可直接注入 private RequestMetadata requestMeta; @GET @Path("/info") public String getUserInfo() { return String.format("User: %s, Request ID: %s", currentUser.getName(), requestMeta.getRequestId()); } }
方案2:独立RequestScoped Bean
如果每个自定义对象不需要集中管理,可以为每个对象单独创建RequestScoped Bean,在Filter中初始化:
步骤1:定义单独的RequestScoped Bean
import jakarta.enterprise.context.RequestScoped; @RequestScoped public class CustomUser { private String userId; private String name; // 构造函数、Getter & Setter public CustomUser() {} public CustomUser(String userId, String name) { this.userId = userId; this.name = name; } // ... 省略Getter/Setter }
步骤2:Filter中注入并初始化
@Provider public class RequestInitFilter implements ContainerRequestFilter { @Inject CustomUser currentUser; @Override public void filter(ContainerRequestContext requestContext) { // 直接初始化Bean属性 currentUser.setUserId("user123"); currentUser.setName("John"); } }
步骤3:端点直接注入
@Path("/user") public class UserResource { @Inject private CustomUser currentUser; @GET @Path("/info") public String getUserInfo() { return "User: " + currentUser.getName(); } }
方案优势
- 无需强制类型转换,编译期就能校验类型,避免运行时错误
- 多对象场景下代码更清晰,每个对象的注入逻辑独立
- 完全贴合原
@Context的使用习惯,代码改动量小
内容的提问来源于stack exchange,提问作者Kiki
相关产品推荐
相关产品推荐

