如何完成定时删除图片任务

完成这项任务前要配合redis数据库进行

配置如下:

yml文件:

#=========================Redis=================
redis:
  host: 8.130.125.162
  port: 6333
  password: 123456
  database: 1
  timeout: 18000
  lettuce:
    pool:
      enabled: true
      max-idle: 10
      min-idle: 3
      max-wait: -1

1.配置QuartzConfig配置类

package com.igeek.logistics.config;


import com.igeek.logistics.job.CleanImgJob;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * TODO
 *
 * @author chemin
 * @since 2024/7/16
 */
@Configuration
public class QuartzConfig {

    //定义清除图片的工作明细
    @Bean
    public JobDetail cleanImgJobDetail(){
        return JobBuilder.newJob(CleanImgJob.class).storeDurably().build();
    }

    //定义清除图片的触发器
    @Bean
    public Trigger cleanImgTrigger(){
        //构建定时任务,并指定cron表达式
        //   0 0 2 * * ?     每天凌晨两点
        //   0/20 * * * * ?  每隔20s执行
        //0/5 * * * * ?   每隔5s执行一次
        ScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ? ");
        return TriggerBuilder.newTrigger().forJob(cleanImgJobDetail()).withSchedule(scheduleBuilder).build();
    }

}
在里面进行规定定时删除的时间

2.配置RedisConfig配置类

package com.igeek.logistics.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;
import java.time.Duration;

/**
 * @Author chenmin
 * @Description TODO
 */
//配置类
@Configuration
//开启缓存
@EnableCaching
public class RedisConfig {

    /**
     * 自定义key规则
     * @return
     */
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                //key 会追加上类的名字
                sb.append(target.getClass().getName());
                //key 会追加上方法的名字
                sb.append(method.getName());
                for (Object obj : params) {
                    //key 会追加上形参的名字
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    /**
     * 其实SpringBoot自动帮我们在容器中生成了一个RedisTemplate和一个StringRedisTemplate。
     * 但是,这个RedisTemplate的泛型是<Object,Object>,写代码不方便,需要写好多类型转换的代码;我们需要一个泛型为<String,Object>形式的RedisTemplate
     * 同时,设置key-value的序列化方式
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);

        // 设置序列化参数
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);


        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        //解决jackson2无法序列化LocalDateTime的问题,这里扩展一个LocalDateTime类型,它是日期类型对象 jdk1.8出的(并且这个类是不可变的和线程安全的,可以研究一下它的API),当然还需要对这个对象进行json格式的转换,如下:
        om.disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS);
        om.registerModule(new JavaTimeModule());
        jackson2JsonRedisSerializer.setObjectMapper(om);


        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }

    /**
     * 设置CacheManager缓存规则
     * @param factory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        //解决jackson2无法序列化LocalDateTime的问题,这里扩展一个LocalDateTime类型,它是日期类型对象 jdk1.8出的(并且这个类是不可变的和线程安全的,可以研究一下它的API),当然还需要对这个对象进行json格式的转换,如下:
        om.disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS);
        om.registerModule(new JavaTimeModule());
        jackson2JsonRedisSerializer.setObjectMapper(om);

        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(4*60*60))  //指定缓存的过期时间
                //.prefixCacheNameWith("")          //指定前缀
                //.disableCachingNullValues()       //不缓存空值
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));


        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}
这个配置类的目的在于配置
@Autowired
private RedisTemplate<String,Object> redisTemplate;

自带的是一个RedisTemplate<Objet,Object> redisTemplate;

改成我们自己需求的

3.写出RedisImgConstant常量

package com.igeek.logistics.constant;

public class RedisImgConstant {

    //记录上传图片
    public static final String UPLOAD_IMG = "upload_img";

    //记录实际在数据库中的图片
    public static final String UPLOAD_DB_IMG = "upload_db_img";

}
目的在于定义记录上传图片以及记录实际在数据库中的图片的键的常量

4.写出CleanImgJob

package com.igeek.logistics.job;


import com.igeek.logistics.constant.RedisImgConstant;
import com.igeek.logistics.utils.QiniuUtils;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.util.CollectionUtils;

import java.util.Set;

/**
 * TODO
 *
 * @author chemin
 * @since 2024/7/16
 */
@Slf4j
public class CleanImgJob extends QuartzJobBean {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        log.info("--------------> 执行删除图片的定时任务....");

        //差集  查询出不在数据库中使用的图片信息
        Set<Object> set = redisTemplate.opsForSet().difference(RedisImgConstant.UPLOAD_IMG, RedisImgConstant.UPLOAD_DB_IMG);
        if(!CollectionUtils.isEmpty(set)){
            for (Object o : set) {
                String img = o.toString();
                //七牛云删除图片
                boolean flag = QiniuUtils.deleteFromQiniu(img);
                if(flag){
                    //Redis中删除图片
                    redisTemplate.opsForSet().remove(RedisImgConstant.UPLOAD_IMG , img);
                    log.info("{} 删除成功" , img);
                }
            }
        }
    }
}

目的在于完成具体的清除图片任务

5.最后一步

分别在

String picName = QiniuUtils.uploadForQiniu(inputStream,newName);
if (StringUtils.hasLength(picName)){
    //记录实际在数据库中的图片数据信息  Set类型:无序不重复 差集
    redisTemplate.opsForSet().add(RedisImgConstant.UPLOAD_IMG ,picName);
    return new Result(true,"头像上传成功",picName);
}

以及

Boolean flag = warehouseManagementService.post(warehouseManagement);
if (flag){
    //记录实际在数据库中的图片数据信息  Set类型:无序不重复 差集
    redisTemplate.opsForSet().add(RedisImgConstant.UPLOAD_DB_IMG , warehouseManagement.getAvatar());
    return new Result(true, MessageConstant.ADD_CHECKITEM_SUCCESS);
}

完成即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值