Spring定时任务@Scheduled

在 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表达式,指定任务在特定时间执行;

Spring定时任务@Scheduled_第1张图片
图片来源: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 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 users = userDao.findAll();
//        users.forEach(u->
//                objectRedisTemplate.opsForHash().
//                        put("loginUser","loginUser:"+u.getUsername(),u));
//        objectRedisTemplate.expire("loginUser",60, TimeUnit.SECONDS);
//

        // Set availableUsers = redisTemplate.opsForHash().keys("availableUsers");//所有用户
        //System.out.println(availableUsers);
        //System.out.println("--->"+redisTemplate.opsForHash().entries("availableUsers"));
        Map 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


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

Spring定时任务@Scheduled_第2张图片

你可能感兴趣的:(redis,springboot,java,spring,java,redis)