亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot集成MinIO實(shí)現(xiàn)大文件分片上傳的示例代碼

 更新時(shí)間:2025年05月21日 09:34:44   作者:Liberty715  
本文主要介紹了SpringBoot集成MinIO實(shí)現(xiàn)大文件分片上傳,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

需求背景:為什么需要分片上傳?

1. 傳統(tǒng)上傳方式的痛點(diǎn)

在文件上傳場(chǎng)景中,當(dāng)用戶嘗試上傳超過(guò) 100MB 的大文件時(shí),傳統(tǒng)單次上傳方式會(huì)面臨三大核心問(wèn)題:

(1)網(wǎng)絡(luò)穩(wěn)定性挑戰(zhàn)

  • 弱網(wǎng)環(huán)境下(如移動(dòng)網(wǎng)絡(luò)/跨國(guó)傳輸)易出現(xiàn)傳輸中斷
  • 網(wǎng)絡(luò)波動(dòng)可能導(dǎo)致整個(gè)文件重傳(用戶需從0%重新開(kāi)始)

(2)服務(wù)器資源瓶頸

  • 單次傳輸大文件占用大量?jī)?nèi)存(如上傳10GB文件需要預(yù)留10GB內(nèi)存)
  • 長(zhǎng)時(shí)間占用線程影響服務(wù)器吞吐量

(3)用戶體驗(yàn)缺陷

  • 無(wú)法顯示實(shí)時(shí)進(jìn)度條
  • 不支持?jǐn)帱c(diǎn)續(xù)傳
  • 失敗重試成本極高

2. 分片上傳的核心優(yōu)勢(shì)

技術(shù)價(jià)值

特性說(shuō)明
可靠性單個(gè)分片失敗不影響整體上傳,支持分片級(jí)重試
內(nèi)存控制分片按需加載(如5MB/片),內(nèi)存占用恒定
并行加速支持多分片并發(fā)上傳(需配合前端Worker實(shí)現(xiàn))

業(yè)務(wù)價(jià)值

  • 支持超大文件:可突破GB級(jí)文件上傳限制
  • 斷點(diǎn)續(xù)傳:刷新頁(yè)面/切換設(shè)備后繼續(xù)上傳
  • 精準(zhǔn)進(jìn)度:實(shí)時(shí)顯示每個(gè)分片的上傳狀態(tài)
  • 容災(zāi)能力:分片可跨服務(wù)器分布式存儲(chǔ)

3. 典型應(yīng)用場(chǎng)景

(1)企業(yè)級(jí)網(wǎng)盤(pán)系統(tǒng)

  • 用戶上傳設(shè)計(jì)圖紙(平均500MB-2GB)
  • 跨國(guó)團(tuán)隊(duì)協(xié)作時(shí)處理4K視頻素材(10GB+)

(2)醫(yī)療影像系統(tǒng)

  • 醫(yī)院PACS系統(tǒng)上傳CT掃描文件(單次檢查約3GB)
  • 支持醫(yī)生在弱網(wǎng)環(huán)境下暫停/恢復(fù)上傳

(3)在線教育平臺(tái)

  • 講師上傳高清課程視頻(1080P視頻約2GB/小時(shí))
  • 學(xué)員斷網(wǎng)后自動(dòng)恢復(fù)上傳至95%進(jìn)度

4. 為什么選擇MinIO?

MinIO作為高性能對(duì)象存儲(chǔ)方案,與分片上傳架構(gòu)完美契合:

(1)分布式架構(gòu)

  • 自動(dòng)將分片分布到不同存儲(chǔ)節(jié)點(diǎn)
  • 支持EC糾刪碼保障數(shù)據(jù)可靠性

(2)高性能合并

// MinIO服務(wù)端合并只需一次API調(diào)用
minioClient.composeObject(ComposeObjectArgs.builder()...);

相比傳統(tǒng)文件IO合并方式,速度提升5-10倍

(3)生命周期管理

  • 可配置自動(dòng)清理臨時(shí)分片
  • 合并后文件自動(dòng)歸檔至冷存儲(chǔ)

一、環(huán)境準(zhǔn)備與依賴配置

1. 開(kāi)發(fā)環(huán)境要求

  • JDK 17+
  • Maven 3.6+
  • MinIO Server(推薦版本:RELEASE.2023-10-25T06-33-25Z)

2. 項(xiàng)目依賴(pom.xml)

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>3.3.4</version>
    </dependency>

    <!-- MinIO Java SDK -->
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.5.7</version>
    </dependency>

    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.30</version>
        <optional>true</optional>
    </dependency>
</dependencies>

二、核心代碼實(shí)現(xiàn)解析

1. MinIO服務(wù)配置(FileUploadService)

(1) 客戶端初始化

private MinioClient createMinioClient() {
    return MinioClient.builder()
            .endpoint(endpoint)
            .credentials(accessKey, secretKey)
            .build();
}
  • 通過(guò)@Value注入配置參數(shù)
  • 支持自定義endpoint和認(rèn)證信息

(2) 分片上傳實(shí)現(xiàn)

public String uploadFilePart(String fileId, String fileName, 
                           MultipartFile filePart, Integer chunkIndex, 
                           Integer totalChunks) throws IOException {
    String objectName = fileId + "/" + fileName + '-' + chunkIndex;
    PutObjectArgs args = PutObjectArgs.builder()
            .bucket(bucketName)
            .object(objectName)
            .stream(filePart.getInputStream(), filePart.getSize(), -1)
            .build();
    minioClient.putObject(args);
    return objectName;
}
  • 分片命名規(guī)則:{fileId}/{fileName}-{chunkIndex}
  • 支持任意大小的文件分片

(3) 分片合并邏輯

public void mergeFileParts(FileMergeReqVO reqVO) throws IOException {
    String finalObjectName = "merged/" + reqVO.getFileId() + "/" + reqVO.getFileName();
    List<ComposeSource> sources = reqVO.getPartNames().stream()
            .map(name -> ComposeSource.builder()
                    .bucket(bucketName)
                    .object(name)
                    .build())
            .toList();
    
    minioClient.composeObject(ComposeObjectArgs.builder()
            .bucket(bucketName)
            .object(finalObjectName)
            .sources(sources)
            .build());
    
    // 清理臨時(shí)分片
    reqVO.getPartNames().forEach(partName -> {
        try {
            minioClient.removeObject(
                RemoveObjectArgs.builder()
                    .bucket(bucketName)
                    .object(partName)
                    .build());
        } catch (Exception e) {
            log.error("Delete chunk failed: {}", partName, e);
        }
    });
}
  • 使用MinIO的composeObject合并分片
  • 最終文件存儲(chǔ)在merged/{fileId}目錄
  • 自動(dòng)清理已合并的分片

2. 控制層設(shè)計(jì)(FileUploadController)

@PostMapping("/upload/part/{fileId}")
public CommonResult<String> uploadFilePart(
        @PathVariable String fileId,
        @RequestParam String fileName,
        @RequestParam MultipartFile filePart,
        @RequestParam int chunkIndex,
        @RequestParam int totalChunks) {
    // [邏輯處理...]
}

@PostMapping("/merge")
public CommonResult<String> mergeFileParts(@RequestBody FileMergeReqVO reqVO) {
    // [合并邏輯...]
}

3. 前端分片上傳實(shí)現(xiàn)

const chunkSize = 5 * 1024 * 1024; // 5MB分片

async function uploadFile() {
    const file = document.getElementById('fileInput').files[0];
    const fileId = generateUUID();
    
    // 分片上傳循環(huán)
    for (let i = 0; i < totalChunks; i++) {
        const chunk = file.slice(start, end);
        const formData = new FormData();
        formData.append('filePart', chunk);
        formData.append('chunkIndex', i + 1);
        
        await fetch('/upload/part/' + fileId, {
            method: 'POST',
            body: formData
        });
    }
    
    // 觸發(fā)合并
    await fetch('/merge', {
        method: 'POST',
        body: JSON.stringify({
            fileId: fileId,
            partNames: generatedPartNames
        })
    });
}

三、功能測(cè)試驗(yàn)證

測(cè)試用例1:上傳500MB視頻文件

選擇測(cè)試文件:sample.mp4(512MB)

觀察分片上傳過(guò)程:

  • 總生成103個(gè)分片(5MB/片)
  • 上傳進(jìn)度實(shí)時(shí)更新

合并完成后檢查MinIO:

sta-bucket
└── merged
    └── 6ba7b814...
        └── sample.mp4

下載驗(yàn)證文件完整性

在這里插入圖片描述

測(cè)試用例2:中斷恢復(fù)測(cè)試

  • 上傳過(guò)程中斷網(wǎng)絡(luò)連接
  • 重新上傳時(shí):
    • 已完成分片跳過(guò)上傳
    • 繼續(xù)上傳剩余分片
  • 最終合并成功

四、關(guān)鍵配置項(xiàng)說(shuō)明

配置項(xiàng)示例值說(shuō)明
minio.endpointhttp://localhost:9991MinIO服務(wù)器地址
minio.access-keyroot訪問(wèn)密鑰
minio.secret-keyxxxxx秘密密鑰
minio.bucket-nameminio-xxxx默認(rèn)存儲(chǔ)桶名稱
server.servlet.port8080Spring Boot服務(wù)端口

附錄:完整源代碼

1. 后端核心類(lèi)

FileUploadService.java

@Service
public class FileUploadService {

    @Value("${minio.endpoint:http://localhost:9991}")
    private String endpoint; // MinIO服務(wù)器地址

    @Value("${minio.access-key:root}")
    private String accessKey; // MinIO訪問(wèn)密鑰

    @Value("${minio.secret-key:xxxx}")
    private String secretKey; // MinIO秘密密鑰

    @Value("${minio.bucket-name:minio-xxxx}")
    private String bucketName; // 存儲(chǔ)桶名稱

    /**
     * 創(chuàng)建 MinIO 客戶端
     *
     * @return MinioClient 實(shí)例
     */
    private MinioClient createMinioClient() {
        return MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
    }

    /**
     * 如果存儲(chǔ)桶不存在,則創(chuàng)建存儲(chǔ)桶
     */
    public void createBucketIfNotExists() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        MinioClient minioClient = createMinioClient();
        try {
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }
        } catch (MinioException e) {
            throw new IOException("Error checking or creating bucket: " + e.getMessage(), e);
        }
    }

    /**
     * 上傳文件分片到MinIO
     *
     * @param fileId   文件標(biāo)識(shí)符
     * @param filePart 文件分片
     * @return 分片對(duì)象名稱
     */
    public String uploadFilePart(String fileId, String fileName, MultipartFile filePart, Integer chunkIndex, Integer totalChunks) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        MinioClient minioClient = createMinioClient();
        try {
            // 構(gòu)建分片對(duì)象名稱
            String objectName = fileId + "/" + fileName + '-' + chunkIndex;
            // 設(shè)置上傳參數(shù)
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .stream(filePart.getInputStream(), filePart.getSize(), -1)
                    .contentType(filePart.getContentType())
                    .build();
            // 上傳文件分片
            minioClient.putObject(putObjectArgs);
            return objectName;
        } catch (MinioException e) {
            throw new IOException("Error uploading file part: " + e.getMessage(), e);
        }
    }

    /**
     * 合并多個(gè)文件分片為一個(gè)完整文件
     */
    public void mergeFileParts(FileMergeReqVO reqVO) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        MinioClient minioClient = createMinioClient();
        try {
            // 構(gòu)建最終文件對(duì)象名稱
            String finalObjectName = "merged/" + reqVO.getFileId() + "/" + reqVO.getFileName();
            // 構(gòu)建ComposeSource數(shù)組
            List<ComposeSource> sources = reqVO.getPartNames().stream().map(name ->
                    ComposeSource.builder().bucket(bucketName).object(name).build()).toList();
            // 設(shè)置合并參數(shù)
            ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder()
                    .bucket(bucketName)
                    .object(finalObjectName)
                    .sources(sources)
                    .build();
            // 合并文件分片
            minioClient.composeObject(composeObjectArgs);

            // 刪除合并后的分片
            for (String partName : reqVO.getPartNames()) {
                minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(partName).build());
            }
        } catch (MinioException e) {
            throw new IOException("Error merging file parts: " + e.getMessage(), e);
        }
    }

    /**
     * 刪除指定文件
     *
     * @param fileName 文件名
     */
    public void deleteFile(String fileName) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        MinioClient minioClient = createMinioClient();
        try {
            // 刪除文件
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
        } catch (MinioException e) {
            throw new IOException("Error deleting file: " + e.getMessage(), e);
        }
    }
}

FileUploadController.java

@AllArgsConstructor
@RestController
@RequestMapping("/files")
public class FileUploadController {

    private final FileUploadService fileUploadService;

    /**
     * 創(chuàng)建存儲(chǔ)桶
     *
     * @return 響應(yīng)狀態(tài)
     */
    @PostMapping("/bucket")
    @PermitAll
    public CommonResult<String> createBucket() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        fileUploadService.createBucketIfNotExists();
        return CommonResult.success("創(chuàng)建成功");
    }

    /**
     * 上傳文件分片
     *
     * @param fileId      文件標(biāo)識(shí)符
     * @param filePart    文件分片
     * @param chunkIndex  當(dāng)前分片索引
     * @param totalChunks 總分片數(shù)
     * @return 響應(yīng)狀態(tài)
     */
    @PostMapping("/upload/part/{fileId}")
    @PermitAll
    public CommonResult<String> uploadFilePart(
            @PathVariable String fileId,
            @RequestParam String fileName,
            @RequestParam MultipartFile filePart,
            @RequestParam int chunkIndex,
            @RequestParam int totalChunks) {

        try {
            // 上傳文件分片
            String objectName = fileUploadService.uploadFilePart(fileId,fileName, filePart, chunkIndex, totalChunks);
            return CommonResult.success("Uploaded file part: " + objectName);
        } catch (IOException | NoSuchAlgorithmException | InvalidKeyException e) {
            return CommonResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Error uploading file part: " + e.getMessage());
        }
    }

    /**
     * 合并文件分片
     *
     * @param reqVO 參數(shù)
     * @return 響應(yīng)狀態(tài)
     */
    @PostMapping("/merge")
    @PermitAll
    public CommonResult<String> mergeFileParts(@RequestBody FileMergeReqVO reqVO) {
        try {
            fileUploadService.mergeFileParts(reqVO);
            return CommonResult.success("File parts merged successfully.");
        } catch (IOException | NoSuchAlgorithmException | InvalidKeyException e) {
            return CommonResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Error merging file parts: " + e.getMessage());
        }
    }

    /**
     * 刪除指定文件
     *
     * @param fileId 文件ID
     * @return 響應(yīng)狀態(tài)
     */
    @DeleteMapping("/delete/{fileId}")
    @PermitAll
    public CommonResult<String> deleteFile(@PathVariable String fileId) {
        try {
            fileUploadService.deleteFile(fileId);
            return CommonResult.success("File deleted successfully.");
        } catch (IOException | NoSuchAlgorithmException | InvalidKeyException e) {
            return CommonResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Error deleting file: " + e.getMessage());
        }
    }
}

FileMergeReqVO.java

@Data
public class FileMergeReqVO {

    /**
     * 文件標(biāo)識(shí)ID
     */
    private String fileId;

    /**
     * 文件名
     */
    private String fileName;

    /**
     * 合并文件列表
     */
    @NotEmpty(message = "合并文件列表不允許為空")
    private List<String> partNames;
}

2. 前端HTML頁(yè)面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File Upload</title>
    <style>
        #progressBar {
            width: 100%;
            background-color: #f3f3f3;
            border: 1px solid #ccc;
        }
        #progress {
            height: 30px;
            width: 0%;
            background-color: #4caf50;
            text-align: center;
            line-height: 30px;
            color: white;
        }
    </style>
</head>
<body>
    <input type="file" id="fileInput" />
    <button id="uploadButton">Upload</button>
    <div id="progressBar">
        <div id="progress">0%</div>
    </div>
    <script>
        const chunkSize = 5 * 1024 * 1024; // 每個(gè)分片大小為1MB

        // 生成 UUID 的函數(shù)
        function generateUUID() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        }
        
        document.getElementById('uploadButton').addEventListener('click', async () => {
            const file = document.getElementById('fileInput').files[0];
            if (!file) {
                alert("Please select a file to upload.");
                return;
            }

            // 生成唯一的 fileId
            const fileId = generateUUID();

            // 獲取文件名
            const fileName = file.name; // 可以直接使用文件名

            const totalChunks = Math.ceil(file.size / chunkSize);
            let uploadedChunks = 0;

            // 上傳每個(gè)分片
            for (let i = 0; i < totalChunks; i++) {
                const start = i * chunkSize;
                const end = Math.min(start + chunkSize, file.size);
                const chunk = file.slice(start, end);

                const formData = new FormData();
                formData.append('filePart', chunk);
                formData.append('fileName', fileName); // 傳遞 文件名
                formData.append('fileId', fileId); // 傳遞 fileId
                formData.append('chunkIndex', i + 1); // 從1開(kāi)始
                formData.append('totalChunks', totalChunks);

                // 發(fā)送分片上傳請(qǐng)求
                const response = await fetch('http://localhost:8080/files/upload/part/' + encodeURIComponent(fileId), {
                    method: 'POST',
                    headers: {
                        'tenant-id': '1',
                    },
                    body: formData,
                });

                if (response.ok) {
                    uploadedChunks++;
                    const progressPercentage = Math.round((uploadedChunks / totalChunks) * 100);
                    updateProgressBar(progressPercentage);
                } else {
                    console.error('Error uploading chunk:', await response.text());
                    alert('Error uploading chunk: ' + await response.text());
                    break; // 如果上傳失敗,退出循環(huán)
                }
            }

            // 合并分片
            const mergeResponse = await fetch('http://localhost:8080/files/merge', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'tenant-id': '1',
                },
                body: JSON.stringify({
                    fileId: fileId,
                    fileName: fileName,
                    partNames: Array.from({ length: totalChunks }, (_, i) => `${fileId}/${fileName}-${i + 1}`),
                }),
            });

            if (mergeResponse.ok) {
                const mergeResult = await mergeResponse.text();
                console.log(mergeResult);
            } else {
                console.error('Error merging chunks:', await mergeResponse.text());
                alert('Error merging chunks: ' + await mergeResponse.text());
            }
            // 最后更新進(jìn)度條為100%
            updateProgressBar(100);
        });

        function updateProgressBar(percent) {
            const progress = document.getElementById('progress');
            progress.style.width = percent + '%';
            progress.textContent = percent + '%';
        }
    </script>
</body>
</html>

注意事項(xiàng):

  • MinIO服務(wù)需提前啟動(dòng)并創(chuàng)建好存儲(chǔ)桶
  • 生產(chǎn)環(huán)境建議增加分片MD5校驗(yàn)
  • 前端需處理上傳失敗的重試機(jī)制
  • 建議配置Nginx反向代理提高性能

通過(guò)本方案可實(shí)現(xiàn)穩(wěn)定的大文件上傳功能,經(jīng)測(cè)試可支持10GB以上文件傳輸,實(shí)際應(yīng)用時(shí)可根據(jù)業(yè)務(wù)需求調(diào)整分片大小和并發(fā)策略。

到此這篇關(guān)于SpringBoot集成MinIO實(shí)現(xiàn)大文件分片上傳的文章就介紹到這了,更多相關(guān)SpringBoot MinIO大文件分片上傳內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java算法之冒泡排序?qū)嵗a

    Java算法之冒泡排序?qū)嵗a

    今天小編就為大家分享一篇關(guān)于Java算法之冒泡排序?qū)嵗a,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • Java集合中的Iterator迭代器接口詳解

    Java集合中的Iterator迭代器接口詳解

    這篇文章主要介紹了Java集合中的Iterator迭代器接口詳解,Iterator,被稱為迭代器接口,本身并不提供存儲(chǔ)對(duì)象的能力,主要用于遍歷Collection中的元素,需要的朋友可以參考下
    2023-11-11
  • Graceful Response 構(gòu)建 Spring Boot 響應(yīng)處理的方法

    Graceful Response 構(gòu)建 Spring Boot 響應(yīng)

    Graceful Response是一個(gè)Spring Boot技術(shù)棧下的優(yōu)雅響應(yīng)處理器,提供一站式統(tǒng)一返回值封裝、全局異常處理、自定義異常錯(cuò)誤碼等功能,本文介紹Graceful Response 構(gòu)建 Spring Boot 下優(yōu)雅的響應(yīng)處理,感興趣的朋友一起看看吧
    2024-01-01
  • ArrayList詳解和使用示例_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    ArrayList詳解和使用示例_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    ArrayList 是一個(gè)數(shù)組隊(duì)列,相當(dāng)于 動(dòng)態(tài)數(shù)組。與Java中的數(shù)組相比,它的容量能動(dòng)態(tài)增長(zhǎng)。接下來(lái)通過(guò)本文給大家介紹arraylist詳解和使用示例代碼,需要的的朋友一起學(xué)習(xí)吧
    2017-05-05
  • SpringBoot超詳細(xì)講解yaml配置文件

    SpringBoot超詳細(xì)講解yaml配置文件

    這篇文章主要介紹了SpringBoot中的yaml配置文件問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • JAVA中通過(guò)Redis實(shí)現(xiàn)延時(shí)任務(wù)demo實(shí)例

    JAVA中通過(guò)Redis實(shí)現(xiàn)延時(shí)任務(wù)demo實(shí)例

    Redis在2.0版本時(shí)引入了發(fā)布訂閱(pub/sub)功能,在發(fā)布訂閱中有一個(gè)channel(頻道),與消息隊(duì)列中的topic(主題)類(lèi)似,可以通過(guò)redis的發(fā)布訂閱者模式實(shí)現(xiàn)延時(shí)任務(wù)功能,實(shí)例中會(huì)議室預(yù)約系統(tǒng),用戶預(yù)約管理員審核后生效,如未審批,需要自動(dòng)變超期未處理,使用延時(shí)任務(wù)
    2024-08-08
  • IDEA 中創(chuàng)建Spring Data Jpa 項(xiàng)目的示例代碼

    IDEA 中創(chuàng)建Spring Data Jpa 項(xiàng)目的示例代碼

    這篇文章主要介紹了IDEA 中創(chuàng)建Spring Data Jpa 項(xiàng)目的示例代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 解決springboot啟動(dòng)報(bào)錯(cuò)bean找不到的問(wèn)題

    解決springboot啟動(dòng)報(bào)錯(cuò)bean找不到的問(wèn)題

    這篇文章主要介紹了解決springboot啟動(dòng)報(bào)錯(cuò)bean找不到原因,本文給大家分享完美解決方案,通過(guò)圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-03-03
  • Java的DelayQueue延遲隊(duì)列簡(jiǎn)單使用代碼實(shí)例

    Java的DelayQueue延遲隊(duì)列簡(jiǎn)單使用代碼實(shí)例

    這篇文章主要介紹了Java的DelayQueue延遲隊(duì)列簡(jiǎn)單使用代碼實(shí)例,DelayQueue是一個(gè)延遲隊(duì)列,插入隊(duì)列的數(shù)據(jù)只有達(dá)到設(shè)置的延遲時(shí)間時(shí)才能被取出,否則線程會(huì)被阻塞,插入隊(duì)列的對(duì)象必須實(shí)現(xiàn)Delayed接口,需要的朋友可以參考下
    2023-12-12
  • java中List集合及其遍歷詳解

    java中List集合及其遍歷詳解

    這篇文章主要介紹了java中List集合及其遍歷詳解的相關(guān)資料,需要的朋友可以參考下
    2015-07-07

最新評(píng)論