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

从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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 03:13:21