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.