SpringBoot MongoDB与MongoDB GridFS基本使用
1. 前言
在开发过程中,我们经常需要使用到数据库进行数据的存储和管理。MongoDB是一个开源的,高性能,面向文档的NoSQL数据库。在Java中,我们可以使用SpringBoot框架来连接MongoDB数据库,并支持使用MongoDB的GridFS进行文件的存储和管理。
2. MongoDB的基本介绍
如果您对MongoDB还不了解,可以先了解一下MongoDB的基本概念。
MongoDB是一种文档导向数据库管理系统(Document-Oriented Database Management System,简称Document DBMS),由C++语言编写。MongoDB的数据结构是由文档(document)组成的,一个文档相当于一个数据记录,可以包含任意数量的字段。MongoDB的数据存储格式是BSON(Binary JSON),它是一种二进制格式的JSON(JavaScript Object Notation)。
3. MongoDB的安装与配置
这一部分不详细说明,仅在此做简要介绍,读者可自行查阅相关文献。
在MongoDB官网下载适合自己操作系统的版本,然后进行安装。
安装完成后,在MongoDB的bin目录下,启动mongod服务:mongod.exe --dbpath "D:\MongoDB\data"。
4. SpringBoot连接MongoDB
在SpringBoot中连接MongoDB,需要使用MongoDB的官方Java驱动包"mongodb-driver"。实现步骤如下:
- 添加依赖
在SpringBoot的pom.xml文件中添加以下依赖:
org.mongodb
mongodb-driver
3.11.2
- 配置MongoDB连接信息
在SpringBoot的application.properties文件中,配置MongoDB的连接信息:
spring.data.mongodb.uri=mongodb://localhost:27017/test
- 编写Java代码
定义一个MongoDBRepository接口并继承MongoRepository,用于操作MongoDB中的数据。可以定义一些常用的操作方法,如下所示:
@Repository
public interface MongoDBRepository extends MongoRepository {
User findByUsername(String username);
List findByAgeGreaterThan(int age);
}
在SpringBoot的启动类中添加@ComponentScan注解,用于扫描MongoDBRepository接口所在的包。
然后,在需要操作MongoDB的地方,进行MongoDBRepository的注入,就可以使用MongoDB进行数据的存储和管理了。
5. MongoDB GridFS的基本介绍
MongoDB GridFS是一种MongoDB存储机制,用于存储大文件。
MongoDB GridFS将文件分为两个部分:元数据和数据。元数据保存在files集合中,数据保存在chunks集合中。元数据中保存了文件的名称、大小、上传日期、类型等信息。数据则是将文件切分为若干个chunk进行存储。
6. SpringBoot使用MongoDB GridFS
在SpringBoot中使用MongoDB GridFS,需要使用MongoDB的官方Java驱动包"mongodb-driver"和"mongodb-driver-core"。实现步骤如下:
- 添加依赖
在SpringBoot的pom.xml文件中添加以下依赖:
org.mongodb
mongodb-driver
3.11.2
org.mongodb
mongodb-driver-core
3.11.2
- 配置MongoDB连接信息
在SpringBoot的application.properties文件中,配置MongoDB的连接信息(同第4步)。
- 编写Java代码
使用以下代码,可以将一个文件保存到MongoDB GridFS中:
@Autowired
private GridFsTemplate gridFsTemplate;
public String storeFile(MultipartFile file) throws IOException {
DBObject metaData = new BasicDBObject();
metaData.put("userId", "12345");
metaData.put("fileName", file.getOriginalFilename());
metaData.put("fileType", file.getContentType());
GridFSFile gridFSFile = gridFsTemplate.store(file.getInputStream(), file.getOriginalFilename(), file.getContentType(), metaData);
return gridFSFile.getId().toString();
}
使用以下代码,可以从MongoDB GridFS中读取一个文件:
@Autowired
private GridFsTemplate gridFsTemplate;
public Resource loadFile(String fileId) throws IOException {
GridFSFile gridFSFile = gridFsTemplate.findOne(new Query(Criteria.where("_id").is(fileId)));
if (gridFSFile == null) {
throw new FileNotFoundException("File not found with id " + fileId);
}
GridFsResource resource = gridFsTemplate.getResource(gridFSFile);
return resource;
}
注意:在使用GridFsTemplate时,需要先进行注入。
7. 示例说明
下面提供两个示例,用于展示SpringBoot MongoDB与MongoDB GridFS的基本使用方法。
示例一:使用MongoDB
在使用MongoDB的示例中,我们将定义一个User类,然后使用MongoDBRepository对User类进行操作。
- 定义User类
User类定义如下:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Document(collection="user")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
private String username;
private Integer age;
private Date birthday;
}
- 编写操作类
在我们的操作类中,进行MongoDBRepository的注入。然后,我们定义了一些基本的操作方法:
@Service
public class MongoDBService {
@Autowired
private MongoDBRepository mongoDBRepository;
public User saveUser(User user) {
return mongoDBRepository.save(user);
}
public void deleteUser(Long id) {
mongoDBRepository.deleteById(id);
}
public User getUserByUsername(String username) {
return mongoDBRepository.findByUsername(username);
}
public List getUsersByAgeGreaterThan(int age) {
return mongoDBRepository.findByAgeGreaterThan(age);
}
}
- 编写测试类
在测试类中,我们进行了一些简单的测试:
@SpringBootTest
class MongoDBServiceTest {
@Autowired
private MongoDBService mongoDBService;
@Test
void saveUser() {
User user = new User();
user.setId(1L);
user.setUsername("张三");
user.setAge(20);
user.setBirthday(new Date());
mongoDBService.saveUser(user);
}
@Test
void deleteUser() {
mongoDBService.deleteUser(1L);
}
@Test
void getUserByUsername() {
User user = mongoDBService.getUserByUsername("张三");
System.out.println(user);
}
@Test
void getUsersByAgeGreaterThan() {
List userList = mongoDBService.getUsersByAgeGreaterThan(15);
for (User user : userList) {
System.out.println(user);
}
}
}
示例二:使用MongoDB GridFS
在使用MongoDB GridFS的示例中,我们将定义一个FileService类,用于操作MongoDB GridFS进行文件的上传和下载。
- 编写FileService类
在FileService类中,我们进行了GridFsTemplate的注入,并定义了进行文件上传和下载的方法:
@Service
public class FileService {
@Autowired
private GridFsTemplate gridFsTemplate;
public String storeFile(MultipartFile file) throws IOException {
DBObject metaData = new BasicDBObject();
metaData.put("userId", "12345");
metaData.put("fileName", file.getOriginalFilename());
metaData.put("fileType", file.getContentType());
GridFSFile gridFSFile = gridFsTemplate.store(file.getInputStream(), file.getOriginalFilename(), file.getContentType(), metaData);
return gridFSFile.getId().toString();
}
public Resource loadFile(String fileId) throws IOException {
GridFSFile gridFSFile = gridFsTemplate.findOne(new Query(Criteria.where("_id").is(fileId)));
if (gridFSFile == null) {
throw new FileNotFoundException("File not found with id " + fileId);
}
GridFsResource resource = gridFsTemplate.getResource(gridFSFile);
return resource;
}
}
- 编写控制器类
在控制器类中,我们进行了FileService的注入,并定义了文件上传和下载的接口:
@RestController
@RequestMapping("/file")
public class FileController {
@Autowired
private FileService fileService;
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
return fileService.storeFile(file);
}
@GetMapping("/download/{fileId}")
public ResponseEntity downloadFile(@PathVariable String fileId) throws IOException {
Resource resource = fileService.loadFile(fileId);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(resource.getFilename()))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
}
- 编写测试类
在使用MongoDB GridFS进行文件上传和下载的测试类中,代码如下:
@SpringBootTest
class FileControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void uploadFile() throws Exception {
File file = new File("D:\\图片\\1.jpg");
FileInputStream input = new FileInputStream(file);
MockMultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "text/plain", input);
mockMvc.perform(MockMvcRequestBuilders.multipart("/file/upload")
.file(multipartFile))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("60d8b807c8addb32c7cc74b5"));
}
@Test
void downloadFile() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/file/download/60d8b807c8addb32c7cc74b5"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.header().exists(HttpHeaders.CONTENT_DISPOSITION));
}
}
注意:在测试FileController类时,我们需要使用MockMvc来进行测试。在本例中,使用MockMultipartFile对象来模拟文件上传。