springboot集成mongoDB實(shí)現(xiàn)一個(gè)文件存儲(chǔ)服務(wù)器

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ù)組。

img

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

image-20220124100535154.png

安裝并配置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)行展示:

image.png

總結(jié)

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容