【问题标题】:How can I separate business logic and email sending functionality?如何分离业务逻辑和电子邮件发送功能?
【发布时间】:2015-03-26 18:44:26
【问题描述】:

我的 Java Web 应用程序有一个要求,我需要在某些条件下发送电子邮件警报。为此,我使用了 javax 邮件 api,并且发送电子邮件工作得很好。但问题是程序执行要等到发送电子邮件的方法被执行。由于在不同的时间点要发送数百封电子邮件……这会显着降低性能。

我正在使用spring,也使用过spring aop。谁能建议我如何分离我的业务逻辑和发送电子邮件功能。应该是这样的——

发送电子邮件是我的建议,它会在调用 xyz 方法时执行 - 因此主执行不应等待建议完成执行,而应返回并执行进一步的业务逻辑,因此电子邮件发送单独执行。

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

【问题讨论】:

    标签: java multithreading spring jakarta-mail spring-aop


    【解决方案1】:

    您可以将邮件发送方式设为@Async。这样,Spring 将在单独的线程中执行此操作。阅读这篇关于它的博文:Creating Asynchronous Methods

    【讨论】:

      【解决方案2】:

      您描述的是异步执行,而进行异步执行的自然方法是 Java 是使用线程。

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

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

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

      最好将此逻辑移动到单独的类中,并以某种方式从方面调用它。

      【讨论】:

        【解决方案3】:

        将电子邮件发送功能视为 IO 设备。使其成为您业务逻辑的插件。不要让任何知道您甚至正在与电子邮件代码交谈的事实进入您的业务逻辑。使电子邮件逻辑依赖于业务逻辑。永远不要反过来。

        下面是关于这种架构的一个很好的讨论:

        https://vimeo.com/97530863

        这里有一系列辩论:

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

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

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

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

        这样做,您的应用就会很好地扩展。我认为这是最好的表达方式:

        来自hexagonal architecture 的帖子。但是,从实现细节中移除为您的业务规则提供一个安全的地方的想法出现在许多架构中。这个answer 很好地把它们四舍五入。

        【讨论】:

          【解决方案4】:

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

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

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

          至于分离逻辑,在需要时引发 Spring Application Event,并创建另一个类来监听它,并从那里发送您的电子邮件。或者考虑一下 Guava 的 EventBus

          【讨论】:

            【解决方案5】:

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

            如果您想要另一种方法,您可以创建一个单独的后端应用程序,它只发送电子邮件。尽管您需要将电子邮件消息提交给应用程序。执行此操作的异步方法是将 JMS 消息发送到电子邮件应用程序。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-09-04
              • 2014-11-30
              • 2020-03-26
              • 2014-05-23
              • 1970-01-01
              相关资源
              最近更新 更多