J'ai un service de messagerie qui envoie simplement une notification aux destinataires.
@RestController public class MyRestController { @Autowired private MailService mailService; @PostMapping("/orders") public void createOrders(@RequestBody List<Order> orders) { // manipulations with orders mailService.send("Order notification", "New orders", "1@mail.com"); } }
Et puis j'ai un contrôleur de repos qui appelle cette méthode après une logique métier.
@Service public class MailService { @Autowired private JavaMailSender mailSender; public void send(String subject, String text, String... emails) { // MailMessage object configuration mailSender.send(mail); } }
Comment concevoir une application pour désactiver les notifications pour différents profils de ressort? Existe-t-il des bonnes pratiques pour configurer la distribution des e-mails en fonction du profil?
3 Réponses :
Ayez juste une implémentation fictive pour les profils qui en ont besoin
@Bean @Profile("prod") public JavaMailSender getRealJavaMailSender() { Â Â Â Â JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); Â Â Â Â mailSender.setHost("smtp.gmail.com"); Â Â Â Â mailSender.setPort(587); Â Â Â Â Â Â Â Â Â mailSender.setUsername("my.gmail@gmail.com"); Â Â Â Â mailSender.setPassword("password"); Â Â Â Â Â Â Â Â Â Properties props = mailSender.getJavaMailProperties(); Â Â Â Â props.put("mail.transport.protocol", "smtp"); Â Â Â Â props.put("mail.smtp.auth", "true"); Â Â Â Â props.put("mail.smtp.starttls.enable", "true"); Â Â Â Â props.put("mail.debug", "true"); Â Â Â Â Â Â Â Â Â return mailSender; } @Bean @Profile("test") public JavaMailSender getDummyJavaMailSender() { return new JavaMailSender() { ... dummy method implementations ... }; }
Une possibilité est de créer une interface MailService
avec deux implémentations. En combinant ces implémentations avec l'annotation @Profile
, vous pouvez correctement injecter l'une ou l'autre implémentation en fonction du profil que vous utilisez. Par exemple:
@RestController public class MyRestController { @Autowired private MailService mailService; @Autowired private Environment environment; @PostMapping("/orders") public void createOrders(@RequestBody List<Order> orders) { // manipulations with orders if (environment.acceptsProfiles(Profiles.of("mail"))) { mailService.send("Order notification", "New orders", "1@mail.com"); } } }
Ensuite, vous pouvez ajouter l'annotation @Profile ("mail")
à une implémentation:
@Aspect @Component @Profile("mail") public class OrderNotificationAspect { private final MailService mailService; public OrderNotificationAspect(MailService mailService) { this.mailService = mailService; } @AfterReturning("execution(* com.example.MyRestController.createOrders(..))") public void sendNotification() { mailService.send("Order notification", "New orders", "1@mail.com"); } }
De plus, vous pouvez ajouter une autre implémentation lorsque le profil de messagerie n'est pas actif:
@RestController public class MyRestController { @PostMapping("/orders") public void createOrders(@RequestBody List<Order> orders) { // manipulations with orders } }
Si vous utilisez maintenant MailService code> dans votre contrôleur, il implémentera correctement l'implémentation correcte en fonction du profil que vous utilisez.
Une autre alternative consiste à découpler l'envoi de mails entièrement depuis la logique de création de commande en utilisant des aspects.
Cela vous permet de supprimer complètement la dépendance MailService
du contrôleur MyRestController
:
@Service @Profile("!mail") // By adding the exclamination mark, this implementation will be used when the mail profile isn't active public class NoopMailServiceImpl implements MailService { private final Logger logger = LoggerFactory.getLogger(getClass()); @Override public void send(String subject, String text, String... emails) { logger.debug("Dummy implementation, no e-mail is being sent"); } }
Au lieu de cela, vous ajoutez la logique mailService
à un aspect distinct:
@Service @Profile("mail") // Only create this bean when the 'mail' profile is used public class JavaMailServiceImpl implements MailService { @Autowired private JavaMailSender mailSender; public void send(String subject, String text, String... emails) { // MailMessage object configuration mailSender.send(mail); } }
Comme avant, nous utilisons l'annotation @Profile
pour n'enregistrer le bean aspect que lorsque le profil de messagerie est actif. Cependant, comme nous ne lions plus directement le contrôleur au MailService
, nous n'avons plus besoin de la "mise en œuvre factice".
Pour utiliser des aspects dans Spring boot, vous devez ajouter le Dépendance spring-boot-starter-aop .
Une autre option consiste à écrire la vérification dans votre code, par exemple:
public interface MailService { void send(String subject, String text, String... emails); }
En fonction de la finesse de cette logique, vous pouvez soit la mettre dans le contrôleur, soit dans le service (si vous souhaitez désactiver tous les e-mails envoyé pour un profil spécifique).
L'option que vous choisissez dépend de vos besoins. L'utilisation de plusieurs implémentations est le moyen le plus simple de désactiver l'envoi de tous les e-mails.
Cependant, si vous souhaitez uniquement désactiver l'envoi de certains e-mails, vous devrez choisir un autre moyen. L'inconvénient de l'utilisation des aspects est que cela rend le flux parfois un peu plus difficile à suivre, bien que les IDE prennent en charge assez bien certains aspects.
Je suggère d'ajouter une variable (par exemple sendEmails = false
) aux fichiers application- [profile-name] .properties avec des paramètres différents pour chaque profil.
Ensuite dans votre code vous pouvez utiliser cette propriété pour décider si les e-mails doivent être envoyés.
@Service public class MailService { @Value("sendEmails}") private boolean sendEmails; @Autowired private JavaMailSender mailSender; public void send(String subject, String text, String... emails) { if (sendEmails) { // MailMessage object configuration mailSender.send(mail); } } }
Cette approche vous permet d'utiliser des paramètres différents (et facilement modifiables) pour chaque profil.