定时任务,这个刚开始接触是在定时导数据,当时要求将某个数据库中的数据,导入另一个表中,这样就写程序,写执行java程序的shell 脚本 最后在linux的crontab 中指定shell 脚本的定时执行。而之后又知道有Quartz 这个定时框架,在后台换公司发现公司有使用定时但使用的是spring 自带的,一查才知道spring3.0 后spring才有了这个功能,下面我们就看看spring 的定时功能。
下面先来看一个超级简单的实例
一、简单的实例1
1、超级简单的目录结构
2、spring 的配置文件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:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd" default-lazy-init="true"> <description>Spring </description> <!-- Enables the Spring Task @Scheduled programming model --> <task:executor id="executor" pool-size="50" /> <task:scheduler id="scheduler" pool-size="100" /> <task:annotation-driven executor="executor" scheduler="scheduler" /> <!-- 配置自定义任务 --> <bean name="scrapydTask" lazy-init="false" class="com.test.Test"></bean> <!-- <bean name="salaryTask" lazy-init="false" class="com.beizhi.hrd.sys.task.SalaryTask"></bean> <bean name="createAttenTask" lazy-init="false" class="com.beizhi.hrd.sys.task.CreateAttenTask"></bean> --> </beans>
(1)、比如要引入tasx命名空间:
xmlns:task="http://www.springframework.org/schema/task"
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
(2)、task:annotation-driven 设置:
<task:executor id="executor" pool-size="50" /> <task:scheduler id="scheduler" pool-size="100" /> <task:annotation-driven executor="executor" scheduler="scheduler" />
<bean name="scrapydTask" lazy-init="false" class="com.test.Test"></bean>其中name 是唯一的 而class 就是要执行定时任务的类
3、定时任务执行类
package com.test; import org.springframework.scheduling.annotation.Scheduled; public class Test { // 这里的时间和linux crontab中写的格式是一样的 @Scheduled(cron = "0 0/1 * * * *") void schedule(){ System.out.println("1234"); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>hrdTask</display-name> <!-- Spring ApplicationContext配置文件的路径,可使用通配符,多个路径用,号分隔 此参数用于后面的Spring Context Loader --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:/config/application.xml </param-value> </context-param> <!--Spring的ApplicationContext 载入 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
总结: 在写spring的定时任务时一定要注意第一spring的版本要在3.0 以上,第二我们在spring的配置文件中一定要引入task 命名空间,第三我们要配置task 、第四我们要写定时任务类并配置到spring的配置文件中,第五 我们写的执行类要的schedule 方法上一定要有@Scheduled 注解,其他的和平时使用时的配置没有什么区别。
二、spring +mybatis 整合使用定时向数据库中导入数据
我这里的demo 就是将controller 层相当于用定时任务程序来替代了,后面的其他的都是一样的,下面我们来看看
1、整体结构:
从整体结构可以看出,变化了的只有controller 层即消失了而多了个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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"> <!-- 加载配置JDBC文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>${jdbc.driverClassName}</value> </property> <property name="url"> <value>${jdbc.url}</value> </property> <property name="username"> <value>${jdbc.username}</value> </property> <property name="password"> <value>${jdbc.password}</value> </property> </bean> <!--使用自动注入的时候要 添加他来扫描bean之后才能在使用的时候 --> <context:component-scan base-package="com.website.service ,com.website.dao" /> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- mybatis配置文件路径 --> <property name="configLocation" value="" /> <!-- 实体类映射文件路径,在开发中映射文件肯定是多个所以使用mybatis/*.xml来替代 --> <property name="mapperLocations" value="classpath:mybatis/UserMapping.xml" /> </bean> <!--其实这里类的实例就是mybatis中SQLSession --> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0"> <ref bean="sqlSessionFactory" /> </constructor-arg> </bean> <!-- 定义事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 下面使用aop切面的方式来实现 --> <tx:advice id="TestAdvice" transaction-manager="transactionManager"> <!--配置事务传播性,隔离级别以及超时回滚等问题 --> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="del*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="*" rollback-for="Exception" /> </tx:attributes> </tx:advice> <aop:config> <!--配置事务切点 --> <aop:pointcut id="services" expression="execution(* com.website.service.*.*(..))" /> <aop:advisor pointcut-ref="services" advice-ref="TestAdvice" /> </aop:config> <!-- 定时任务 --> <task:executor id="executor" pool-size="50" /> <task:scheduler id="scheduler" pool-size="100" /> <task:annotation-driven executor="executor" scheduler="scheduler" /> <!--定时任务类 --> <bean name="scrapydTask" lazy-init="false" class="com.website.task.Task"></bean> </beans>
3、web.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>website2</display-name> <!-- 加载spring容器配置 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 设置Spring容器加载配置文件路径 程序的入口--> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:config/ApplicationContext.xml </param-value> </context-param> </web-app>
4、定时任务执行类:
package com.website.task; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import com.website.service.UserService; /** * @author WHD data 2016年7月3日 */ @Component public class Task { // 自动注入 @Autowired private UserService userService; // 设置执行时间 @Scheduled(cron = "0 0/1 * * * *") void schedule() { Map<String, String> map = new HashMap<String, String>(); map.put("id", "whd6"); map.put("name", "whd6"); map.put("password", "whd6"); // 调用service层的方法向数据库中插入数据 userService.saveUser(map); System.out.println("123"); } }
总结:
使用spring 的定时功能挺方便的,下面总结一下流程:
1、web.xml 配置文件
这个配置文件是程序的入口,其中配置了spring 配置文件的路径,同时在启动服务(tomcat……)时会加载解析这个文件
2、spring 配置文件,这个文件中配置了spring需要的东西同时可以配置mybatis 的配置以及事务,定时任务等的配置
3、如果是spring和mybatis 整合的则需要配置mybatis的映射文件
4、定时任务执行类的编写,注意这里的类名要和spring 配置文件写的那个定时任务的类名称要一致不然的话,找不到就不会执行了。
总的一句话来说,之前你不管是使用 springmvc+spring+mybatis 还是 springmvc+spring+hibernate 那些配置文件你都可以不用修改,只需要在spring 配置文件中引入xmlns:task="http://www.springframework.org/schema/task" 同时写定时任务,使用定时任务类来取代controller 来调用service 层的方法。
当然上面说的那是在刚学习的时候或不熟悉的情况下可以这样修改,当我们熟悉了后,看到多余的代码我们会很烦,这时你可以吧web.xml配置文件中除了指定spring配置文件的路径的配置外,可以吧其他所有配置都删除,具体的可以参考上面的demo,而spring+mybatis 或hibernate 的配置就不要修改了。
注意点:
1、必须是spring3.0以上版本
2、spring配置文件中一定要引入task 命名空间
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
4、写的定时任务类名称要和spring配置文件中的定时任务类名称一致
5、定时任务类的方法名称以及注解要注意添加
package com.website.task; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import com.website.service.UserService; /** * @author WHD data 2016年7月3日 */ @Component public class Task { // 自动注入 @Autowired private UserService userService; // 设置执行时间 @Scheduled(cron = "0 0/1 * * * *") void schedule() { Map<String, String> map = new HashMap<String, String>(); map.put("id", "whd6"); map.put("name", "whd6"); map.put("password", "whd6"); // 调用service层的方法向数据库中插入数据 userService.saveUser(map); System.out.println("123"); } }