解决思路:
- 图片上传云端后将图片上传后的路径添加到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项目的启动类上添加注解@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 实现定时任务