SpringBoot + MongoDB 配置详解
本文将详细介绍SpringBoot与MongoDB的整合配置,包括依赖引入、连接配置、连接池设置、实体类定义、Repository使用和高级功能等内容,帮助开发者快速实现MongoDB数据库操作。
一、依赖配置
首先在pom.xml中添加Spring Data MongoDB的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- 可选:添加Lombok简化实体类开发 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
二、基本连接配置 (application.yml)
在application.yml中配置MongoDB连接信息:
1. 基本连接(无认证)
spring:
data:
mongodb:
# 基本URI格式
uri: mongodb://localhost:27017/yourdatabase
2. 带认证的连接
spring:
data:
mongodb:
# 普通用户认证
uri: mongodb://用户名:密码@127.0.0.1:27017/yourdatabase
# 超级管理员认证(需要指定authSource)
# uri: mongodb://用户名:密码@127.0.0.1:27017/yourdatabase?authSource=admin&authMechanism=SCRAM-SHA-1
3. 连接池配置
spring:
data:
mongodb:
uri: mongodb://localhost:27017/yourdatabase
# 连接池配置
connection-pool:
max-size: 50 # 最大连接数
min-size: 10 # 最小连接数
max-wait-queue-size: 500 # 最大等待队列大小
max-wait-time: 2000ms # 最大等待时间
max-idle-time: 60000ms # 最大空闲时间
max-life-time: 1800000ms # 连接最大生命周期
4. 副本集配置
spring:
data:
mongodb:
# 副本集连接格式
uri: mongodb://user:password@host1:27017,host2:27017,host3:27017/yourdatabase?replicaSet=rs0
三、自定义MongoDB配置类
对于更复杂的配置需求,可以创建自定义配置类:
1. 配置属性类
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import java.util.List;
@Component
@ConfigurationProperties(prefix = "spring.data.mongodb.custom")
@Validated
public class MongoSettingsProperties {
@NotBlank
private String database;
@NotEmpty
private List<String> hosts;
@NotEmpty
private List<Integer> ports;
private String replicaSet;
private String username;
private String password;
private String authenticationDatabase;
private Integer minConnectionsPerHost = 10;
private Integer connectionsPerHost = 20;
// getter和setter方法
// ...
}
2. 配置类实现
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class MongoConfig {
@Autowired
private MongoSettingsProperties mongoSettingsProperties;
@Bean
public MongoClient mongoClient() {
// 创建服务器地址列表
List<ServerAddress> serverAddresses = new ArrayList<>();
for (int i = 0; i < mongoSettingsProperties.getHosts().size(); i++) {
serverAddresses.add(new ServerAddress(
mongoSettingsProperties.getHosts().get(i),
mongoSettingsProperties.getPorts().get(i)
));
}
// 创建认证信息
MongoCredential credential = null;
if (mongoSettingsProperties.getUsername() != null && !mongoSettingsProperties.getUsername().isEmpty()) {
credential = MongoCredential.createCredential(
mongoSettingsProperties.getUsername(),
mongoSettingsProperties.getAuthenticationDatabase() != null ?
mongoSettingsProperties.getAuthenticationDatabase() :
mongoSettingsProperties.getDatabase(),
mongoSettingsProperties.getPassword().toCharArray()
);
}
// 构建MongoClientSettings
MongoClientSettings.Builder builder = MongoClientSettings.builder()
.applyToConnectionPoolSettings(builder1 -> {
builder1.maxSize(mongoSettingsProperties.getConnectionsPerHost());
builder1.minSize(mongoSettingsProperties.getMinConnectionsPerHost());
});
if (credential != null) {
builder.credential(credential);
}
if (mongoSettingsProperties.getReplicaSet() != null && !mongoSettingsProperties.getReplicaSet().isEmpty()) {
builder.applyToClusterSettings(builder1 ->
builder1.requiredReplicaSetName(mongoSettingsProperties.getReplicaSet())
);
}
builder.applyToClusterSettings(builder1 -> builder1.hosts(serverAddresses));
return MongoClients.create(builder.build());
}
@Bean
public MongoDatabaseFactory mongoDatabaseFactory(MongoClient mongoClient) {
return new SimpleMongoClientDatabaseFactory(
mongoClient, mongoSettingsProperties.getDatabase());
}
@Bean
public MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDatabaseFactory) {
return new MongoTemplate(mongoDatabaseFactory);
}
}
3. 自定义配置对应的application.yml
spring:
data:
mongodb:
custom:
hosts:
- 127.0.0.1
ports:
- 27017
# 副本集配置
# replica-set: rs0
username: admin
password: admin123
database: testdb
authentication-database: admin
connections-per-host: 20
min-connections-per-host: 10
四、实体类定义
使用Spring Data MongoDB注解定义实体类:
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import java.util.Date;
@Data
@Document(collection = "users") // 指定集合名称
public class User {
@Id // 主键
private String id;
@Field("username") // 字段映射
private String username;
@Field("email")
private String email;
@Field("created_at")
private Date createdAt;
@Field("age")
private Integer age;
}
五、Repository接口
Spring Data MongoDB支持Repository模式,简化数据访问层开发:
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface UserRepository extends MongoRepository<User, String> {
// 基于方法名自动生成查询
Optional<User> findByUsername(String username);
List<User> findByAgeGreaterThan(int age);
// 自定义查询
@Query("{ 'email' : ?0 }")
Optional<User> findByEmail(String email);
// 分页查询
Page<User> findByAgeBetween(int minAge, int maxAge, Pageable pageable);
}
六、使用MongoTemplate操作数据库
对于更复杂的查询需求,可以使用MongoTemplate:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private UserRepository userRepository;
// 使用MongoTemplate查询
public List<User> findUsersByAge(int age) {
Query query = new Query(Criteria.where("age").is(age));
return mongoTemplate.find(query, User.class);
}
// 保存用户
public User saveUser(User user) {
return mongoTemplate.save(user);
}
// 复杂查询
public List<User> findUsersByCondition(String keyword, int minAge) {
Criteria criteria = new Criteria();
criteria.orOperator(
Criteria.where("username").regex(keyword),
Criteria.where("email").regex(keyword)
);
criteria.and("age").gte(minAge);
Query query = new Query(criteria);
return mongoTemplate.find(query, User.class);
}
// 删除用户
public void deleteUser(String id) {
mongoTemplate.remove(Query.query(Criteria.where("_id").is(id)), User.class);
}
}
七、控制器实现
创建RESTful API控制器:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private UserRepository userRepository;
// 获取所有用户
@GetMapping
public List<User> getAllUsers() {
return userRepository.findAll();
}
// 分页查询
@GetMapping("/page")
public Page<User> getUsersByPage(@RequestParam int page, @RequestParam int size) {
return userRepository.findAll(PageRequest.of(page, size));
}
// 根据ID获取用户
@GetMapping("/{id}")
public Optional<User> getUserById(@PathVariable String id) {
return userRepository.findById(id);
}
// 创建用户
@PostMapping
public User createUser(@RequestBody User user) {
return userService.saveUser(user);
}
// 更新用户
@PutMapping("/{id}")
public User updateUser(@PathVariable String id, @RequestBody User user) {
user.setId(id);
return userService.saveUser(user);
}
// 删除用户
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable String id) {
userService.deleteUser(id);
}
// 按年龄查询
@GetMapping("/by-age")
public List<User> getUsersByAge(@RequestParam int age) {
return userService.findUsersByAge(age);
}
}
八、副本集高级配置
对于MongoDB副本集配置,需要注意以下几点:
- 确保MongoDB实例已配置为副本集
- 在连接URI中指定副本集名称
- 配置读取偏好,实现读写分离
@Configuration
public class MongoReplicaSetConfig {
@Bean
public MongoClient mongoClient() {
MongoClientSettings settings = MongoClientSettings.builder()
.applyToClusterSettings(builder ->
builder.hosts(Arrays.asList(
new ServerAddress("host1", 27017),
new ServerAddress("host2", 27017),
new ServerAddress("host3", 27017)
))
.requiredReplicaSetName("rs0")
)
.applyToConnectionPoolSettings(builder -> {
builder.maxSize(50);
builder.minSize(10);
})
// 配置读取首选项,实现读写分离
.readPreference(ReadPreference.secondaryPreferred())
.build();
return MongoClients.create(settings);
}
}
九、常见问题与解决方案
1. 连接超时问题
- 检查MongoDB服务是否启动
- 确认网络连接和防火墙设置
- 调整连接超时参数
spring:
data:
mongodb:
uri: mongodb://localhost:27017/testdb?connectTimeoutMS=5000&socketTimeoutMS=30000
2. 认证失败问题
- 确认用户名和密码是否正确
- 检查认证数据库是否正确(通常是admin)
- 验证用户权限
3. 性能优化
- 合理设置连接池大小
- 创建适当的索引
- 使用批量操作减少网络开销
4. 序列化问题
对于复杂对象的序列化,可能需要自定义转换器:
@Configuration
public class MongoConfig {
@Bean
public MongoCustomConversions mongoCustomConversions() {
List<Converter<?, ?>> converters = new ArrayList<>();
// 添加自定义转换器
converters.add(new LocalDateTimeToDateConverter());
converters.add(new DateToLocalDateTimeConverter());
return new MongoCustomConversions(converters);
}
}
通过以上配置和示例,您可以成功实现SpringBoot与MongoDB的整合,并根据项目需求进行灵活的配置和使用。