SpringBoot中使用MongoDB的連接池配置

在SpringBoot中,我們可以通過引入 spring-boot-starter-data-mongodb 依賴來實現spring-data-mongodb 的自動配置。但是,默認情況下,該依賴並沒有像使用MySQL或者Redis那樣為我們提供連接池配置的功能。因此,我們需要自行重寫 MongoDbFactory,實現MongoDB客戶端連接的參數配置擴展。需要說明的是,MongoDB的客戶端本身就是一個連接池,因此,我們隻需要配置客戶端即可。

引入依賴

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.0.2.RELEASE</version>
 </parent>
 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-mongodb</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
 </dependencies>

配置文件

為瞭方便對Mongodb進行統一管理,我們將相關的配置抽取到 mongo-pool.properties 中,前綴為spring.data.mongodb(前綴可自己隨意配置):

spring.data.mongodb.address=172.16.250.234:27017,172.16.250.239:27017,172.16.250.240:27017
spring.data.mongodb.replica-set=rs0
spring.data.mongodb.database=test
spring.data.mongodb.username=admin
spring.data.mongodb.password=admin
 
# Configure spring.data.mongodbDB Pool
spring.data.mongodb.min-connections-per-host=10
spring.data.mongodb.max-connections-per-host=100
spring.data.mongodb.threads-allowed-to-block-for-connection-multiplier=5
spring.data.mongodb.server-selection-timeout=30000
spring.data.mongodb.max-wait-time=120000
spring.data.mongodb.max-connection-idel-time=0
spring.data.mongodb.max-connection-life-time=0
spring.data.mongodb.connect-timeout=10000
spring.data.mongodb.socket-timeout=0
spring.data.mongodb.socket-keep-alive=false
spring.data.mongodb.ssl-enabled=false
spring.data.mongodb.ssl-invalid-host-name-allowed=false
spring.data.mongodb.always-use-m-beans=false
spring.data.mongodb.heartbeat-socket-timeout=20000
spring.data.mongodb.heartbeat-connect-timeout=20000
spring.data.mongodb.min-heartbeat-frequency=500
spring.data.mongodb.heartbeat-frequency=10000
spring.data.mongodb.local-threshold=15
spring.data.mongodb.authentication-database=auth_dev

配置文件映射為JavaBean

為方便調用,將上述配置包裝成一個配置實體類,代碼如下:

import java.util.List;
 
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
 
@Component
@PropertySource(value = "classpath:mongo-pool.properties")
@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoSettingsProperties {
 
 private List<String> address;
 private String replicaSet;
 private String database;
 private String username;
 private String password;
 private Integer minConnectionsPerHost = 0;
 private Integer maxConnectionsPerHost = 100;
 private Integer threadsAllowedToBlockForConnectionMultiplier = 5;
 private Integer serverSelectionTimeout = 30000;
 private Integer maxWaitTime = 120000;
 private Integer maxConnectionIdleTime = 0;
 private Integer maxConnectionLifeTime = 0;
 private Integer connectTimeout = 10000;
 private Integer socketTimeout = 0;
 private Boolean socketKeepAlive = false;
 private Boolean sslEnabled = false;
 private Boolean sslInvalidHostNameAllowed = false;
 private Boolean alwaysUseMBeans = false;
 private Integer heartbeatConnectTimeout = 20000;
 private Integer heartbeatSocketTimeout = 20000;
 private Integer minHeartbeatFrequency = 500;
 private Integer heartbeatFrequency = 10000;
 private Integer localThreshold = 15;
 private String authenticationDatabase;
 
 // 省略Getters和Setters方法
}

覆蓋MongoDbFactory

自定義創建一個MongoDbFactory用來替代Springboot為我們自動裝配的MongoDbFactory,代碼如下:

import java.util.ArrayList;
import java.util.List;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
 
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
 
@Configuration
public class MongoConfig {
 
 private static final Logger logger = LoggerFactory.getLogger(MongoConfig.class);
 
 // 覆蓋容器中默認的MongoDbFacotry Bean
 @Bean
 @Autowired
 public MongoDbFactory mongoDbFactory(MongoSettingsProperties properties) {
 
  // 客戶端配置(連接數,副本集群驗證)
  MongoClientOptions.Builder builder = new MongoClientOptions.Builder();
  builder.connectionsPerHost(properties.getMaxConnectionsPerHost());
  builder.minConnectionsPerHost(properties.getMinConnectionsPerHost());
  if (properties.getReplicaSet() != null) {
   builder.requiredReplicaSetName(properties.getReplicaSet());
  }
  builder.threadsAllowedToBlockForConnectionMultiplier(
    properties.getThreadsAllowedToBlockForConnectionMultiplier());
  builder.serverSelectionTimeout(properties.getServerSelectionTimeout());
  builder.maxWaitTime(properties.getMaxWaitTime());
  builder.maxConnectionIdleTime(properties.getMaxConnectionIdleTime());
  builder.maxConnectionLifeTime(properties.getMaxConnectionLifeTime());
  builder.connectTimeout(properties.getConnectTimeout());
  builder.socketTimeout(properties.getSocketTimeout());
  // builder.socketKeepAlive(properties.getSocketKeepAlive());
  builder.sslEnabled(properties.getSslEnabled());
  builder.sslInvalidHostNameAllowed(properties.getSslInvalidHostNameAllowed());
  builder.alwaysUseMBeans(properties.getAlwaysUseMBeans());
  builder.heartbeatFrequency(properties.getHeartbeatFrequency());
  builder.minHeartbeatFrequency(properties.getMinHeartbeatFrequency());
  builder.heartbeatConnectTimeout(properties.getHeartbeatConnectTimeout());
  builder.heartbeatSocketTimeout(properties.getHeartbeatSocketTimeout());
  builder.localThreshold(properties.getLocalThreshold());
  MongoClientOptions mongoClientOptions = builder.build();
 
  // MongoDB地址列表
  List<ServerAddress> serverAddresses = new ArrayList<ServerAddress>();
  for (String address : properties.getAddress()) {
   String[] hostAndPort = address.split(":");
   String host = hostAndPort[0];
   Integer port = Integer.parseInt(hostAndPort[1]);
   ServerAddress serverAddress = new ServerAddress(host, port);
   serverAddresses.add(serverAddress);
  }
 
  logger.info("serverAddresses:" + serverAddresses.toString());
 
  // 連接認證
  // MongoCredential mongoCredential = null;
  // if (properties.getUsername() != null) {
  //  mongoCredential = MongoCredential.createScramSha1Credential(
  //    properties.getUsername(), properties.getAuthenticationDatabase() != null
  //      ? properties.getAuthenticationDatabase() : properties.getDatabase(),
  //    properties.getPassword().toCharArray());
  // }
 
  // 創建認證客戶端
  // MongoClient mongoClient = new MongoClient(serverAddresses, mongoCredential, mongoClientOptions);
 
  // 創建非認證客戶端
  MongoClient mongoClient = new MongoClient(serverAddresses, mongoClientOptions);
 
  // 創建MongoDbFactory
  MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClient, properties.getDatabase());
  return mongoDbFactory;
 }
}

MongoDB測試

創建數據實體

import java.io.Serializable;
 
public class UserEntity implements Serializable {
 
 private static final long serialVersionUID = 1L;
 
 private Long id;
 private String userName;
 private String passWord;
 
 public Long getId() {
  return id;
 }
 
 public void setId(Long id) {
  this.id = id;
 }
 
 public String getUserName() {
  return userName;
 }
 
 public void setUserName(String userName) {
  this.userName = userName;
 }
 
 public String getPassWord() {
  return passWord;
 }
 
 public void setPassWord(String passWord) {
  this.passWord = passWord;
 }
 
 public String toString() {
  return "id: " + id + ",userName: " + userName + ",passWord: " + passWord;
 }
}

創建Dao接口及實現

public interface UserDao {
 
 void saveUser(UserEntity user);
 
 UserEntity findUserByName(String userName);
}
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.Component;
 
@Component
public class UserDaoImpl implements UserDao {
 
 @Autowired
 private MongoTemplate mongoTemplate;
 
 @Override
 public void saveUser(UserEntity user) {
  mongoTemplate.save(user);
 }
 
 @Override
 public UserEntity findUserByName(String userName) {
  Query query = new Query(Criteria.where("userName").is(userName));
  UserEntity user = mongoTemplate.findOne(query, UserEntity.class);
  return user;
 }
}

編寫測試代碼

import java.util.Optional;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Example;
import org.springframework.test.context.junit4.SpringRunner;
 
import com.pengjunlee.UserDao;
import com.pengjunlee.UserEntity;
import com.pengjunlee.UserRepository;
 
@RunWith(SpringRunner.class)
@SpringBootTest
public class MongoTest {
 @Autowired
 private UserDao userDao;
 
 @Autowired
 private UserRepository userRepository;
 
 @Test
 public void testSaveUser() {
  UserEntity user = new UserEntity();
  user.setId(88L);
  user.setUserName("XiaoMing");
  user.setPassWord("123456");
  userDao.saveUser(user);
 }
 
 @Test
 public void testFindUser01() {
  UserEntity user = userDao.findUserByName("XiaoMing");
  System.out.println(user);
 }
 
 @Test
 public void testFindUser02() {
  UserEntity queryUser = new UserEntity();
  queryUser.setUserName("XiaoMing");
  Example<UserEntity> example = Example.of(queryUser);
  Optional<UserEntity> optional = userRepository.findOne(example);
  System.out.println(optional.get());
 }
}

查詢結果:

id: 88,userName: XiaoMing,passWord: 123456

到此這篇關於SpringBoot中使用MongoDB的連接池配置的文章就介紹到這瞭,更多相關SpringBoot MongoDB連接池配置內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: