如何使用 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 {
...
}
应该有预期的效果。将在 BeanRequestFilter
和 BeanService
.
中注入相同的实例
但是,我认为您也可以通过将 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);
}
}
我有一个带有 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 {
...
}
应该有预期的效果。将在 BeanRequestFilter
和 BeanService
.
但是,我认为您也可以通过将 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);
}
}