解决思路:
- 图片上传云端后将图片上传后的路径添加到Redis数据库,用Set类型存储
//此处使用的是阿里云 @PostMapping("/upload") public Result upload(MultipartFile imgFile) { log.info("文件上传:{}",imgFile); try { //获取文件原始名 String originalFilename = imgFile.getOriginalFilename(); //获取文件后缀名 String extension = originalFilename.substring(originalFilename.lastIndexOf('.')); //生成新文件名 UUID是获取一个随机字符串 String objectName = UUID.randomUUID() + extension; //文件请求路径 String filePath = aliOssUtil.upload(imgFile.getBytes(), objectName); //保存路径到Redis,方便后面对垃圾文件进行处理 redisTemplate.opsForSet().add("imgOnAliOSS",filePath); return new Result(true, MessageConstant.UPLOAD_SUCCESS, filePath); } catch (IOException e) { log.error("文件上传失败:{}",e.getMessage()); } return new Result(false, MessageConstant.PIC_UPLOAD_FAIL); }
- 套餐数据进行增、改操作时添加路径信息到Redis另一个Set类型存储,删除时将路径信息从Redis删除
@Transactional //开启事务 public void addSetmeal(Setmeal setmeal) { //新增套餐 setmealMapper.insert(setmeal); //添加新增图片地址到Redis库存储 key value redisTemplate.opsForSet().add("imgOnLocal", setmeal.getImg()); } @Transactional public void updateSetmeal(Setmeal setmeal) { //更新检查组 setmealMapper.update(setmeal); //添加新增图片地址到Redis库存储 key value redisTemplate.opsForSet().add("imgOnLocal", setmeal.getImg()); } @Override @Transactional public void delete(Long id) { //查找数据库获取图像信息 Setmeal setmeal = setmealMapper.getById(id); //删除Redis数据库中存储的图片信息 key value redisTemplate.opsForSet().remove("imgOnLocal",setmeal.getImg()); //删除套餐 setmealMapper.deleteById(id); }
- 通过SpringTask定时校验云端是否存在垃圾数据,存在就调用阿里云工具类删除,同时删除云端垃圾文件在Redis数据库中存储信息。
@Slf4j @Component public class RedisTask { @Autowired private RedisTemplate redisTemplate; @Autowired private AliOssUtil aliOssUtil; @Scheduled(cron = "0 0 1 * * ?") public void deleteImgFile() { log.info("定时清理垃圾文件"); //输出日志信息 //获取Redis中Set类型的对象 SetOperations setOperations = redisTemplate.opsForSet(); //获取数据库数据和云端数据交集 Set<String> intersect = setOperations.intersect("imgOnAliOSS", "imgOnLocal"); //创建新的Redis表存储交集数据 for (String value : intersect) { setOperations.add("intersect", value); } //获取云端多余数据 Set<String> difference = setOperations.difference("imgOnAliOSS", "intersect"); if (difference != null && difference.size() > 0) { for (String filePath : difference) { //我的项目中Redis存储信息和阿里云工具类中需要的信息不符合,用split()函数更改一下 String[] split = filePath.split("/"); //删除云端上的多余数据 aliOssUtil.delete(split[3]); //清楚Redis数据库中存储的云端多余信息,防止下次运行时出错 setOperations.remove("imgOnAliOSS",filePath); } } redisTemplate.delete("intersect"); } }
用到的技术:
Redis:
Redis是一个内存存储的数据结构数据库,可以用来当数据库、高速缓存和消息队列代理,数据类型有字符串、哈希表、列表、集合、有序集合等,我这里使用的是SpringDataRedis, 在SpringBoot项目中可以通过配置pom.xml文件添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
并在application.yml文件中配置自定义的信息
redis: host: localhost #服务器 port: 6379 #端口号 password: root #看你个人有没有设置密码,没有不用配置 database: 10 #数据库
然后编写配置类,创建RedisTemplate对象(这一步操作中也会修改一下Redis key的序列化器,最后就可以通过RedisTemplate对象操作Redis数据库)
@Configuration @Slf4j public class RedisConfiguration { @Bean public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){ log.info("开始创建redis模板对象..."); RedisTemplate redisTemplate = new RedisTemplate(); //设置redis的连接工厂对象 redisTemplate.setConnectionFactory(redisConnectionFactory); //设置redis key的序列化器 redisTemplate.setKeySerializer(new StringRedisSerializer()); return redisTemplate; } }
注意事项:在项目中使用Redis数据库时数据库必须启动,不然没法用(踩过很多次这个坑)
SpringTask
SpringTask: 多用来设置定时任务:定时获取信息、发送信息、执行操作等,首先在SpringBoot项目的启动类上添加注解
@SpringBootApplication @EnableScheduling //开启定时任务 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
然后创建定时任务
@Scheduled(cron = "0/5 * * * * ?") public void sendMessageToClient() { System.out.println("Hello"); }
定时任务方法上需要添加
其中cron表达式(上面用的就是),对应分别是 秒 分 时 日 月 周 (还有年,但这里没用)。cron表达式可以通过在线工具直接生成。
fixedDelay间隔时间是上次任务结束时才开始计时,fixedRate规定了两次定时任务执行的时间间隔,理论上当上一个定时任务开始执行时,下一个定时任务开始时间就已经确定了。(这两种我目前没使用过)
还有一个属性叫做:
注意事项:SpringTask默认单线程执行,多线程时会影响到定时策略。SpringTask默认不支持分布式。
关于SpringTask更详细的内容可以看傲娇鹿先生的文章—Spring Boot 中使用 Spring Task 实现定时任务