解决思路:
- 图片上传云端后将图片上传后的路径添加到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 valueredisTemplate.opsForSet().add("imgOnLocal", setmeal.getImg());}@Transactionalpublic void updateSetmeal(Setmeal setmeal) {//更新检查组setmealMapper.update(setmeal);//添加新增图片地址到Redis库存储key valueredisTemplate.opsForSet().add("imgOnLocal", setmeal.getImg()); }@Override@Transactionalpublic void delete(Long id) {//查找数据库获取图像信息Setmeal setmeal = setmealMapper.getById(id);//删除Redis数据库中存储的图片信息key valueredisTemplate.opsForSet().remove("imgOnLocal",setmeal.getImg());//删除套餐setmealMapper.deleteById(id);}
- 通过SpringTask定时校验云端是否存在垃圾数据,存在就调用阿里云工具类删除,同时删除云端垃圾文件在Redis数据库中存储信息。
@Slf4j@Componentpublic class RedisTask {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate 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文件添加依赖:
org.springframework.bootspring-boot-starter-data-redis
并在application.yml文件中配置自定义的信息
redis:host: localhost #服务器port: 6379#端口号password: root#看你个人有没有设置密码,没有不用配置database: 10#数据库
然后编写配置类,创建RedisTemplate对象(这一步操作中也会修改一下Redis key的序列化器,最后就可以通过RedisTemplate对象操作Redis数据库)
@Configuration@Slf4jpublic class RedisConfiguration {@Beanpublic 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项目的启动类上添加注解@EnableScheduling
,作用是开启相关的定时任务功能。
@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");}
定时任务方法上需要添加@Scheduled(cron = "0 * * * * ?")
注解并指定执行策略,执行策略有:corn、fixedDelay和flixedRate三种种执行策略.
其中cron表达式(上面用的就是),对应分别是 秒 分 时 日 月 周 (还有年,但这里没用)。cron表达式可以通过在线工具直接生成。
fixedDelay间隔时间是上次任务结束时才开始计时,fixedRate规定了两次定时任务执行的时间间隔,理论上当上一个定时任务开始执行时,下一个定时任务开始时间就已经确定了。(这两种我目前没使用过)
还有一个属性叫做:initialDelay
用来初始化延迟时间,也就是第一次延迟执行的时间。只能配合 fixedDelay 或 fixedRate 使用。如 @Scheduled(initialDelay=5000,fixedDelay = 1000)
注意事项:SpringTask默认单线程执行,多线程时会影响到定时策略。SpringTask默认不支持分布式。
关于SpringTask更详细的内容可以看傲娇鹿先生的文章—Spring Boot 中使用 Spring Task 实现定时任务