java - 我可以向哪些类/实例中注入(inject) CDI 事件?

标签 java tomcat servlets jakarta-ee cdi

我想要一个可以触发事件的类。理想情况下,我希望将它放在 POJO 中(处理 POJO 中的遗留代码),但我知道这是不可能的。因此,我想要 POJO 可以调用的可以触发事件的东西。

注意:我在带有 CDI 的 Tomcat 上,还安装了 JPA (在这个项目上不能切换到完整的 EE 服务器)

我不确定它是否应该是单例/应用程序范围的单例,或者应该是每个请求(甚至 session )。所以我的问题是:

  1. 事件可以注入(inject)什么? (例如 @WebListener@SingletonRequestScoped@Stateless)

  2. 对于这个用例,哪个最有意义?

  3. 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/

相关文章:

java - 将串行端口输出重定向到套接字

tomcat - 如何启动外部tomcat?

从维基百科文章中提取Java关键字

java - Tomcat 请求因超时而取消

java - 用于包装请求正文的 Sling Filter

java - 如何创建pdf文件并在spring boot应用程序的邮件中发送

java - 使用 PDFBox、iText 提取文本为空且未知,因为文本具有 type3 字体(困难的主题!)

java - 这个 HashMap 有什么问题,我不断收到不兼容的类型

java - Spring Servlet 映射困惑

java - TomEE 遇到 "a non-application exception",但只在 windows 上,不在 mac 上