最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于SpringBoot + 七牛云 + Quartz實(shí)現(xiàn)圖片存儲(chǔ)與定時(shí)清理

 更新時(shí)間:2026年04月12日 14:13:43   作者:小旭9527  
這篇文章主要介紹了在實(shí)際項(xiàng)目中使用七牛云對(duì)象存儲(chǔ)進(jìn)行圖片存儲(chǔ)的方法,以及如何實(shí)現(xiàn)套餐管理(包括圖片上傳和多對(duì)多關(guān)聯(lián)檢查組)的前端和后端功能,此外,還詳細(xì)講解了如何使用Quartz定時(shí)任務(wù)組件自動(dòng)清理垃圾圖片,以節(jié)省存儲(chǔ)資源,需要的朋友可以參考下

一、圖片存儲(chǔ)方案

1.1 常見圖片存儲(chǔ)方案

實(shí)際項(xiàng)目中會(huì)拆分不同功能服務(wù)器,提升系統(tǒng)運(yùn)行效率,圖片存儲(chǔ)常用三種方案:

  1. Nginx 搭建圖片服務(wù)器
  2. 分布式文件存儲(chǔ)系統(tǒng)(FastDFS、HDFS)
  3. 云存儲(chǔ)(阿里云 OSS、七牛云)

本文選用七牛云對(duì)象存儲(chǔ),接入簡(jiǎn)單、CDN 加速快、適合中小項(xiàng)目快速落地。

1.2 七牛云使用流程

1.2.1 注冊(cè)與實(shí)名認(rèn)證

  1. 訪問七牛云官網(wǎng):https://www.qiniu.com/
  2. 注冊(cè)賬號(hào)并完成個(gè)人實(shí)名認(rèn)證(創(chuàng)建存儲(chǔ)空間必須認(rèn)證)

1.2.2 新建存儲(chǔ)空間

控制臺(tái)進(jìn)入對(duì)象存儲(chǔ) KODO

  1. 創(chuàng)建存儲(chǔ)空間(Bucket):
    • 名稱:3~63 位小寫字母 / 數(shù)字 / 短橫線
    • 存儲(chǔ)區(qū)域:華東 / 華北 / 華南等
    • 訪問控制:公開 / 私有(圖片通常設(shè)為公開)

  1. 創(chuàng)建成功后可在文件管理查看上傳資源。

1.2.3 獲取 AK/SK 密鑰

  1. 進(jìn)入個(gè)人中心 → 密鑰管理
  2. 復(fù)制 AccessKeySecretKey(Java SDK 鑒權(quán)使用)

1.3 Java SDK 接入七牛云

1.3.1 引入 Maven 依賴

<!-- 七牛云SDK -->
<dependency>
    <groupId>com.qiniu</groupId>
    <artifactId>qiniu-java-sdk</artifactId>
    <version>7.7.0</version>
</dependency>

1.3.2 封裝七牛云工具類

將上傳、刪除封裝為工具類,放入公共模塊(ICan-common):

public class QiniuUtils {
    public static String accessKey = "你的AK";
    public static String secretKey = "你的SK";
    public static String bucket = "你的存儲(chǔ)空間名";
    // 文件路徑上傳
    public static void upload2Qiniu(String filePath,String fileName){
        Configuration cfg = new Configuration(Zone.zone2()); //你自己存儲(chǔ)空間的存儲(chǔ)區(qū)域
        UploadManager uploadManager = new UploadManager(cfg);
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(filePath, fileName, upToken);
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
        } catch (QiniuException ex) {
            ex.printStackTrace();
        }
    }
    // 字節(jié)數(shù)組上傳
    public static void upload2Qiniu(byte[] bytes, String fileName){
        Configuration cfg = new Configuration(Zone.zone2());
        UploadManager uploadManager = new UploadManager(cfg);
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(bytes, fileName, upToken);
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
        } catch (QiniuException ex) {
            ex.printStackTrace();
        }
    }
    // 刪除文件
    public static void deleteFileFromQiniu(String fileName){
        Configuration cfg = new Configuration(Zone.zone2());
        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            bucketManager.delete(bucket, fileName);
        } catch (QiniuException ex) {
            System.err.println(ex.code());
        }
    }
}
?

二、新增套餐功能(圖片上傳 + 多對(duì)多關(guān)聯(lián))

2.1 需求說明

套餐是檢查組的集合,套餐與檢查組為多對(duì)多關(guān)系,需中間表t_setmeal_checkgroup關(guān)聯(lián)。新增套餐需錄入:

  • 基本信息(編碼、名稱、價(jià)格、圖片等)
  • 關(guān)聯(lián)檢查組

2.2 前端實(shí)現(xiàn)(Vue+ElementUI)

2.2.1 彈出新增窗口

點(diǎn)擊新建按鈕,清空表單并展示彈窗,同時(shí)加載所有檢查組:

handleCreate(){
  this.resetForm();
  this.dialogFormVisible = true;
  // 查詢所有檢查組
  axios.get("/checkgroup/findAll.do").then((res)=>{
    if(res.data.flag){
      this.tableData = res.data.data;
    }else{
      this.$message.error(res.data.message);
    }
  });
}

2.2.2 圖片上傳與預(yù)覽

使用el-upload組件,限制 JPG 格式、大小≤2MB:

<el-upload
  class="avatar-uploader"
  action="/setmeal/upload.do"
  :auto-upload="autoUpload"
  name="imgFile"
  :show-file-list="false"
  :on-success="handleAvatarSuccess"
  :before-upload="beforeAvatarUpload">
  <img v-if="imageUrl" :src="imageUrl" class="avatar">
  <i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>

上傳前校驗(yàn):

beforeAvatarUpload(file){
  const isJPG = file.type === 'image/jpeg';
  const isLt2M = file.size / 1024 / 1024 < 2;
  if(!isJPG) this.$message.error("只能上傳JPG格式!");
  if(!isLt2M) this.$message.error("圖片大小不能超過2MB!");
  return isJPG && isLt2M;
}

2.3 后端實(shí)現(xiàn)

2.3.1 圖片上傳接口

@Controller
@RequestMapping("/setmeal")
public class SetmealController {
    @Autowired
    private JedisPool jedisPool;

    // 圖片上傳
    @RequestMapping("/upload")
    @ResponseBody
    public Result upload(@RequestParam("imgFile") MultipartFile imgFile){
        try {
            String originalFilename = imgFile.getOriginalFilename();
            String extention = originalFilename.substring(originalFilename.lastIndexOf("."));
            String fileName = UUID.randomUUID().toString() + extention;
            // 上傳七牛云
            QiniuUtils.upload2Qiniu(imgFile.getBytes(),fileName);
            // 存入Redis(所有上傳圖片)
            jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_RESOURCES,fileName);
            return new Result(true, MessageConstant.PIC_UPLOAD_SUCCESS,fileName);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.PIC_UPLOAD_FAIL);
        }
    }
}

2.3.2 新增套餐(事務(wù) + 多對(duì)多關(guān)聯(lián))

@Service
@Transactional
public class SetmealServiceImpl implements SetmealService {
    @Autowired
    private SetmealDao setmealDao;

    @Override
    public void add(Setmeal setmeal, Integer[] checkgroupIds) {
        // 新增套餐基本信息
        setmealDao.add(setmeal);
        Integer setmealId = setmeal.getId();
        // 設(shè)置套餐與檢查組關(guān)聯(lián)
        this.setSetmealAndCheckgroup(setmealId,checkgroupIds);
    }

    // 維護(hù)多對(duì)多關(guān)系
    private void setSetmealAndCheckgroup(Integer setmealId, Integer[] checkgroupIds) {
        if(checkgroupIds != null && checkgroupIds.length > 0){
            for (Integer checkgroupId : checkgroupIds) {
                Map<String,Integer> map = new HashMap<>();
                map.put("setmealId",setmealId);
                map.put("checkgroupId",checkgroupId);
                setmealDao.setSetmealAndCheckGroup(map);
            }
        }
    }
}

2.3.3 保存套餐后同步 Redis

@RequestMapping("/add")
@ResponseBody
public Result add(@RequestBody Setmeal setmeal, Integer[] checkgroupIds){
    try {
        setmealService.add(setmeal,checkgroupIds);
        // 存入Redis(已保存到數(shù)據(jù)庫的圖片)
        jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_DB_RESOURCES,setmeal.getImg());
        return new Result(true, MessageConstant.ADD_SETMEAL_SUCCESS);
    }catch (Exception e){
        e.printStackTrace();
        return new Result(false, MessageConstant.ADD_SETMEAL_FAIL);
    }
}

三、定時(shí)任務(wù)組件 Quartz(重點(diǎn))

3.1 Quartz 核心概念

  1. Job:要執(zhí)行的任務(wù)(清理圖片)
  2. Trigger:觸發(fā)器(定義執(zhí)行時(shí)間)
  3. Scheduler:調(diào)度器(綁定任務(wù)與觸發(fā)器)

3.2 Cron 表達(dá)式

格式:秒 分 時(shí) 日 月 周 年(年可省略)常用示例:

  • 0/1 * * * * ?:每秒執(zhí)行
  • 0 0 2 * * ?:每天凌晨 2 點(diǎn)執(zhí)行
  • 0 0 0/1 * * ?:每小時(shí)執(zhí)行

示例:

前面介紹了cron表達(dá)式,但是自己編寫表達(dá)式還是有一些困難的,我們可以借助一些 cron表達(dá)式在線生成器來根據(jù)我們的需求生成表達(dá)式即可。

http://cron.qqe2.com/

3.3 SpringBoot 整合 Quartz

3.3.1 引入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

3.3.2 配置類

@Configuration
public class QuartzConfig {
    @Bean    //job:干什么事
    public MethodInvokingJobDetailFactoryBean jobDetail(ClearImgJob clearImgJob){
        MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
        bean.setTargetObject(clearImgJob);
        bean.setTargetMethod("clearImg");
        return bean;
    }

    @Bean    //trigger:什么時(shí)候
    public CronTriggerFactoryBean trigger(MethodInvokingJobDetailFactoryBean jobDetail){
        CronTriggerFactoryBean bean = new CronTriggerFactoryBean();
        bean.setCronExpression("0 0 2 * * ?"); // 每天凌晨2點(diǎn)
        bean.setJobDetail(jobDetail.getObject());
        return bean;
    }

    @Bean    //scheduler:什么時(shí)候干什么事
    public SchedulerFactoryBean scheduler(CronTriggerFactoryBean trigger){
        SchedulerFactoryBean bean = new SchedulerFactoryBean();
        bean.setTriggers(trigger.getObject());
        return bean;
    }
}

?

四、定時(shí)清理垃圾圖片(核心)

4.1 垃圾圖片產(chǎn)生原因

用戶上傳圖片后未提交套餐,圖片存于七牛云但無數(shù)據(jù)庫記錄,成為垃圾文件。

4.2 清理思路

  1. Redis 集合 A:setmealPicResources(所有上傳圖片)
  2. Redis 集合 B:setmealPicDbResources(已保存數(shù)據(jù)庫圖片)
  3. 求差集:A - B = 垃圾圖片
  4. 定時(shí)刪除七牛云 + Redis 中的垃圾文件

4.3 清理任務(wù)實(shí)現(xiàn)

@Component
public class ClearImgJob {
    @Autowired
    private JedisPool jedisPool;

    public void clearImg(){
        // 計(jì)算差集
        Set<String> garbageImg = jedisPool.getResource().sdiff(
                RedisConstant.SETMEAL_PIC_RESOURCES,
                RedisConstant.SETMEAL_PIC_DB_RESOURCES);

        if(garbageImg != null){
            for (String imgName : garbageImg) {
                // 刪除七牛云文件
                QiniuUtils.deleteFileFromQiniu(imgName);
                // 刪除Redis記錄
                jedisPool.getResource().srem(RedisConstant.SETMEAL_PIC_RESOURCES,imgName);
                System.out.println("清理垃圾圖片:" + imgName);
            }
        }
    }
}

?

五、總結(jié)

  1. 圖片存儲(chǔ):選用七牛云對(duì)象存儲(chǔ),接入簡(jiǎn)單、CDN 加速、支持 Java SDK。
  2. 套餐管理:多對(duì)多關(guān)聯(lián)檢查組,支持圖片上傳預(yù)覽、分頁查詢。
  3. 垃圾清理:基于 Redis 集合差集定位垃圾圖片,Quartz 定時(shí)自動(dòng)清理,節(jié)省存儲(chǔ)資源。

本文完整實(shí)現(xiàn)預(yù)約系統(tǒng)套餐管理的圖片存儲(chǔ)與定時(shí)清理,可直接復(fù)用至同類項(xiàng)目。

以上就是基于SpringBoot + 七牛云 + Quartz實(shí)現(xiàn)圖片存儲(chǔ)與定時(shí)清理的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot七牛云圖片存儲(chǔ)與定時(shí)清理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解設(shè)計(jì)模式中的proxy代理模式及在Java程序中的實(shí)現(xiàn)

    詳解設(shè)計(jì)模式中的proxy代理模式及在Java程序中的實(shí)現(xiàn)

    代理模式主要分為靜態(tài)代理和動(dòng)態(tài)代理,使客戶端方面的使用者通過設(shè)置的代理來操作對(duì)象,下面來詳解設(shè)計(jì)模式中的proxy代理模式及在Java程序中的實(shí)現(xiàn)
    2016-05-05
  • Java中字符串轉(zhuǎn)時(shí)間與時(shí)間轉(zhuǎn)字符串的操作詳解

    Java中字符串轉(zhuǎn)時(shí)間與時(shí)間轉(zhuǎn)字符串的操作詳解

    Java 的 java.time 包提供了強(qiáng)大的日期和時(shí)間處理功能,通過 DateTimeFormatter 可以輕松地在日期時(shí)間對(duì)象和字符串之間進(jìn)行轉(zhuǎn)換,下面小編給大家詳細(xì)介紹一下Java中字符串轉(zhuǎn)時(shí)間與時(shí)間轉(zhuǎn)字符串的操作,需要的朋友可以參考下
    2025-04-04
  • jmeter中beanshell的用法小結(jié)

    jmeter中beanshell的用法小結(jié)

    本文主要介紹了jmeter中beanshell的用法小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • IntelliJ IDEA新版本中Maven子模塊不顯示的解決方案

    IntelliJ IDEA新版本中Maven子模塊不顯示的解決方案

    在使用IntelliJ IDEA 2024版本開發(fā)Maven多模塊項(xiàng)目時(shí),我發(fā)現(xiàn)一個(gè)令人困惑的現(xiàn)象,父模塊的子模塊未在右側(cè) Maven 工具窗口中顯示,僅顯示父模塊名稱,而此前2021版本中,父模塊和子模塊均能正常顯示,所以本文給大家介紹了IntelliJ IDEA新版本中Maven子模塊不顯示的解決方案
    2025-05-05
  • Java利用隨機(jī)分錢模擬財(cái)富變化

    Java利用隨機(jī)分錢模擬財(cái)富變化

    這篇文章主要為大家詳細(xì)介紹了Java如何利用隨機(jī)分錢思想模擬財(cái)富的變化,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-12-12
  • Spring MVC 更靈活的控制 json 返回問題(自定義過濾字段)

    Spring MVC 更靈活的控制 json 返回問題(自定義過濾字段)

    本篇文章主要介紹了Spring MVC 更靈活的控制 json 返回問題(自定義過濾字段),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • Mapper報(bào)錯(cuò)@MapKey is required問題及解決方式

    Mapper報(bào)錯(cuò)@MapKey is required問題及解決方式

    這段描述主要討論了在使用MyBatis或類似框架時(shí)遇到@MapKeyisrequired錯(cuò)誤的常見原因及解決方法,包括MapKey注解的正確使用以及相關(guān)配置檢查,特別強(qiáng)調(diào)了正確配置isMapMapKey和ResultMap注解對(duì)于避免數(shù)據(jù)不一致和運(yùn)行時(shí)異常的重要性
    2026-06-06
  • 深入了解MyBatis參數(shù)

    深入了解MyBatis參數(shù)

    今天小編就為大家分享一篇關(guān)于深入了解MyBatis參數(shù),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • Java Applet查找素?cái)?shù)小程序代碼實(shí)例

    Java Applet查找素?cái)?shù)小程序代碼實(shí)例

    這篇文章主要介紹了Java Applet查找素?cái)?shù)小程序代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Springboot攔截filter中異常的處理

    Springboot攔截filter中異常的處理

    SpringBoot提供了全局異常處理機(jī)制可以攔截所有異常,包括Filter中的異常,本文主要介紹了Springboot攔截filter中異常的處理,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11

最新評(píng)論

中牟县| 博爱县| 郧西县| 台中县| 无棣县| 清水河县| 和龙市| 蒙阴县| 香格里拉县| 手机| 米林县| 基隆市| 扎鲁特旗| 永嘉县| 吴旗县| 剑阁县| 杨浦区| 日土县| 香港| 贺州市| 闽侯县| 突泉县| 九江县| 广元市| 宜昌市| 丹阳市| 临猗县| 荥经县| 咸丰县| 临漳县| 白河县| 石嘴山市| 柘城县| 池州市| 和顺县| 华蓥市| 临清市| 项城市| 彭阳县| 绥江县| 宜兰县|