Spring定时任务@Scheduled

news/2024/10/23 5:39:22/

在 Spring 框架中,可以使用定时任务来执行周期性或延迟执行的任务。Spring 提供了多种方式来配置和管理定时任务。有Java自带的java.util.Timer类,也有强大的调度器Quartz,还有SpringBoot自带的Scheduled。

在实际应用中,如果没有分布式场景(quartz 支持分布式, schedule 不支持(需要自己实现,用分布式锁),schedule跟spring结合的更好,还是很适用的。

以下介绍的是使用@Scheduled 注解的方式:

1、在启动类上添加@EnableScheduling 注解来开启定时器任务

2、在实现类的方法上添加@Scheduled 注解并设置相关参数

    @Scheduled(cron = "0 22 14 * * ? ")@Overridepublic void testSchedule() {System.out.println("测试定时器");log.debug("定时任务已启动");}

3、相关参数

cron:cron表达式,指定任务在特定时间执行;


图片来源:Cron - 在线Cron表达式生成器

fixedDelay:表示上一次任务执行完成后多久再次执行,参数类型为long,单位ms;
fixedDelayString:与fixedDelay含义一样,只是参数类型变为String;
fixedRate:表示按一定的频率执行任务,参数类型为long,单位ms;
fixedRateString: 与fixedRate的含义一样,只是将参数类型变为String;
initialDelay:表示延迟多久再第一次执行任务,参数类型为long,单位ms;
initialDelayString:与initialDelay的含义一样,只是将参数类型变为String;
zone:时区,默认为当前时区,一般没有用到。

4、实现用户的预加载功能

业务分析:

(1)预加载能够访问系统的用户(即用户数据存在在数据库中)

        实现逻辑:查找数据库中所有有效用户放入availableUsers哈希表中;

                          给有效用户设置缓存过期的时间,超时删除availableUsers表中该用户缓存。

(2)每个用户有60s时间登录访问系统,超出60秒,从系统中删除

        需要判断:该用户是否存在(数据库)

                          该用户是否超时(能否访问系统)  

5、部分代码示例

UserService层接口方法

    /*** 1、从数据库查出所有用户放入 aviableUsers*/void preLoginUser();//2、redis VIP用户登录预加载,超时删除该用户void preStoreUserInRedis(long roleId);//3、使用上面preStoreUserInRedis方法将roleId=1的有效用户放入vipLoginUsers哈希表中void vipLogin(String username, String password);

UserServiceImpl实现类

    //1、查找数据库中所有有效用户放入availableUsers哈希表中@Scheduled(cron = "0 06 16 * * ?")@Overridepublic void preLoginUser() {List<User> users = userDao.findAll();users.forEach(u->objectRedisTemplate.opsForHash().put("availableUsers","availableUsers:"+u.getUsername(),u));objectRedisTemplate.expire("loginUsers",1, TimeUnit.DAYS);}//2、redis VIP用户登录预加载,超时删除该用户@Overridepublic void preStoreUserInRedis(long roleId) {
//        List<User> users = userDao.findAll();
//        users.forEach(u->
//                objectRedisTemplate.opsForHash().
//                        put("loginUser","loginUser:"+u.getUsername(),u));
//        objectRedisTemplate.expire("loginUser",60, TimeUnit.SECONDS);
//// Set<Object> availableUsers = redisTemplate.opsForHash().keys("availableUsers");//所有用户//System.out.println(availableUsers);//System.out.println("--->"+redisTemplate.opsForHash().entries("availableUsers"));Map<Object, Object> map = objectRedisTemplate.opsForHash().entries("availableUsers");//对所有有效用户遍历map遍历map.forEach((k,v)->{User user = (User) v;if(user.getRoleId().intValue()==roleId){ //如果角色为1,放入活动d的redis缓存objectRedisTemplate.opsForHash().put("vipLoginUsers","vipLoginUsers:"+user.getUsername(),user);}});objectRedisTemplate.expire("vipLoginUsers",60, TimeUnit.SECONDS);}//3、使用上面preStoreUserInRedis方法将roleId=?的有效用户放入vipLoginUsers哈希表中//另外,加入异常@Overridepublic void vipLogin(String username, String password) {/*使用 Redis 的 opsForHash().get() 方法从名为 "availableUsers" 的 Hash 中获取键key为 "availableUsers:" + username 的值value,并将其赋给 availableUsers 对象。如果获取到的值为空,则表示该用户不存在。如果用户不存在,在下一行将会抛出自定义异常 IlegealUserException。*/Object availableUsers = objectRedisTemplate.opsForHash().get("availableUsers", "availableUsers:" + username);if(Objects.isNull(availableUsers)) throw  new IlegealUserException("用户不存在异常");Object vip = objectRedisTemplate.opsForHash().get("vipLoginUsers", "vipLoginUsers:" + username);if(Objects.isNull(vip)) throw  new NotVipException("不是有效的vip用户禁止登录");/*总的来说,这段代码用于进行 VIP 用户登录验证。首先,从 Redis 中获取用户名对应的用户信息 aviableUsers,如果为空,表示用户不存在,会抛出 IlegealUserException 异常。然后,从 Redis 中获取用户名对应的 VIP 用户信息 vip,如果为空,表示用户不是 VIP 用户,会抛出 NotVipException 异常。如果两个条件都满足,则表示用户存在且为 VIP 用户,可以进行后续操作。*/}

控制层

    //3、VIP用户按时登录完成@GetMapping("/vipLogin")public HttpResp vipLogin(String username, String password){userService.vipLogin(username,password);return HttpResp.success("按时登录完成");}//2、预先加载所有vip客户到缓存中,根据roleId=?查询出的(业务实现层)@GetMapping("/setVip")public HttpResp setVip(long roleId){userService.preStoreUserInRedis(roleId);return HttpResp.success("预先加载所有vip客户到缓存中");}

参考:

SpringBoot学习-(十九)SpringBoot定时器#Schedule_wx6345200418f8c的技术博客_51CTO博客

https://www.cnblogs.com/toutou/p/9802955.html


感谢阅读,码字不易,多谢点赞!如有不当之处,欢迎反馈指出,感谢!


http://www.ppmy.cn/news/1168948.html

相关文章

B-tree(PostgreSQL 14 Internals翻译版)

概览 B树(作为B树访问方法实现)是一种数据结构&#xff0c;它使您能够通过从树的根向下查找树的叶节点中所需的元素。为了明确地标识搜索路径&#xff0c;必须对所有树元素进行排序。B树是为有序数据类型设计的&#xff0c;这些数据类型的值可以进行比较和排序。 下面的机场代…

[每周一更]-(第68期):Excel常用函数及常用操作

日常工作&#xff0c;偶尔也会存在excel表格入库的情况&#xff0c;针对复杂的入库情况&#xff0c;一般都是代码编号&#xff0c;读文件-写db形式&#xff1b;但是有些简单就直接操作&#xff0c;但是 这些简单的入库不仅仅是直接入库&#xff0c;而是内容中有部分需要进行映射…

Cannot load from short array because “sun.awt.FontConfiguration.head“ is null

错误描述 在使用Easyexcel时发生了报错&#xff0c;请求返回空白 但是只在Linux上出现了该报错&#xff0c;在本地windows环境没有出现 JDK都使用的是17版本 错误原因 由于在linux上缺失Easyexcel使用的字体导致 解决办法 下载一个jdk1.8 在其jre/lib目录里复制fontconfi…

【Edabit 算法 ★☆☆☆☆☆】 Correct the Mistakes

【Edabit 算法 ★☆☆☆☆☆】 Correct the Mistakes bugs language_fundamentals algebra Instructions Fix the code in the code tab to pass this challenge (only syntax errors). Look at the examples below to get an idea of what the function should do. Examples…

学成在线第二天-查询课程、查询课程分类、新增课程接口实现以及跨域的处理思路和全局异常处理的使用以及面试题

目录 一、接口的实现 二、跨域的处理思路 三、全局异常处理 四、面试题 五、总结 一、接口的实现 1. 查询课程接口 思路&#xff1a; 典型的分页查询 按需查询 模糊查询的查询 controller&#xff1a; ApiOperation(value "课程列表", notes "课程…

DVWA(一)

环境搭建 搭建DVWA Web渗透测试靶场_dvwa 白屏-CSDN博客 Brute Force&#xff08;暴力破解&#xff09; LOW 输入账号密码 burp suite拦截请求 请求发送至intruder attack type:选择cluster bomb,将用户名和密码Add添加 payload 1 添加用户名字典&#xff0c;payload 2 添…

Python学习第3天-第一个Python程序

文章目录 前言一、创建项目二、创建程序总结 前言 下面给大家展示下经典的Hello World! 一、创建项目 二、创建程序 print("Hello World!")总结 回到顶部 学习网站 欢迎来到Python的世界&#xff01;

Elasticsearch 8.9 Master节点处理请求源码

大家看可以看ElasticSearch源码&#xff1a;Rest请求与Master节点处理流程&#xff08;1&#xff09; 这个图非常好&#xff0c;下午的讲解代码在各个类和方法之间流转&#xff0c;都体现这个图上 一、Master节点处理请求的逻辑1、节点(数据节点)要和主节点进行通讯&#xff0…