Использование таймеров Spring --- XML, аннотация, настройка

Java задняя часть база данных Spring
Использование таймеров Spring --- XML, аннотация, настройка

Временные задачи очень распространены в ежедневной разработке системы.Например, мы можем захотеть сделать таймер для запроса статуса транзакции и суммирования его, или мы хотим очистить соответствующие данные базы данных в 4 часа утра, или мы хотим В 0:00 в конце каждого месяца запускать транзакцию регулярно, чтобы делать статистику и отчеты по данным текущего месяца и квартала Пепла много! Я даже не могу закончить!

Существует немного понимания Xiaobian задач синхронизации, то есть: задачи синхронизации просто говорят системе выполнить задачу в определенное время, а что касается того, когда задача выполняется и завершается, это не входит в область задач синхронизации, и задачи синхронизации должны только гарантировать, что команда для вызова задачи может быть выдана в определенное время.

Лидером по реализации задач на время в области Java являетсяquartzв настоящее время,quartzФреймворк широко использовался до весны 3.0 и, конечно же, сейчас,quartzОн поддерживает сохранение данных и соответствующее развертывание кластера. Версия Spring после Spring 3.0 сама по себе реализовала набор структур временных задач. Мы можем рассматривать это какquartzМладшая версия , в ней нет поддержки кластеров, но другие функции уже очень мощные!

Следуя весенней традиции, Spring-Task, собственная структура временных задач Spring, поддерживает как XML, так и аннотации для настройки временных задач.Конечно, редактор также объяснит, как мы настраиваем временные задачи. Открыв пакет с исходным кодом spring, мы можем обнаружить, что на самом деле, помимо собственной задачи spring, Spring также предоставляетquartzИнтеграция того, как Spring интегрируетсяquartz, пожалуйста, прочитайте статью, которую я написал ранееКратко поговорим о фреймворке задач синхронизации Java --- Quartz

Ниже я объясню, как использовать spring-task в трех аспектах: xml, аннотации и настройка.

1. Реализация весенних задач синхронизации на основе конфигурации xml

Существует три компонента задачи с синхронизацией: планировщик, задача и момент времени выполнения. нам нужно импортироватьbean,context,coreТри пружинных пакета.

application.xml

<?xml version="1.0" encoding="UTF-8"?>    
<beans xmlns="http://www.springframework.org/schema/beans"    
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:aop="http://www.springframework.org/schema/aop"   
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:jee="http://www.springframework.org/schema/jee"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="    
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd  
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd  
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/task 
        http://www.springframework.org/schema/task/spring-task-3.0.xsd">  
	<!-- 创建一个调度器 -->
	<task:scheduler id="schedualer"/>
	<!-- 配置任务类的bean -->
	<bean id="xmlTask" class="wokao666.club.spring_task.tasks.XmlTask"></bean>
	<task:scheduled-tasks scheduler="schedualer">
		<!-- 每2秒执行一次 -->
		<task:scheduled ref="xmlTask" method="say" cron="0/2 * * * * ?"/>
	</task:scheduled-tasks>
</beans>

XmlTask.java

package wokao666.club.spring_task.tasks;

import java.text.SimpleDateFormat;

import wokao666.club.spring_task.util.DateFormatter;

/**
 * 基于XML的spring定时任务
 */
public class XmlTask {
    public void say() {
        SimpleDateFormat format = DateFormatter.getDateFormatter();
        System.err.println(format.format(System.currentTimeMillis()) + " I am spring xml-based task!");
    }
}

DateFormatter.java

package wokao666.club.spring_task.util;

import java.text.SimpleDateFormat;

/**
 * 日期格式
 * @author hjw
 *
 */
public class DateFormatter {
    private static volatile SimpleDateFormat formater = null;
    private DateFormatter() {}
    public static SimpleDateFormat getDateFormatter() {
        if(null == formater) {
            synchronized (DateFormatter.class) {
                if(null == formater) {
                    formater = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                }
            }
        }
    return formater;
    }
}

App.java

package wokao666.club.spring_task;

import org.springframework.context.support.ClassPathXmlApplicationContext;


/**
 * Hello world!
 *
 */
public class App 
{
    private static ClassPathXmlApplicationContext ctx;
    public static void main( String[] args ) {
            ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
}

Вывод программы:

六月 10, 2018 10:47:11 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2328c243: startup date [Sun Jun 10 22:47:11 CST 2018]; root of context hierarchy
六月 10, 2018 10:47:11 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
六月 10, 2018 10:47:12 下午 org.springframework.scheduling.concurrent.ExecutorConfigurationSupport initialize
信息: Initializing ExecutorService  'schedualer'
2018-06-10 10:47:14 I am spring xml-based task!
2018-06-10 10:47:16 I am spring xml-based task!
2018-06-10 10:47:18 I am spring xml-based task!

2. Spring-задача на основе аннотаций

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>    
<beans xmlns="http://www.springframework.org/schema/beans"    
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:aop="http://www.springframework.org/schema/aop"   
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:jee="http://www.springframework.org/schema/jee"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="    
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd  
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd  
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/task 
        http://www.springframework.org/schema/task/spring-task-3.0.xsd">  
        <!-- 开启注解驱动 -->
	<task:annotation-driven/>
	<!-- bean 扫描 -->
	<context:component-scan base-package="wokao666.club.spring_task.tasks"></context:component-scan>
</beans>

AnnotationTask.java

package wokao666.club.spring_task.tasks;

import java.text.SimpleDateFormat;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import wokao666.club.spring_task.util.DateFormatter;
/**
 * 测试基于注解的定时任务
 * @author hjw
 */
@Service
public class AnnotationTask {
    @Scheduled(cron="0/2 * * * * ?")
    public void say() {
        SimpleDateFormat format = DateFormatter.getDateFormatter();
        System.err.println(format.format(System.currentTimeMillis()) + " good morning");
    }
}

App.java,DateFormatter.javaКак и выше, вывод программы выглядит следующим образом:

六月 10, 2018 10:53:45 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2328c243: startup date [Sun Jun 10 22:53:45 CST 2018]; root of context hierarchy
六月 10, 2018 10:53:45 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
六月 10, 2018 10:53:46 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition
信息: Overriding bean definition for bean 'org.springframework.context.annotation.internalScheduledAnnotationProcessor' with a different definition: replacing [Generic bean: class [org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.scheduling.annotation.SchedulingConfiguration; factoryMethodName=scheduledAnnotationProcessor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/scheduling/annotation/SchedulingConfiguration.class]]
六月 10, 2018 10:53:46 下午 org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor finishRegistration
信息: No TaskScheduler/ScheduledExecutorService bean found for scheduled processing
2018-06-10 10:53:48 good morning
2018-06-10 10:53:50 good morning
2018-06-10 10:53:52 good morning
2018-06-10 10:53:54 good morning

Обратите внимание на приведенный выше выводNo TaskScheduler/ScheduledExecutorService bean found for scheduled processingЭто предложение, потому что вы можете пройти вjava.util.ExecutorОбъект пула потоков для реализации вызовов асинхронных задач, если вы укажетеexecutorсвойство, spring создаст значение по умолчаниюSimpleAsyncTaskExecutorобъект для выполнения,executorАтрибут указывает пул потоков для выполнения задачи по времени с акцентом на выполнение, в то время какschedulerСвойство представляет собой пул потоков для планирования задач, поскольку Spring по умолчанию использует однопоточное последовательное планирование.Если вы хотите разрешить многопоточное параллельное планирование, вам необходимо настроитьschedulerсвойства, пример конфигурации выглядит следующим образом:

<!-- 调度线程池 -->
<task:scheduler id="scheduler" pool-size="10" />
<!-- 任务执行线程池 -->
<task:executor id="executor" pool-size="10" />
<task:annotation-driven executor="executor" scheduler="scheduler"/>
<context:component-scan base-package="wokao666.club.spring_task.tasks"></context:component-scan>

(Здесь необходимо дополнительно изучить знания и принципы асинхронных задач spring и использовать асинхронное выполнение@Asyncметод маркировки)

3. Пользовательские задачи по времени

Реализуйте настраиваемые задачи по времени, или мы можем изменить связанныеcronВыражение, это выглядит невероятно, но это можно сделать, редакция рекомендует пример статьиSpring @Scheduled временные задачи динамически изменяют параметры cron

CustomSchedual.java

package wokao666.club.spring_task.tasks;

import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import wokao666.club.spring_task.util.DateFormatter;

/**
 * 演示自定义定时器
 */
@EnableScheduling
@Component
public class CustomSchedual implements SchedulingConfigurer{
    
    private static String cron = "0/2 * * * * ?";
    
    private CustomSchedual() {
        new Thread(()->{
            try {
                Thread.sleep(16000);
            } catch (InterruptedException e) {}
            cron = "0/10 * * * * ?";
            System.err.println("change")
        }).start();
    }
    public void configureTasks(ScheduledTaskRegistrar arg0) {
        arg0.addTriggerTask(()->{
            System.err.println(DateFormatter.getDateFormatter().format(System.currentTimeMillis()) + " good night!");
        },(triggerContext)->{
        CronTrigger trigger = new CronTrigger(cron);
        return trigger.nextExecutionTime(triggerContext);
        });
    }
}

Вывод программы выглядит следующим образом, вы можете видеть, что после того, как программа появится через 16 секунд, частота выполнения изменится с 2 секунд/раз до 10 секунд/раз:

六月 10, 2018 11:49:13 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2328c243: startup date [Sun Jun 10 23:49:13 CST 2018]; root of context hierarchy
六月 10, 2018 11:49:13 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
六月 10, 2018 11:49:14 下午 org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor finishRegistration
信息: No TaskScheduler/ScheduledExecutorService bean found for scheduled processing
2018-06-10 11:49:16 good night!
2018-06-10 11:49:18 good night!
2018-06-10 11:49:20 good night!
2018-06-10 11:49:22 good night!
2018-06-10 11:49:24 good night!
2018-06-10 11:49:26 good night!
2018-06-10 11:49:28 good night!
2018-06-10 11:49:30 good night!
change
2018-06-10 11:49:32 good night!
2018-06-10 11:49:40 good night!
2018-06-10 11:49:50 good night!
2018-06-10 11:50:00 good night!
2018-06-10 11:50:10 good night!
2018-06-10 11:50:20 good night!

В конце концов, недостаточно просто использовать его.Надо не только знать правду, но и знать причину.Есть время изучить больше принципов позже.По сути, нижний слой не что иное, как использование пул потоков java Давай, Сао Нянь, спокойной ночи!