springboot集成mongoDB實(shí)現(xiàn)一個(gè)文件存儲(chǔ)服務(wù)器
mongoDB簡(jiǎn)介
什么是MongoDB ?
MongoDB 是由C++語言編寫的,是一個(gè)基于分布式文件存儲(chǔ)的開源數(shù)據(jù)庫系統(tǒng)。在高負(fù)載的情況下,添加更多的節(jié)點(diǎn),可以保證服務(wù)器性能。MongoDB 旨在為WEB應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案。MongoDB 將數(shù)據(jù)存儲(chǔ)為一個(gè)文檔,數(shù)據(jù)結(jié)構(gòu)由鍵值(key=>value)對(duì)組成。MongoDB 文檔類似于 JSON 對(duì)象。字段值可以包含其他文檔,數(shù)組及文檔數(shù)組。

MongoDB的用途
游戲場(chǎng)景,使用 MongoDB 存儲(chǔ)游戲用戶信息,用戶的裝備、積分等直接以內(nèi)嵌文檔的形式存儲(chǔ),方便查詢、更新。
物流場(chǎng)景,使用 MongoDB 存儲(chǔ)訂單信息,訂單狀態(tài)在運(yùn)送過程中會(huì)不斷更新,以 MongoDB 內(nèi)嵌數(shù)組的形式來存儲(chǔ),一次查詢就能將訂單所有的變更讀取出來。
社交場(chǎng)景,使用 MongoDB 存儲(chǔ)存儲(chǔ)用戶信息,以及用戶發(fā)表的朋友圈信息,通過地理位置索引實(shí)現(xiàn)附近的人、地點(diǎn)等功能。
物聯(lián)網(wǎng)場(chǎng)景,使用 MongoDB 存儲(chǔ)所有接入的智能設(shè)備信息,以及設(shè)備匯報(bào)的日志信息,并對(duì)這些信息進(jìn)行多維度的分析。
視頻直播,使用 MongoDB 存儲(chǔ)用戶信息、禮物信息等。
-
......
總體而言,mongoDB適用于對(duì)事務(wù)沒有要求的數(shù)據(jù)存儲(chǔ),比如評(píng)論、流水日志等信息。
springboot集成mongoDB搭建文件存儲(chǔ)服務(wù)器
項(xiàng)目使用的s版本
springboot版本: 2.3.7.REALEASE
mongoDB版本:mongodb-linux-x86_64-rhel70-4.2.18
下載mongoDB數(shù)據(jù)庫
下載地址:Try MongoDB Atlas Products | MongoDB

安裝并配置mongoDB
將下載好的mongoDB放到要安裝的linux虛擬機(jī)里,執(zhí)行以下指令進(jìn)行解壓:
tar -xzvf mongodb-linux-x86_64-rhel70-4.2.18.tgz
解壓后得到文件:mongodb-linux-x86_64-rhel70-4.2.18,將文件移入自己想放到的地方:
mv mongodb-linux-x86_64-rhel70-4.2.18 /usr/local/mongodb4
設(shè)置mongoDB的啟動(dòng)目錄環(huán)境變量,方便啟動(dòng):
vim /etc/profile
#執(zhí)行后在文件的最后一行添加
export PATH=/usr/local/mongodb4/bin:$PATH #文件目錄是mongoDB文件所在位置下的bin文件
#最后執(zhí)行文件,將環(huán)境變量加載
source /etc/profile
配置mongoDB的啟動(dòng)方式,讓它以后臺(tái)形式啟動(dòng),可遠(yuǎn)程訪問,不需要進(jìn)行認(rèn)證:
vim /etc/mongodb.conf #創(chuàng)建mongodb的配置文件
進(jìn)入配置文件后:
#mongoDB的數(shù)據(jù)保存目錄路徑
dbpath=/var/lib/mongo
#mongoDB的日志文件路徑
logpath=/var/log/mongodb/mongod.log
#配置任何ip都可以進(jìn)行遠(yuǎn)程訪問,可以單獨(dú)配置個(gè)人ip
bind_ip=0.0.0.0
#訪問的端口號(hào)
port=27017
#配置該項(xiàng),讓mongoDB以后臺(tái)方式進(jìn)行啟動(dòng)
fork=true
#配置該項(xiàng),遠(yuǎn)程訪問mongoDB不需要認(rèn)證,即不用賬號(hào)和密碼
auth=false
啟動(dòng)mongoDB數(shù)據(jù)庫:
mongod -f /etc/mongodb.conf #以文件配置方式啟動(dòng)mongoDB服務(wù)器
搭建文件服務(wù)器
創(chuàng)建maven工程,配置pom.xml文件
在linux虛擬機(jī)啟動(dòng)mongoDB數(shù)據(jù)庫后進(jìn)行配置,加入相關(guān)依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<!-- SpringWeb依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombok注解依賴 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- mongoDB數(shù)據(jù)庫依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- 工具庫依賴,MD5編碼等 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.1</version>
</dependency>
</dependencies>
配置yml文件
#springboot應(yīng)用的地址和端口
server:
port: 8080
address: localhost
spring:
data:
mongodb:
database: test #要使用的mongoDB數(shù)據(jù)庫
port: 27017 #端口號(hào)和mongodb.conf相一致
host: 192.168.200.130 #虛擬機(jī)地址
實(shí)體類代碼
實(shí)體類會(huì)在mongoDB中以鍵值對(duì)的方式,保存到數(shù)據(jù)庫中。
@Document
@NoArgsConstructor
@ToString
public class MongoFile {
private String id;
private String name;
private String contentType;
private long size;
private Date uploadDate;
private String md5;
private Binary content;
private String path;
public MongoFile(String name, String contentType, long size, Binary content) {
this.name = name;
this.contentType = contentType;
this.size = size;
this.uploadDate = new Date();
this.content = content;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public Date getUploadDate() {
return uploadDate;
}
public void setUploadDate(Date uploadDate) {
this.uploadDate = uploadDate;
}
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
public Binary getContent() {
return content;
}
public void setContent(Binary content) {
this.content = content;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if(obj == null || getClass() != obj.getClass()) {
return false;
}
MongoFile fileInfo = (MongoFile) obj;
return java.util.Objects.equals(size, fileInfo.size)
&& java.util.Objects.equals(name, fileInfo.name)
&& java.util.Objects.equals(contentType, fileInfo.contentType)
&& java.util.Objects.equals(uploadDate, fileInfo.uploadDate)
&& java.util.Objects.equals(md5, fileInfo.md5)
&& java.util.Objects.equals(id, fileInfo.id);
}
@Override
public int hashCode() {
return java.util.Objects.hash(name, contentType, size, uploadDate, md5, id);
}
}
Repository代碼
以直接繼承MongoRepository類的方式,實(shí)現(xiàn)mongoDB的增刪改查操作。
@Repository
public interface FileMapper extends MongoRepository<MongoFile, String> {
}
Service層代碼
@Service
public class FileServiceImpl implements FileService {
@Resource
private FileMapper fileMapper;
/* 保存文件 */
@Override
public MongoFile saveFile(MongoFile file) {
return fileMapper.save(file);
}
/* 刪除文件 */
@Override
public void removeFile(String id) {
fileMapper.deleteById(id);
}
/* 獲取文件 */
@Override
public Optional<MongoFile> getFileById(String id) {
return fileMapper.findById(id);
}
/* 查詢文件,前端以分頁的方式展示 */
@Override
public List<MongoFile> listFilesByPage(int pageIndex, int pageSize) {
Page<MongoFile> page = null;
List<MongoFile> list = null;
Sort sort = Sort.by(Sort.Direction.DESC, "uploadDate");
Pageable pageable = PageRequest.of(pageIndex, pageSize,sort);
page = fileMapper.findAll(pageable);
list = page.getContent();
return list;
}
}
Controller層代碼
@Controller
public class FileController {
@Autowired
private FileService fileService;
@Value("${server.address}")
private String host;
@Value("${server.port}")
private String port;
/* 獲取文件列表 */
@RequestMapping("/file")
public String index(Model model) {
List<MongoFile> files = fileService.listFilesByPage(0,20);
model.addAttribute("files",files );
return "file";
}
/* 獲取文件的分頁列表 */
@RequestMapping("/file/{pageIndex}/{pageSize}")
@ResponseBody
public List<MongoFile> listFilesByPage(@PathVariable int pageIndex, @PathVariable int pageSize) {
return fileService.listFilesByPage(pageIndex,pageSize);
}
/* 前端對(duì)文件進(jìn)行預(yù)覽下載 */
@GetMapping("/file/view/{id}")
@ResponseBody
public ResponseEntity<Object> serveFileOnline(@PathVariable String id) {
Optional<MongoFile> file = fileService.getFileById(id);
if(file.isPresent()) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "fileName=\""+file.get().getName()+"\"")
.header(HttpHeaders.CONTENT_TYPE,file.get().getContentType())
.header(HttpHeaders.CONTENT_LENGTH, file.get().getSize()+"")
.header("Connection", "close")
.body(file.get().getContent().getData());
}else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("File was not found");
}
}
/* 前端以ajax方式上傳文件后,返回文件的預(yù)覽(下載)路徑 */
@PostMapping("/file/upload")
@ResponseBody
public ResultEntity handlerFileUpload(@RequestParam("file")MultipartFile file) {
try {
MongoFile f = new MongoFile(file.getOriginalFilename(), file.getContentType(), file.getSize(),
new Binary(file.getBytes()));
f.setMd5(SecureUtil.md5(file.getInputStream()));
MongoFile saveFile = fileService.saveFile(f);
String fileUrl = "http://"+host+":"+port+"/file/view/"+saveFile.getId();
return ResultEntity.successWithData(fileUrl);
} catch (IOException e) {
e.printStackTrace();
return ResultEntity.fail(e.getMessage());
}
}
/* 刪除文件 */
@DeleteMapping("/file/{id}")
@ResponseBody
public ResultEntity deleteFile(@PathVariable("id") String id) {
try {
fileService.removeFile(id);
return ResultEntity.successWithoutData();
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.fail(e.getMessage());
}
}
}
前端展示
前端頁面對(duì)上傳的文件進(jìn)行展示:

總結(jié)
由于mongoDB對(duì)保存文件大小有較大的限制,本人將該項(xiàng)目?jī)H用于保存圖片,用于展示個(gè)人用戶的頭像以及MarkDown文件中的圖片鏈接。