如何分离业务逻辑和电子邮件发送function?

我的java web应用程序中有一个要求,我需要在某些条件下发送电子邮件警报。 为此,我使用了javax mail api并发送电子邮件工作正常。 但问题是程序执行等待直到执行发送电子邮件的方法。 由于在不同的点上发送了数百封电子邮件……这会显着降低性能。

我正在使用弹簧,也使用了弹簧。 任何人都可以建议我如何分离我的业务逻辑和发送电子邮件function。 它应该像 –

发送电子邮件是我的建议,在调用xyz方法时执行 – 所以主要执行不应该等待建议完成其执行,而应该返回并执行进一步的业务逻辑,从而单独执行电子邮件发送。

这里创建新线程似乎是明显的选择。 但我认为可能有更好的方法,是吗? 谢谢。

你所描述的是异步执行和自然的异步执行方式是Java是使用线程。

您可以引入一些Executor ,例如Executors.newFixedThreadPool() ,并使用它将邮件任务卸载到单独的线程中。

Aspect本身是一个不适合的地方,因为这会将状态引入方面,例如,您可能想要使用返回的Future来检查邮件任务是否成功:

 class Mailer { private final ExecutorService executor = Executors.newFixedThreadPool(maxMailingThreads); //... public void doMail(MailTask anEmail) { Future future = executor.submit(new MailTask(anEmail)); future.get().isSuccessful(); // handle success or failure somehow } 

更好地将这个逻辑移动到单独的类中并以某种方式从方面调用它。

您可以使邮件发送方法@Async 。 这样Spring就会在一个单独的线程中执行它。 阅读此博客文章: 创建异步方法

像IO设备一样对待电子邮件发送function。 使其成为您的业务逻辑的插件。 不要让任何关于您甚至将电子邮件代码与业务逻辑对话的事实的知识。 使电子邮件逻辑依赖于业务逻辑。 从来没有反过来。

这是一个关于这种架构的非常好的讨论:

https://vimeo.com/97530863

这是一个系列辩论它:

https://www.youtube.com/watch?v=z9quxZsLcfo

这是一个ruby大师用真实代码演示它。 我们想念他。

https://www.youtube.com/watch?v=tg5RFeSfBM4

如果您的业务规则足够值得尊重,那么这就是让它们成为您应用程序主人的方法。 仅使用java表达它们。 不接受任何帮助。 没有spring,没有奇怪的注释,只是商业规则。 将所有“帮助”推送到邮件代码。

这样做,你的应用程序将很好地扩展。 我认为这是最好的方式:

http://blog.mattwynne.net/category/hexagonal-rails/

这是一个六角形的架构文章。 但是,从许多体系结构中可以看出,为业务规则提供安全的生存环境的想法已从实现细节中删除。 这个答案很好地完善了它们。

使用localhost MTA(如OpenSMTPD),然后中继到您的真实SMTP服务器,如Amazon SES(“卫星”模式)。 它不会阻止。

我做了一个测试,并以这种方式在2.8秒内发送了1000封电子邮件

它比在java中执行异步更简单,并且在多个应用程序中很有用。

至于分离逻辑,在需要时引发Spring应用程序事件,并让另一个类听它,然后从那里发送你的电子邮件。 或者考虑类似Guava的EventBus

考虑创建一个单独的线程来在您的应用程序中发送电子邮件 这将允许并行执行(应用程序+电子邮件发送)。

如果您需要其他方法,则可以创建仅发送电子邮件的单独后端应用程序。 虽然您需要将电子邮件提交给应用程序。 执行此操作的异步方法是将JMS消息发送到电子邮件应用程序。