Spring定时任务@Scheduled

news2024/11/27 4:23:52

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

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

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

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

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

    @Scheduled(cron = "0 22 14 * * ? ")
    @Override
    public 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 * * ?")
    @Override
    public 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用户登录预加载,超时删除该用户
    @Override
    public 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哈希表中
    //另外,加入异常
    @Override
    public 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.coloradmin.cn/o/1122315.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实际项目中如何进行问题排查

Linux自带 文本操作 文本查找 - grep文本分析 - awk文本处理 - sed文件操作 文件监听 - tail文件查找 - find网络和进程 网络接口 - ifconfig防火墙 - iptables -L路由表 - route -nnetstat其他常用 进程 ps -ef | grep java分区大小 df -h内存 free -m硬盘大小 fdisk -l | gr…

STM32F4_USB读卡器(USB_Slave)/USB U盘(Host)

前言 STM32F4芯片自带了USB OTG FS&#xff08;FS&#xff0c;即全速&#xff0c;12Mbps&#xff09;和USB OTG HS&#xff0c;支持USB Host和USB Device。 1. USB简介 USB&#xff0c;是英文Universal Serial BUS&#xff08;通用串行总线&#xff09;的缩写&#xff0c;是一…

硬盘无法分区的原因以及3种解决方法!

硬盘无法分区的原因 无论是新买的硬盘还是用了很久的硬盘&#xff0c;在分区过程中都可能会遇到硬盘无法分区的问题。在这里我们总结了以下几点原因&#xff1a; 主板生产商为了防止病毒侵入引导区文件在主板进行了设置&#xff0c;导致硬盘无法进行分区。 新买的硬盘没有…

42910-2023 无机胶粘剂高温压缩剪切强度试验方法

1 范围 本文件描述了在高温条件下测定无机胶粘剂压缩剪切强度的试验方法。 本文件适用于300℃~1000℃温度范围内&#xff0c;耐热陶瓷、复合材料及其他非金属材料之间搭接压缩 剪切强度的测定。 2 规范性引用文件 下列文件中的内容通过文中的规范性引用而构成本文件必不可…

一、BurpSuite基本界面学习

一、Dashboard 1.Scan Scan功能&#xff1a;能够对网站进行爬行&#xff08;主要发现网站可交互的接口和网址关联的路径&#xff0c;结果显示在Target&#xff09;和代码审计&#xff08;除了爬行的效果外&#xff0c;一定程度上会进行漏洞发现与查找&#xff09; 重点&#…

VMware17.0安装教程(2023最新最详细)

目录 一.简介 二.安装步骤 软件&#xff1a;VMware版本&#xff1a;17.0语言&#xff1a;简体中文大小&#xff1a;554.98M安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.6GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨下载链接&#xff1a; htt…

如何快速从Oracle迁移到Mysql?

database 一、使用navicat工具二、问题 一、使用navicat工具 1、选择工具中的数据传输 2、源选Oracle,目标选Mysql,一直点下一步 二、问题 1、navicat连接oracle报错:Oracle library is not loaded navicat是通过oracle的客户端连接oracle的,报这个错是因为navicat for or…

SpringBoot 入门 参数接收 必传参数 数组 集合 时间接收

接口声明 RestController //表示该类为请求处理类public class HttpDeal {RequestMapping("/login")//这个方法处理哪一个地址过来的请求public String hello(){return "返回给浏览器";}}接收参数 RequestMapping("/login")public String logi…

【tg】2:视频采集的输入和输出

属于libtgcalls模块使用了 media thread和 worker thread 代码分布 视频采集 对外的interface :VideoCaptureInterface static std::unique_ptr<VideoCaptureInterface> Create(std::shared_ptr<Threads> threads

看《软技能》的读后感

最近在图书大夏看了一本书的一部分&#xff0c;书名是《软技能》。本人看到了几个有意思的观点。一是接一些兼职项目。 二是分享自己的技术&#xff0c;让同事能干自己的工作&#xff0c;让自己的工作变得别人也能干&#xff0c;才有机会让自己的职位提升。 三是让手动操作变…

一个功能强大的Flutter开源聊天列表插件

flutter_im_list是一款高性能、轻量级的Flutter聊天列表插件。可以帮助你快速创建出类微信的聊天列表的效果。 目录 预览图示例视频教程如何使用API 预览图 整体长按输入中动图 示例 Examples 视频教程 欢迎通过视频教程学习交流。 如何使用 第一步添加依赖 在项目根…

爬虫进阶-反爬破解7(逆向破解被加密数据:全方位了解字体渲染的全过程+字体文件的检查和数据查看+字体文件转换并实现网页内容还原+完美还原上百页的数据内容)

目录 一、全方位了解字体渲染的全过程 1.加载顺序 2.实践操作&#xff1a;浏览器中调试字体渲染 3.总结&#xff1a; 二、字体文件的检查和数据查看 1.字体文件的操作软件 2.映射关系的建立 3.实践操作&#xff1a;翻找样式和真实内容 4.总结&#xff1a; 三、字体文…

【c++】简单了解运算符重载

引例 class Integer{ public:Integer(int num):_num(num){}int& getValue(){return _num;} private:int _num; };现在有两个Integer对象a,b。想让a和b相加得到的结果给对象c&#xff0c;现在可以肯定的是cab编译后肯定会报错 请注意这条信息no match for operator (oper…

Zookeeper、Kafka集群与Filebeat+Kafka+ELK架构、部署实例

Zookeeper、Kafka集群与FilebeatKafkaELK架构、部署实例 一、Zookeeper1.1、Zookeeper 定义1.2、Zookeeper 工作机制1.3、Zookeeper 特点1.4、Zookeeper 数据结构1.5、Zookeeper 应用场景1.5、Zookeeper 选举机制1.5.1、 第一次启动选举机制1.5.2、 非第一次启动选举机制 二、Z…

信息系统项目管理师教程 第四版【1-共24章整体脑图整理】

信息系统项目管理师教程 第四版 电子版链接 链接&#xff1a;https://pan.baidu.com/s/1cicvAH519G-j2IBjE69JCQhttps://link.zhihu.com/?targethttps%3A//pan.baidu.com/s/1cicvAH519G-j2IBjE69JCQ 提取码&#xff1a;1qaz 如果失效可以用下面这个&#xff0c; 链接&…

Java EE-servlet API 三种主要的类

上述的代码如下&#xff1a; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.i…

MQ相关介绍

【1】MQ&#xff1a;MessageQueue&#xff0c;消息队列。 队列&#xff0c;是一种FIFO 先进先出的数据结构。消息由生产者发送到MQ进行排队&#xff0c;然后按原来的顺序交由消息的消费者进行处理。QQ和微信就是典型的MQ。 为什么要用MQ&#xff08;MQ的优点&#xff09;&#…

Seata学习

Seata Seata 是一款开源的分布式事务解决方案&#xff0c;致力于在微服务架构下提供高性能和简单易用的分布式事务服务。 官网地址&#xff1a;https://seata.io/zh-cn/index.html 为什么会产生分布式事务&#xff1f; 示例&#xff1a;用户下单后需要创建订单&#xff0c;同时…

关于动态内存管理中的常见练习题

文章目录 前言练习1&#xff1a;练习2&#xff1a;练习3&#xff1a;练习4&#xff1a; 前言 学习完C语言中的动态内存管理&#xff0c;大家开始利用动态内存管理来去开辟空间&#xff0c;经过一顿狂敲代码后&#xff0c;发现了问题&#xff0c;程序要么崩掉&#xff0c;要么运…