【Spring之轨迹】结合 @Scheduled 实现定时将 Redis 缓存刷入数据库(配 Redis 工具类与例子实战)

0. 假设已配置好 SSM 环境

1. 配置文件

有划分配置文件的话建议添加在 spring-service.xml 中,没有的话就放在可以生效的地方

spring-service.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/task
        https://www.springframework.org/schema/task/spring-task.xsd">

    <!-- 扫描 service 下的包 -->
    <!-- service 为定时任务所在的包 -->
    <!-- utils 为 Redis 工具类所在的包 -->
    <context:component-scan base-package="com.qg.service"/>
    <context:component-scan base-package="com.qg.utils"/>

    <!-- 配置注自动装配注解的支持 -->
    <context:annotation-config/>

    <!-- 配置定时任务 -->
    <!-- 配置定时任务的注解驱动 -->
    <task:annotation-driven scheduler="myScheduler"/>

    <!-- 配置定时任务的线程池 -->
    <task:scheduler id="myScheduler" pool-size="5"/>

</beans>

2. 定时服务

ScheduleService.java

public interface ScheduleService {

    /**
     * 定时将用户离线状况存入数据库中
     */
    void userOffLine();
}

ScheduleServiceImpl.java

@Service
public class ScheduleServiceImpl implements ScheduleService {

    @Override
    @Scheduled(cron = "* * */12 * * ? ")
    public void userOffLine() {
		// ...
	}

3. cron 解释

@Scheduled(cron = "* * */12 * * ? ")
表示从程序运行开始,每 12 小时执行一次

① cron 参数(按顺序依次为)

  • 秒(0~59)
  • 分钟(0~59)
  • 小时(0~23)
  • 天(0~31,看月的天数而定)
  • 月(0~11)
  • 星期(1~7 或 SUN,MON,TUE,WED,THU,FRI,SAT)(1 = SUN)
  • 年份(1970-2099)

② 特殊符号

  • , 表示列举可能的值,以秒为例

    10,12,16,40 表示在第 10,12,16,40 秒时执行
    
  • * 表示所有可能的值,如

    每秒钟,每分钟,每小时,每天
    
  • / 指定增量,以秒为例

    */10 表示自开始运行时,每 10 秒执行一次
    0/10 表示自第 0 秒开始,每 10 秒执行一次,即第 0,10,20,30,40,50 ,秒执行
    
  • ? 只用于天和星期两个子表达式,表示不指定值

    当 ”天“ 被指定时,需将 ”星期“ 设置为 ?
    同理 ”星期“ 被设置时,需将 ”天“ 设置为 ?
    这样做时为了避免冲突
    
  • L 只用于天和星期两个子表达式,表示 last(最后),如

    0/20 * 12 L * ? 表示:
    在每月的最后一天(L)中午十二点(12)从 0 开始每隔 20 秒执行一次(0/20)
    L 前还可以加数字,以天数为例,6L 表示每月的倒数第 6 天
    

4. Redis 工具类

Spring 与 Redis 的整合与工具类,参见补充:
【Redis之轨迹】Redis基础入门(Linux & IDEA)(配套工具类例子)

5. 例子实战

将用户的离线信息保存在 redis 缓存中,定时刷入数据库,实现类如下

@Service
public class ScheduleServiceImpl implements ScheduleService {

    @Autowired
    StatusMapper statusMapper;

    /**
     * 设置每隔 1 小时将数据刷入数据库
     */
    @Override
    @Scheduled(cron = "* * 0/1 * * ? ")
    @LogMessage("【将用户离线信息刷入数据库中】")
    public void userOffLine() {
        // 在缓存中拿出全部用户的离线信息,以及对应的 key 集合
        Map<Object, Object> offlineMap = RedisUtils.hashGetAll("user:offline");
        Set<Object> keySet = offlineMap.keySet();

        // 将缓存中的用户离线信息刷入数据库
        keySet.forEach(userId -> {
            // 将数据刷入数据库
            Integer integer = statusMapper.updateOffline(Integer.parseInt(userId.toString()), (String) offlineMap.get(userId));
            System.out.println("【刷入数据库】 用户 id = " + userId + ",离线时间 = " + offlineMap.get(userId) + " -> 是否成功? " + integer);

            // 如果刷入成功,则将该记录从缓存中删去
            if (integer == 1) {
                Long result = RedisUtils.hashDel("user:offline", userId);
                System.out.println("【将缓存中的数据删去】 删除 " + userId + " 是否成功? " + result);
            }
        });
    }
}

接下来只需要将具体的刷入数据库操作,改为存入缓存操作即可,例如:

// 往 Redis 缓存中放入用户的离线时间,并指定 60 分钟失效
RedisUtils.hashSet("user:offline", "" + userId, DateUtil.getTime(), 60 * 60);

深潜曈曚,浅尝晨曦(IceClean)

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寒冰小澈IceClean

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值