SSM-Quartz定时器

x33g5p2x  于2021-09-27 转载在 其他  
字(16.3k)|赞(0)|评价(0)|浏览(445)

我们就不搞乱七八糟的了 直接使用最佳方案 Quartz注解版 而一般情况使用Quartz都会搭配着数据库进行使用…

小二上代码 来了客官…

项目结构

需要的Maven

<dependencies>
       <!--quartz-->
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz-jobs</artifactId>
        <version>2.2.3</version>
    </dependency>
    
       <!--spring-->
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.2.5.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.5.RELEASE</version>
    </dependency>
        <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.5</version>
    </dependency>
    
    <!--java JDBC-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>

    <!--java druid 连接-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.12</version>
    </dependency>

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    
</dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
</project>

配置文件和表

druid.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false
name=root
pass=root
# 初始化连接数量
initialSize=5
#最小空闲连接
minIdle=3
# 最大连接数
maxActive=10
# 最大超时时间  3秒
maxWait=3000

log4j.properties

## 设置Logger输出级别和输出目的地(可以指定多个目的地) ###
### 一般在开发的时候使用debug,开发完成后使用error ###
### 他们对应的是输出信息的级别,级别越低信息输出越详细,使用debug级别的时候,info中的信息也能输出,使用info的时候,debug对应的信息显示不出来 ###
### 日志记录器输出级别:fatal>error>warn>info>debug ###
### 后面的两个对应下方的两处 一处打印在控制台 另一处打印在日志文件里
log4j.rootLogger=debug,console,logFile

#############################################################################################
### 把日志信息输出到控制台 ###
log4j.appender.console=org.apache.log4j.ConsoleAppender
### 信息打印到System.err上,红色 ###
log4j.appender.console.Target=System.out
### 指定日志在控制台上输出的布局类型  采用指定格式的类型 ###
log4j.appender.console.layout=org.apache.log4j.PatternLayout
### %r:输出自应用启动到输出该 log信息耗费的毫秒数    %x表示信息输出时左对齐
### %5p:%p表示输出日志信息优先级,即 DEBUG, INFO, WARN, ERROR, FATAL 中间的5控制最小的宽度为5
### %F:%L %F:输出日志消息产生时所在的文件名称   %L:输出代码中的行号
### %l:输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及行数
### %m:输出代码中指定的消息,产生的日志具体信息  %n:输出一个回车换行符, Windows 平台为"\r\n", Unix 平台为"\n"输出日志信息换行
log4j.appender.console.layout.ConversionPattern= -> (%r ms) - %d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n
#############################################################################################

#############################################################################################
### 把日志信息输出到文件:logt.log 注意:如果有路径\符号一定要写成\\ 否则会被转义  ###
log4j.appender.logFile=org.apache.log4j.FileAppender
### 指定日志输出的文件名 ###
log4j.appender.logFile.File=D:\\log.log
### 指定转换模式 ###
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
### 指定日志布局类型 ###
###log4j.appender.logFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}%l %F %p %m%n
###log4j.appender.logFile.layout.ConversionPattern= -> (%r ms) - %d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n
log4j.appender.logFile.layout.ConversionPattern= -> (%r ms) - %d{yyyy-MM-dd HH:mm:ss}%x[%5p]%l %m%n
#############################################################################################

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置日志-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
        <!-- 懒加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
        <!-- 开启二级缓存-->
        <setting name="cacheEnabled" value= "true" />
    </settings>
    <!-- 别名-->
    <typeAliases>
        <package name="cn.quartz.pojo"/>
    </typeAliases>

    <mappers>
        <package name="com.htsa.dao"/>
    </mappers>

</configuration>

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: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/task http://www.springframework.org/schema/task/spring-task-4.0.xsd ">


    <!--开启Quartz注解驱动-->
    <task:annotation-driven/>
    <!--包扫描-->
    <context:component-scan base-package="cn.quartz"/>


    <!-- 配置数据源 使用外部druid.properties配置文件-->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:druid.properties"/>
    </bean>

    <!-- 连接数据库-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <!-- 基本属性 url、user、password -->
        <property name="driverClassName" value="${driverClassName}"/>
        <property name="url" value="${url}" />
        <property name="username" value="${name}" />
        <property name="password" value="${pass}" />
        <!-- 初始化连接数量-->
        <property name="initialSize" value="${initialSize}" />
        <!-- 最小连接数-->
        <property name="minIdle" value="${minIdle}" />
        <!-- 最大连接数 -->
        <property name="maxActive" value="${maxActive}" />
        <!-- 最大超时时间 3秒-->
        <property name="maxWait" value="${maxWait}"/>
    </bean>

    <!-- 配置sqlSessionFactory工厂 有了这个就可以使用Mybatis接口了-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"> </property>
    </bean>
    <!--获取 sqlSession-->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

    <!-- 配置Dao层下接口 自动生成Mapper实现类 类名为 接口首字母小写 -->
    <!-- MapperScannerConfigurer内部会自动调用SqlSessionFactoryBean-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <property name="basePackage" value="cn.quartz.mapper"/>
    </bean>

    <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 配置事务通知属性 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 定义事务传播属性 -->
        <tx:attributes>
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="edit*" propagation="REQUIRED" />
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="new*" propagation="REQUIRED" />
            <tx:method name="set*" propagation="REQUIRED" />
            <tx:method name="remove*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="change*" propagation="REQUIRED" />
            <tx:method name="check*" propagation="REQUIRED" />
            <tx:method name="get*" propagation="REQUIRED" read-only="true" />
            <tx:method name="find*" propagation="REQUIRED" read-only="true" />
            <tx:method name="load*" propagation="REQUIRED" read-only="true" />
            <tx:method name="*" propagation="REQUIRED" read-only="true" />
        </tx:attributes>
    </tx:advice>

    <!-- 配置事务切面 -->
    <aop:config>
        <aop:pointcut id="serviceOperation" expression="execution(* cn.quartz.service.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
    </aop:config>

</beans>

表user

/* Navicat Premium Data Transfer Source Server : lllllll Source Server Type : MySQL Source Server Version : 50649 Source Host : localhost:3306 Source Schema : test Target Server Type : MySQL Target Server Version : 50649 File Encoding : 65001 Date: 08/03/2021 13:47:09 */

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` int(11) NULL DEFAULT NULL,
  `sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'hu', 22, '男');
INSERT INTO `user` VALUES (2, 'an', 23, '女');
INSERT INTO `user` VALUES (3, 'he', 22, '男');
INSERT INTO `user` VALUES (4, 'huan', 21, '男');
INSERT INTO `user` VALUES (11, 'huanmin', 22, '男');

SET FOREIGN_KEY_CHECKS = 1;

job

package cn.quartz.job;

import cn.quartz.pojo.User;
import cn.quartz.service.UserService;
import org.quartz.DisallowConcurrentExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

@Component
@DisallowConcurrentExecution
public class MyTask {

    @Autowired
    private UserService userService;

    @Scheduled(cron = "0/10 * * * * ?")  //每10秒执行一次
    public void excTask(){

        System.out.println("定时任务执行,执行时间是:"+new Date());
        List<User> users = userService.selectAll();
        System.out.println("查询数据库user表的全部值是:"+users);
    }
}

mapper

package cn.quartz.mapper;

import cn.quartz.pojo.User;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface UserMapper {

    @Select("select * from user")
    List<User> selectAll();

}

pojo

package cn.quartz.pojo;

import java.io.Serializable;

public class User implements Serializable {
    private Integer id;

    private String name;

    private Integer age;

    private String sex;

   ......get set toString
}

service

UserService

package cn.quartz.service;

import cn.quartz.pojo.User;

import java.util.List;

public interface UserService {

    List<User> selectAll();

}

impl/UserServiceImpl

package cn.quartz.service.impl;

import cn.quartz.mapper.UserMapper;
import cn.quartz.pojo.User;
import cn.quartz.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<User> selectAll() {
        return userMapper.selectAll();
    }
}

测试启动类

package cn.quartz;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("ApplicationContext.xml");
    }

}

测试结果这里就不贴上了 大概就是没10秒就从数据库查询一次user表内的全部数据 然后打印在控制台

定时器配合Redis使用

在上面案例的基础上我们增加Redis进行使用

我们来想一个案例就是秒杀商品 全部步骤之一中的商品录入

秒杀查询压力是非常大的,我们可以在秒杀之前把秒杀商品存入到Redis缓存中,页面每次列表查询的时候直接从Redis缓存中取,这样会大大减轻MySQL数据库的压力。我们可以创建一个定时任务工程,每天秒杀的前一天运行并加载MySQL数据库数据到Redis缓存。

项目结构:

图中utils里的工具类就不提供了还有和工具类相关的配置文件

因为Redis在java中使用方式有很多 所以为这里只提供思想

关键代码

package cn.quartz.job;

import cn.quartz.pojo.User;
import cn.quartz.service.UserService;
import cn.quartz.utils.JsonTurnUtils;
import cn.quartz.utils.RedisUtis;
import org.quartz.DisallowConcurrentExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Component
@DisallowConcurrentExecution
public class MyTask {
    
    @Autowired
    private UserService userService;

    //每天23点59分钟 开始将数据库最新的数据录入到 Redis里
    @Scheduled(cron = "0 59 23 * * ?")
    public void excTask(){
        System.out.println("定时任务执行,执行时间是:"+new Date());
        List<User> users = userService.selectAll();
        System.out.println("查询数据库user表的全部值是:"+users);
        String josn= JsonTurnUtils.objTurnJson(users);
        RedisUtis.setStringRedis("userAll",josn);
    }

    //上面代码的测试版
    @Scheduled(cron = "0 0/1 * * * ?") //每一分钟录入一次
    public void excTask_test(){

        System.out.println("定时任务执行,执行时间是:"+new Date());
        List<User> users = userService.selectAll();
        System.out.println("查询数据库user表的全部值是:"+users);
        String josn= JsonTurnUtils.objTurnJson(users);
        RedisUtis.setStringRedis("userAll",josn);
        //记录录入的时间
        Date dNow = new Date( );
        SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
        RedisUtis.setStringRedis("userAll_date", ft.format(dNow));
        System.out.println("数据录入到Redis成功");
    }
}

然后我们使用reids进行查询下

@Test
    public   void   getKey(){
        String userAll = RedisUtis.getStringRedis("userAll");
        System.out.println("数据: "+userAll);
        String userAll_date= RedisUtis.getStringRedis("userAll_date");
        System.out.println("录入数据的最后时间:"+userAll_date);
        
    }

数据: [{“id”:1,“name”:“hu”,“age”:22,“sex”:“男”},{“id”:2,“name”:“an”,“age”:23,“sex”:“女”},{“id”:3,“name”:“he”,“age”:22,“sex”:“男”},{“id”:4,“name”:“huan”,“age”:21,“sex”:“男”},{“id”:11,“name”:“huanmin”,“age”:22,“sex”:“男”}]
录入数据的最后时间:2021-03-08 04:14:00

小结: 使用Quartz定时器能干的事情太多太多了

比如:

  1. 定时生成报表
  2. 信用卡自动还款
  3. 定时给当年暗恋女神发一封匿名贺卡
  4. 想每隔1小时,备份一下自己的爱情动作片
  5. 订单支付来说,超过一定时间会执行这个job,去判断你是否支付,未支付就会取消此次订单
  6. 银行每天会自动下载流水
  7. 出于安全考虑,长时间没有修改密码会发出警告
  8. 会员到期了,TX提醒你进行充值

根据上面的这些案例 我们可以总结出 ,Quartz就是干自动化的 也就是当条件满足时自动完成一些任务而不依托于主程序

注意: 要预防一件事,就是如果集群系统了,那么定时器如何保证在多个系统中只执行一个呢? ,可以使用redis的分布式锁…
点赞 -收藏-关注-便于以后复习和收到最新内容有其他问题在评论区讨论-或者私信我-收到会在第一时间回复如有侵权,请私信联系我感谢,配合,希望我的努力对你有帮助^_^

相关文章