我想要一个可以触发事件的类。理想情况下,我希望将它放在 POJO 中(处理 POJO 中的遗留代码),但我知道这是不可能的。因此,我想要 POJO 可以调用的可以触发事件的东西。
注意:我在带有 CDI 的 Tomcat 上,还安装了 JPA (在这个项目上不能切换到完整的 EE 服务器)
我不确定它是否应该是单例/应用程序范围的单例,或者应该是每个请求(甚至 session )。所以我的问题是:
事件可以注入(inject)什么? (例如
@WebListener
、@Singleton
、RequestScoped
、@Stateless
)对于这个用例,哪个最有意义?
POJO 如何访问该类/实例(从 servlet 调用 POJO)?
示例代码:
//Is this correct?
@WebListener
public class EventHandler
{
@Inject
@MyEventQualifier
private Event<MyEvent> myEvent;
public void fireEvent(MyEvent anEvent)
{
myEvent.fireAsync( anEvent );
}
}
最佳答案
基本容器类是您的标准“托管”对象,如您列出的对象(WebListeners、Filters、Servlet)。这些充当上下文链的根。由于它们由 CDI 管理,因此它们注入(inject)的任何内容也将受到管理,并沿着这条线进行管理。
如果您的 Servlet(例如)注入(inject) PojoX,PojoX 可以注入(inject) PojoY,等等。游戏是躲new
并改用 CDI 构造来创建您的 POJO。
至于跨越遗留的 POJO/CDI 鸿沟,您可以做几件事。
你可以注入(inject)一个 EventHandler
的实例到 Servlet,然后将该实例作为参数传递到 POJO。
您可以将该实例作为属性粘贴到请求中,或者在首次创建 Servlet 时将该实例推送到 ServletContext 中。
您可以将 EventHandler 设为 @Singleton
并在其 @PostConstruct
设置一个可以通过标准静态返回的静态变量 getInstance
打电话。
您可以让您的 POJO 直接调用容器来执行查找(或调用实用函数)。
当然,如果 POJO 可以自己注入(inject),就那样做。
评论补充:
如果适合您的工作,您可以简单地注入(inject) POJO。
这是一个例子:
@WebServlet(name = "NewServlet", urlPatterns = {"/NewServlet"})
public class NewServlet extends HttpServlet {
@Inject
Instance<Pojo> pojoInstance;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Pojo pojo = pojoInstance.get();
String world = pojo.getWorld();
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet NewServlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet NewServlet at " + request.getContextPath() + "</h1>");
out.println("<p>Hello " + world);
out.println("</body>");
out.println("</html>");
}
}
}
public class Pojo {
@Inject
Event<PojoEvent> pojoEventHdlr;
@PostConstruct
public void postConstruct() {
System.out.println("Look, another Pojo!");
}
public String getWorld() {
PojoEvent pe = new PojoEvent("World event pojo fired");
pojoEventHdlr.fire(pe);
return "world";
}
}
public class PojoEvent {
String msg;
public PojoEvent() {
}
public PojoEvent(String msg) {
this.msg = msg;
}
public String toString() {
return "PojoEvent with msg: " + msg;
}
}
@Singleton
public class SingletonPojo {
public void pojoEventObserver(@Observes PojoEvent pe) {
System.out.println("We got a PojoEvent " + pe);
}
}
需要注意的重要一点是,我注入(inject)了一个 Instance<Pojo>
在 servlet 中,然后使用 Instance.get
在上面,而不仅仅是直接在 Pojo 上。原因是 Servlet 在网络应用程序中名义上是单例,因此如果您注入(inject)一个实际的 Pojo,您的所有请求都将使用完全相同的 Pojo 实例(不太可能是您想要的)。
你可以看到 Pojo 触发了事件,我有一个 @Singleton
类观察事件并转储消息。
如果您愿意对遗留代码进行更改,您可以做自己喜欢的事,没有真正需要跳过障碍来弥合 CDI <-> 遗留鸿沟。只需根据需要将它们转入 CDI。
关于java - 我可以向哪些类/实例中注入(inject) CDI 事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44684147/