我正在开发一个部署在Tomcat中的Web应用程序。我们在客户端使用Spring,Hibernate,GWT)。
此应用程序的一个功能是在创建,更新或删除任何实体时向用户发送警报(电子邮件)。 (用户可以动态添加警报,因此需要进行一些处理 - 确定应通过电子邮件通知哪些用户)。
理想情况下,警报机制应该是异步的,它应该影响CRUD操作的性能。
我想到的第一件事是创建一个线程并拥有一个阻塞队列。线程保持轮询阻塞队列以查看它是否有任何事件。但是,在Web应用程序中创建线程是许多容器不鼓励的事情。
有人可以建议/建议 - 这是正确的做法吗?或者有更好的方法来做同样的事情。
任何指针都会受到高度赞赏。
提前致谢, 萨钦
答案 0 :(得分:7)
在容器中创建线程的限制实际上只是让没有经验的开发人员在脚下自我射击的建议。没有容器实际上禁止你这样做。使用java.util.concurrent类,创建线程应该不易出错,我不会太担心这个限制。
如果您的要求很简单,那么在ServletContextListener中创建单个线程/ runnable就足够了。在contextInitialized()
中创建并启动该主题并在contextDestroyed()
中将其关闭。 。使用ScheduledExecutorService
创建的Executors.newSingleThreadScheduledExecutor()
。传递给Executor的Runnable将从BlockingQueue中读取。
如果您的需求发生变化并且您需要更复杂的东西,您可能希望查看JMS / MDB或Quartz之类的调度程序。
答案 1 :(得分:1)
您可以使用调度程序定期运行作业,也可以使用Spring驱动Bean(some documentation on JMS and Spring)等效,它由执行队列轮询的容器执行。
答案 2 :(得分:1)
您可以尝试使用Spring 3.x异步方法调用。调用方法将立即返回,实际执行异步发生
的applicationContext:
<task:annotation-driven executor="asyncExecutor" mode="aspectj"/>
<task:executor id="asyncExecutor" pool-size="${executor.poolSize}"/>
在你的bean上:
@Async
public void sendEmail(...) {
// ...
}
请参阅Spring文档以获取更多详细信息:Spring 3.x Task Execution and Scheduling
答案 3 :(得分:0)
有很多方法可以做到,最简单的(除了简单地创建一个非托管线程)就是使用commonj WorkManager。当然,您可以使用简单的线程路径,但它在您运行的环境中确实存在缺陷(如链接中所述)。