基于SpringBoot和MySQL實(shí)現(xiàn)圖片CRUD的三種解決方案
引言
在基于 Spring Boot 和 MySQL 開(kāi)發(fā)的后端程序中,處理圖片的增刪改查(CRUD)通常涉及到兩個(gè)核心部分:存儲(chǔ)圖片路徑信息到數(shù)據(jù)庫(kù)和實(shí)際文件操作(上傳、刪除等)。以下是幾種常見(jiàn)的解決方案,分別詳細(xì)說(shuō)明其使用方法,并對(duì)比優(yōu)缺點(diǎn)
解決方案一:將圖片保存為 BLOB 類(lèi)型直接存入數(shù)據(jù)庫(kù)
使用方法:
建表語(yǔ)句示例:
CREATE TABLE book_details (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
image BLOB -- 存儲(chǔ)圖片二進(jìn)制數(shù)據(jù)
);
Spring Boot 實(shí)體類(lèi)定義:
@Entity
public class BookDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@Lob
private byte[] image; // 存儲(chǔ)圖片的字節(jié)數(shù)組
// Getters and Setters
}
Controller 示例代碼:
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookRepository bookRepository;
@PostMapping("/upload")
public ResponseEntity<String> uploadBookImage(@RequestParam("title") String title,
@RequestParam("file") MultipartFile file) throws IOException {
BookDetail book = new BookDetail();
book.setTitle(title);
book.setImage(file.getBytes());
bookRepository.save(book);
return ResponseEntity.ok("圖片已上傳");
}
@GetMapping("/image/{id}")
public ResponseEntity<byte[]> getBookImage(@PathVariable Long id) {
BookDetail book = bookRepository.findById(id).orElseThrow();
return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(book.getImage());
}
}
優(yōu)點(diǎn):
- 數(shù)據(jù)集中管理,方便備份與遷移。
- 圖片與業(yè)務(wù)數(shù)據(jù)強(qiáng)關(guān)聯(lián),適合小規(guī)模應(yīng)用。
缺點(diǎn):
- 大量圖片存儲(chǔ)會(huì)顯著增加數(shù)據(jù)庫(kù)體積,影響性能。
- 不利于擴(kuò)展,不適合高并發(fā)場(chǎng)景。
解決方案二:將圖片存儲(chǔ)在服務(wù)器文件系統(tǒng),僅保存路徑到數(shù)據(jù)庫(kù)
使用方法:
建表語(yǔ)句示例:
CREATE TABLE book_details (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
image_path VARCHAR(255) -- 存儲(chǔ)圖片路徑
);
Spring Boot 實(shí)體類(lèi)定義:
@Entity
public class BookDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String imagePath; // 存儲(chǔ)圖片的路徑
// Getters and Setters
}
Controller 示例代碼:
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookRepository bookRepository;
// 文件存儲(chǔ)目錄
private static final String FILE_DIR = "D:/images/";
@PostMapping("/upload")
public ResponseEntity<String> uploadBookImage(@RequestParam("title") String title,
@RequestParam("file") MultipartFile file) throws IOException {
String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
Path filePath = Paths.get(FILE_DIR, fileName);
Files.write(filePath, file.getBytes());
BookDetail book = new BookDetail();
book.setTitle(title);
book.setImagePath(filePath.toString());
bookRepository.save(book);
return ResponseEntity.ok("圖片已上傳");
}
@GetMapping("/image/{id}")
public ResponseEntity<Resource> getBookImage(@PathVariable Long id) throws IOException {
BookDetail book = bookRepository.findById(id).orElseThrow();
Path path = Paths.get(book.getImagePath());
Resource resource = new UrlResource(path.toUri());
if (resource.exists() || resource.isReadable()) {
return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(resource);
} else {
throw new RuntimeException("無(wú)法讀取圖片");
}
}
@DeleteMapping("/delete/{id}")
public ResponseEntity<String> deleteBookImage(@PathVariable Long id) throws IOException {
BookDetail book = bookRepository.findById(id).orElseThrow();
Path path = Paths.get(book.getImagePath());
if (Files.exists(path)) {
Files.delete(path);
}
bookRepository.delete(book);
return ResponseEntity.ok("圖片已刪除");
}
@PutMapping("/update/{id}")
public ResponseEntity<String> updateBookImage(@PathVariable Long id,
@RequestParam("title") String title,
@RequestParam("file") MultipartFile file) throws IOException {
BookDetail book = bookRepository.findById(id).orElseThrow();
Path oldPath = Paths.get(book.getImagePath());
if (Files.exists(oldPath)) {
Files.delete(oldPath);
}
String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
Path newPath = Paths.get(FILE_DIR, fileName);
Files.write(newPath, file.getBytes());
book.setTitle(title);
book.setImagePath(newPath.toString());
bookRepository.save(book);
return ResponseEntity.ok("圖片已更新");
}
}
優(yōu)點(diǎn):
- 減輕數(shù)據(jù)庫(kù)壓力,提升性能。
- 易于擴(kuò)展,支持大量文件存儲(chǔ)。
缺點(diǎn):
- 需要額外管理文件系統(tǒng)或云存儲(chǔ)。
- 文件路徑變更時(shí)需要同步更新數(shù)據(jù)庫(kù)記錄。
解決方案三:使用云存儲(chǔ)服務(wù)(如阿里云 OSS、AWS S3)
使用方法:
建表語(yǔ)句示例:
CREATE TABLE book_details (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
image_url VARCHAR(255) -- 存儲(chǔ)云上的圖片鏈接
);
Spring Boot 實(shí)體類(lèi)定義:
@Entity
public class BookDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String imageUrl; // 存儲(chǔ)云上的圖片鏈接
// Getters and Setters
}
Controller 示例代碼(以阿里云 OSS 為例):
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookRepository bookRepository;
// 初始化 OSS 客戶(hù)端
private OSS ossClient = new OSSClientBuilder().build("endpoint", "accessKeyId", "accessKeySecret");
@PostMapping("/upload")
public ResponseEntity<String> uploadBookImage(@RequestParam("title") String title,
@RequestParam("file") MultipartFile file) throws IOException {
String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
ossClient.putObject("bucketName", "images/" + fileName, new ByteArrayInputStream(file.getBytes()));
BookDetail book = new BookDetail();
book.setTitle(title);
book.setImageUrl("https://bucketName.oss-cn-region.aliyuncs.com/images/" + fileName);
bookRepository.save(book);
return ResponseEntity.ok("圖片已上傳");
}
@DeleteMapping("/delete/{id}")
public ResponseEntity<String> deleteBookImage(@PathVariable Long id) {
BookDetail book = bookRepository.findById(id).orElseThrow();
String url = book.getImageUrl();
String objectName = url.replace("https://bucketName.oss-cn-region.aliyuncs.com/", "");
ossClient.deleteObject("bucketName", objectName);
bookRepository.delete(book);
return ResponseEntity.ok("圖片已刪除");
}
@PutMapping("/update/{id}")
public ResponseEntity<String> updateBookImage(@PathVariable Long id,
@RequestParam("title") String title,
@RequestParam("file") MultipartFile file) throws IOException {
BookDetail book = bookRepository.findById(id).orElseThrow();
String oldUrl = book.getImageUrl();
String oldObjectName = oldUrl.replace("https://bucketName.oss-cn-region.aliyuncs.com/", "");
// 刪除舊圖片
ossClient.deleteObject("bucketName", oldObjectName);
// 上傳新圖片
String newFileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
ossClient.putObject("bucketName", "images/" + newFileName, new ByteArrayInputStream(file.getBytes()));
// 更新數(shù)據(jù)庫(kù)
book.setTitle(title);
book.setImageUrl("https://bucketName.oss-cn-region.aliyuncs.com/images/" + newFileName);
bookRepository.save(book);
return ResponseEntity.ok("圖片已更新");
}
}
優(yōu)點(diǎn):
- 支持高并發(fā)訪(fǎng)問(wèn),適合大規(guī)模應(yīng)用場(chǎng)景。
- 提供豐富的 API 和工具,便于集成和管理。
缺點(diǎn):
- 增加開(kāi)發(fā)復(fù)雜度和成本。
- 對(duì)第三方服務(wù)依賴(lài)較高,存在潛在風(fēng)險(xiǎn)。
總結(jié)對(duì)比表格
| 方案 | 存儲(chǔ)方式 | 優(yōu)點(diǎn) | 缺點(diǎn) | 適用場(chǎng)景 |
|---|---|---|---|---|
| 方案一:BLOB 存儲(chǔ) | 直接將圖片存入數(shù)據(jù)庫(kù) | 數(shù)據(jù)集中管理,易于備份和遷移 | 影響數(shù)據(jù)庫(kù)性能,不適用于高并發(fā) | 小規(guī)模項(xiàng)目,簡(jiǎn)單功能 |
| 方案二:本地文件系統(tǒng) | 圖片存服務(wù)器,路徑存數(shù)據(jù)庫(kù) | 減輕數(shù)據(jù)庫(kù)壓力,易擴(kuò)展 | 文件管理復(fù)雜,需同步更新路徑 | 中小型項(xiàng)目,單機(jī)部署 |
| 方案三:云存儲(chǔ)服務(wù) | 圖片存云端,URL 存數(shù)據(jù)庫(kù) | 高并發(fā)支持,功能豐富 | 開(kāi)發(fā)復(fù)雜度高,依賴(lài)第三方服務(wù) | 大型項(xiàng)目,分布式架構(gòu) |
根據(jù)你的項(xiàng)目規(guī)模和技術(shù)需求選擇合適的方案,可以平衡開(kāi)發(fā)效率、性能和可維護(hù)性。
以上就是基于SpringBoot和MySQL實(shí)現(xiàn)圖片CRUD的三種解決方案的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot MySQL圖片CRUD的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java線(xiàn)程中斷?interrupt?和?LockSupport解析
這篇文章主要為大家介紹了java線(xiàn)程中斷?interrupt?和?LockSupport示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Leetcode常見(jiàn)鏈表問(wèn)題及代碼示例
這篇文章主要介紹了Leetcode常見(jiàn)鏈表問(wèn)題及代碼示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
Intellij IDEA的一些調(diào)試技巧(小結(jié))
本篇文章主要介紹了Intellij IDEA的一些調(diào)試技巧(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11
詳解在Java程序中運(yùn)用Redis緩存對(duì)象的方法
這篇文章主要介紹了在Java程序中運(yùn)用Redis緩存對(duì)象的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03
java書(shū)店系統(tǒng)畢業(yè)設(shè)計(jì) 用戶(hù)模塊(2)
這篇文章主要介紹了java書(shū)店系統(tǒng)畢業(yè)設(shè)計(jì),第二步系統(tǒng)總體設(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
Spring運(yùn)行環(huán)境Environment的解析
本文主要介紹了Spring運(yùn)行環(huán)境Environment的解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08

