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

如何定义HTTP过滤器并将生成对象作为@RequestScoped实例供REST资源使用?

在Jersey中通过ContainerRequestFilter传递对象到REST资源方法

要实现解析请求头/参数构建对象并传递给资源方法,核心是利用Jersey的请求上下文存储对象,再通过参数注入或直接获取的方式让资源方法访问。以下是具体实现方案:

1. 定义待传递的对象类

先创建你需要的上下文对象,比如存储用户信息的UserContext:

public class UserContext {
    private String userId;
    private String authToken;

    public UserContext(String userId, String authToken) {
        this.userId = userId;
        this.authToken = authToken;
    }

    // Getter方法
    public String getUserId() { return userId; }
    public String getAuthToken() { return authToken; }
}

2. 实现ContainerRequestFilter解析请求并存储对象

在过滤器中解析请求头、参数,构建对象后存入ContainerRequestContext的Properties中:

@Provider
public class UserContextFilter implements ContainerRequestFilter {
    // 用类全限定名作为唯一key,避免冲突
    private static final String USER_CONTEXT_KEY = UserContext.class.getName();

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        // 解析请求头示例:获取Authorization头
        String authToken = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
        // 解析Query参数示例:获取userId参数
        String userId = requestContext.getUriInfo().getQueryParameters().getFirst("userId");

        // 构建上下文对象(实际场景可加入token验证、用户信息查询等逻辑)
        UserContext userContext = new UserContext(userId, authToken);
        
        // 将对象存入请求上下文
        requestContext.setProperty(USER_CONTEXT_KEY, userContext);
    }
}

3. 让资源方法访问对象:两种方式

方式一:直接通过@Context获取(简单快速)

在资源方法中注入ContainerRequestContext,手动取出对象:

@Path("/demo")
public class DemoResource {

    @GET
    public Response getDemoData(@Context ContainerRequestContext requestContext) {
        UserContext userContext = (UserContext) requestContext.getProperty(UserContext.class.getName());
        return Response.ok(String.format("当前用户ID:%s,Token:%s", userContext.getUserId(), userContext.getAuthToken())).build();
    }
}

方式二:自定义注解+参数注入(优雅推荐)

这种方式无需手动从上下文取对象,直接注入到方法参数中,代码更简洁。

步骤1:定义自定义注解

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestUserContext {
}

步骤2:实现参数注入的Provider

创建ValueFactoryProvider,用于向Jersey提供UserContext实例:

@Provider
public class UserContextValueFactoryProvider extends AbstractValueFactoryProvider {
    private static final String USER_CONTEXT_KEY = UserContext.class.getName();

    @Inject
    public UserContextValueFactoryProvider(MultivaluedParameterExtractorProvider extractorProvider, ServiceLocator serviceLocator) {
        super(extractorProvider, serviceLocator, Parameter.Source.UNKNOWN);
    }

    @Override
    protected Factory<?> createValueFactory(Parameter parameter) {
        // 判断参数类型和注解是否匹配
        if (parameter.getType() == UserContext.class && parameter.isAnnotationPresent(RequestUserContext.class)) {
            return new Factory<UserContext>() {
                @Context
                private ContainerRequestContext requestContext;

                @Override
                public UserContext provide() {
                    return (UserContext) requestContext.getProperty(USER_CONTEXT_KEY);
                }

                @Override
                public void dispose(UserContext userContext) {
                    // 无需清理操作
                }
            };
        }
        return null;
    }
}

步骤3:注册过滤器和Provider

确保过滤器和Provider被Jersey识别,可通过ResourceConfig手动注册:

public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        // 注册过滤器
        register(UserContextFilter.class);
        // 注册参数注入Provider
        register(UserContextValueFactoryProvider.class);
        // 注册资源类
        register(DemoResource.class);
    }
}

步骤4:在资源方法中使用注解注入

@Path("/demo")
public class DemoResource {

    @GET
    public Response getDemoData(@RequestUserContext UserContext userContext) {
        return Response.ok(String.format("当前用户ID:%s,Token:%s", userContext.getUserId(), userContext.getAuthToken())).build();
    }
}

注意事项

  • 如果需要解析POST请求的请求体,注意请求流只能读取一次,需将流包装为可重复读取的CachedOutputStream后再解析,避免后续资源方法无法读取请求体。
  • 确保@Provider注解的类被Jersey扫描到,或手动注册到配置类中。
  • 存储对象时使用唯一的key,避免与其他组件的属性冲突。

内容的提问来源于stack exchange,提问作者Kostas Pagratis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 10:25:17