如何使用 CDI 传播相同的实例

How to propagate same instance using CDI

我有一个带有 JAX-RS、CDI 和 EJB 的 Web 应用程序。在每个资源中,我都注入了一个无状态 SessionBean,我的问题是是否有可能将相同的实例注入到 JAX-RS 和无状态 SesionBean 的提供者中。我正在尝试将每个请求中的一些数据从 ContainerRequestFilter 传递到无状态 SesionBean。所有 EJB 组件只能由 jax rs 资源访问。

示例:

public class Bean {
    private String attr;

    // getter and setter
}

@Stateless
public class BeanService {

    @Inject
    Bean bean;

    public void doStuff() {
        bean.getAttr();
        // do something with bean.attr
    }
}

@Path("/bean")
public class BeanResource {

    @Inject
    BeanService service;

    @GET
    public void doStuff() {
        service.doStuff():
    }
}

@Provider
public class BeanRequestFilter implements ContainerRequestFilter {

    @Inject
    Bean bean;

    @Override
    public void filter(ContainerRequestContext containerRequestContext) throws IOException {
        String data = null; // <- get data from request
        bean.setAttr(data);
    }
}

更新

更改 Pojo 的 Bean,我的唯一目的是使用一个 class 来保存每个请求中出现的一些状态,并且可以在每次调用中传输,因为 PojoResource 到 PojoService。我想以这种方式进行,因为所有服务都会检索这些数据,我不想将其作为参数传递给每个方法。

如果您希望 Bean 成为一种使用 CDI 的单例,请参阅 @ApplicationScoped annotation(在这种情况下 Bean 应该是 Sersializable )

或者,如果您希望 EJB BeanService 成为单例,请参阅 @Singleton annotation

这看起来像您的 Bean class 本质上是请求范围的,因此将其更改为:

@RequestScoped
public class Bean {
    ...
}

应该有预期的效果。将在 BeanRequestFilterBeanService.

中注入相同的实例

但是,我认为您也可以通过将 ContainerRequestContext 直接注入 BeanService 并完全忘记 Bean 来获得您想要的东西。

@Stateless
public class BeanService {

   @Context
   ContainerRequestContext containerRequestContext;

   public void doStuff() {
      // <- get data from request
   }
}

在回答问题之前,Bean 永远不应该被更新。 bean的一个概念就是提供服务,用数据来处理请求。

也就是说,您当然可以将数据作为 bean 提供,但是数据需要一次性生成才能使用,而不是更新。

因此,我会使用 BeanRequestFilter 生成 bean,并让 BeanService 注入生成的 bean。

尽管如此,我看到这是基于请求的数据?是header数据吗?请求参数?那么我建议您在 jax-rs 资源中使用 jax-rs @QueryParam@HeaderParam@PathParam@FormParam@CookieParam class,然后将数据作为域 object 参数提供给您的 BeanService,因此:

@Path("/api/resource-path")
public class MyResource {

    public void processSomething(@QueryParam("qparam") String param,  @HeaderParam("hparam") String hParam) {
        MyDomain domain = new MyDomain(qParam, hParam);
        myService.process(domain);
    }
}