[SPRING] 실시간 통지 전자 메일을 구현하기위한 Quartz와의 Full Spring 통합
SPRING실시간 통지 전자 메일을 구현하기위한 Quartz와의 Full Spring 통합
저는 현재 사용자가 약속을 잡을 수있는 스프링 부트 응용 프로그램을 개발 중입니다. 따라서 기본적으로 약속에는 startDateTime 및 endDateTime 필드와 전자 메일이 있습니다. 약속을 작성하면 MySql 데이터베이스의 약속 테이블에 새로운 행이 추가됩니다.
내가하고 싶은 일은 데이터베이스에 전자 메일로 정의 된 startDateTime의 한 시간 전에 사용자에게 알리는 것입니다. 솔루션을 찾았지만 찾을 수 없습니다. 나는 일자리 (스프링 배치)가이 일을 할 수 있다는 것을 알았지 만, 일자리가 주파수 수표 (일, 주, 달)에 의존한다는 것은 실시간 알림이라는 것입니다. 이러한 작업을 실현하는 솔루션에 대한 도움이나 안내가 환영 받는다.
인사말
해결법
-
==============================
1.석영과 같은 스케줄 라이브러리를 사용하여 Spring 프레임 워크와 쉽게 통합 할 수 있습니다.
석영과 같은 스케줄 라이브러리를 사용하여 Spring 프레임 워크와 쉽게 통합 할 수 있습니다.
데이터베이스에 약속이 저장되면 원하는 시간 (예 : 시작 날짜 1 시간 전) 동안 "이메일 전송"작업이 예약됩니다.
"send-email"작업은 org.quartz.Job을 구현해야하며, 특히 Autowired SendEmailService 구현을 사용할 수있는 메소드를 실행해야한다.
아래에서 코드에서 이러한 요구 사항을 구현하는 방법에 대한 (거의) 완전한 예를 찾을 수 있습니다.
업데이트 - 작업을 예약하는 코드
먼저 SchedulingService 인터페이스를 정의합니다.
public interface SchedulingService { startScheduler() throws SchedulerException; void standbyScheduler() throws SchedulerException; void shutdownScheduler() throws SchedulerException; void scheduleJob(JobDetail jobDetail, Trigger trigger) throws SchedulerException; }
그리고 관련 구현.
@Service public class SchedulingServiceImpl implements SchedulingService { @Autowired private Scheduler scheduler; @Override public void startScheduler() throws SchedulerException { if (!scheduler.isStarted()) { scheduler.start(); } } @Override public void standbyScheduler() throws SchedulerException { if (!scheduler.isInStandbyMode()) { scheduler.standby(); } } @Override public void shutdownScheduler() throws SchedulerException { if (!scheduler.isShutdown()) { scheduler.shutdown(); } } @Override public void scheduleJob(JobDetail jobDetail, Trigger trigger) throws SchedulerException { scheduler.scheduleJob(jobDetail, trigger); } }
그런 다음 AppointmentServiceImpl에 scheduleSendEmailJob ()을 호출하는 createAppointment () 메소드가 있습니다.
@Service public class AppointmentServiceImpl implements AppointmentService { @Autowired private SchedulingService schedulingService; public void createAppointment(Appointment appointment) throws SchedulerException { // Save appointment to database // ... // Schedule send email job if appointment has been successfully saved scheduleSendEmailJob(appointment); return; } private void scheduleSendEmailJob(Appointment appointment) throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob().ofType(SendEmailJob.class) .storeDurably() .withIdentity(UuidUtils.generateId(), "APPOINTMENT_NOTIFICATIONS") .withDescription("Send email notification for appointment") .build(); jobDetail.getJobDataMap().put("appointmentId", appointment.getId()); Date scheduleDate = appointment.computeDesiredScheduleDate(); String cronExpression = convertDateToCronExpression(scheduleDate); CronTrigger trigger = TriggerBuilder.newTrigger().forJob(jobDetail) .withIdentity(UuidUtils.generateId(), "APPOINTMENT_NOTIFICATIONS") .withDescription("Trigger description") .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)) .build(); schedulingService.scheduleJob(jobDetail, trigger); } private String convertDateToCronExpression(Date date) { Calendar calendar = new GregorianCalendar(); if (date == null) return null; calendar.setTime(date); int year = calendar.get(java.util.Calendar.YEAR); int month = calendar.get(java.util.Calendar.MONTH) + 1; int day = calendar.get(java.util.Calendar.DAY_OF_MONTH); int hour = calendar.get(java.util.Calendar.HOUR_OF_DAY); int minute = calendar.get(java.util.Calendar.MINUTE); return String.format("0 %d %d %d %d ? %d", minute, hour, day, month, year); } }
SendEmailJob 클래스는 Job 인터페이스의 구현이며 관련 서비스를 사용하여 이메일을 전송합니다.
업데이트 - 스케줄링 방법에서 실제 작업 실행으로 매개 변수를 전달하는 코드
매개 변수를 전달할 때 jobDataMap이 사용됩니다. 예를 들면 :
public class SendEmailJob implements Job { @Autowired private AppointmentService appointmentService; @Autowired private SendEmailService sendEmailService; @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); // Retrieving passed parameters Long appointmentId = (Long) jobDataMap.get("appointmentId"); Appointment appointment = appointmentService.findById(appointmentId); // Send email sendEmailService.sendEmail(appointment); } }
참고 : 예약 객체가 예약 메소드에서 실제 작업 실행으로 전달 될 수도 있습니다. 다음과 같이 전달할 수 있습니다.
jobDetail.getJobDataMap().put("appointment", appointment);
그리고 얻다:
// Retrieving passed parameters Appointment appointment = (Appointment) jobDataMap.get("appointment");
업데이트 - 구성 코드
Bean 스케줄러는 Quartz 초기화를 담당하는 @Configuration 클래스에 정의된다.
SchedulingConfiguration 클래스는 다음과 같이 정의됩니다.
@Configuration public class SchedulingConfiguration { @Autowired private ApplicationContext applicationContext; @Bean public Scheduler scheduler() throws SchedulerException, IOException { StdSchedulerFactory factory = new StdSchedulerFactory(); factory.initialize(new ClassPathResource("properties/quartz.properties").getInputStream()); Scheduler scheduler = factory.getScheduler(); scheduler.setJobFactory(springBeanJobFactory()); return scheduler; } @Bean public SpringBeanJobFactory springBeanJobFactory() { AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory(); jobFactory.setApplicationContext(applicationContext); return jobFactory; } }
quartz.properties 파일은 resources / properties 폴더에 있습니다. 작업 지속성 데이터베이스는 Oracle 인스턴스입니다.
# Configure Main Scheduler Properties org.quartz.scheduler.instanceName = AppScheduler org.quartz.scheduler.instanceId = AUTO # Configure ThreadPool org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 10 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true # Configure JobStore org.quartz.jobStore.misfireThreshold = 60000 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.oracle.OracleDelegate org.quartz.jobStore.tablePrefix = APP.QRTZ_ org.quartz.jobStore.useProperties = false org.quartz.jobStore.dataSource = appDs org.quartz.jobStore.isClustered = true org.quartz.jobStore.clusterCheckinInterval = 20000 # Configure Datasources org.quartz.dataSource.appDs.driver = oracle.jdbc.driver.OracleDriver org.quartz.dataSource.appDs.URL = jdbc:oracle:thin:@dbsrv:1521:appdb org.quartz.dataSource.appDs.user = db_user org.quartz.dataSource.appDs.password = db_pwd org.quartz.dataSource.appDs.maxConnections = 5 org.quartz.dataSource.appDs.validationQuery = select 0 from dual
마지막 단계는 다음과 같이 애플리케이션 컨텍스트 초기화에서 스케쥴러 메소드를 호출하는 것입니다 (SchedulingService에 추가 된 메소드를 참고하십시오).
public class SchedulingContextListener implements ServletContextListener { private static final Logger logger = LogManager.getLogger(SchedulingContextListener.class); private SchedulingService schedulingService(ServletContextEvent sce) { WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()); return springContext.getBean(SchedulingService.class); } @Override public void contextInitialized(ServletContextEvent sce) { try { this.schedulingService(sce).startScheduler(); } catch (SchedulerException e) { logger.error("Error while Scheduler is being started", e); } } @Override public void contextDestroyed(ServletContextEvent sce) { try { this.schedulingService(sce).shutdownScheduler(); } catch (SchedulerException e) { logger.error("Error while Scheduler is being shutdown", e); } } }
참고 : SchedulingContextListener는 스프링 초기화 또는 기존 스프링 MVC 구성을 사용하여 Spring 구성이 정의 된 방식에 따라 응용 프로그램 초기화시 servletContext에 등록되어야합니다.
희망이 도움이됩니다.
from https://stackoverflow.com/questions/46417393/full-spring-integration-with-quartz-to-implement-real-time-notification-e-mails by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링은 CDI를 지원합니까? [닫은] (0) | 2019.04.03 |
---|---|
[SPRING] Hibernate 4.0.1에서 Spring 3.1을 사용할 때 java.lang.ClassNotFoundException : org.hibernate.util.DTDEntityResolver를 어떻게 해결할 수 있습니까? (0) | 2019.04.03 |
[SPRING] 자바에서 반사에 의해 setter 메서드를 호출하는 방법 (0) | 2019.04.03 |
[SPRING] @Cacheable 주석을 사용하여 스프링 빈을 키로 사용하기 (0) | 2019.04.02 |
[SPRING] 스프링 부트 액추에이터 엔드 포인트의 JSON 출력을 멋지게 출력 (0) | 2019.04.02 |