掘金 后端 ( ) • 2024-04-19 10:07

需求

一个项目里需要连接多个 mongodb,有的 mongodb 是集群。

详细步骤及代码

  • step1:创建springboot项目,pom.xml引入依赖 mongodb
    • spring-boot-starter-parent:2.0.4.RELEASE 版本
    • spring-boot-starter-web
    • spring-boot-starter-data-mongodb
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.4.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.awen</groupId>
	<artifactId>day201220-mongodb-connect</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>day201220-mongodb-connect</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- mongodb -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-mongodb</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

  • step2:application.yaml 添加mongodb配置
server:
  port: 8080
  servlet:
    context-path: /mongodb-connect

spring:
  application:
    name: mongodb-connect
  # mongodb
  data:
    mongodb:
      test1:
#        uri: mongodb://test1:[email protected]:27017/test1_authsource
        addresses: 127.0.0.1:27017
        username: test1
        password: test1_password
        authsource: test1_authsource
        database: test1_database
      test2:
#        uri: mongodb://${mongodb.username}:${mongodb.password}@${mongodb.addresses}/${mongodb.authsource}
        addresses: 127.0.0.1:27017,127.0.0.2:27017
        username: test2
        password: test2_password
        authsource: admin
        database: test2_database
  • step3:创建 AbstractMongoConfig 抽象MongoConfig
    • 建议使用 MongoCredential 方式,不推荐 MongoClientURI 方式创建。
    • 因为有的时候 mongodb 连接的密码是带 @ 或者其他特殊字符的密码,使用 uri 方式建立连接,可能在拆分 uri 的时候,拆分错误,导致创建失败。

test1 mongodb 的 uri 是:mongodb://test1:[email protected]:27017/test1_authsource。 比如密码是 test1@123456,如果使用 uri,mongodb://test1:test1@[email protected]:27017/test1_authsource,会被拆分为“username=test1, password=test1, [email protected]:27-17”,会创建失败。

package com.awen.day201220mongodbconnect.config;

import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * MongoTemplate 配置
 *      使用 MongoCredential 方式;支持集群。
 */
public abstract class AbstractMongoConfig {
    /**
     * mongodb 配置信息
     */
    private ArrayList<String> addresses;
    private String uri;
    private String authsource, database, username, password;

    // 省略 addresses、uri、authsource, database, username, password 的 setXXX/getXXX方法
    // ...

    /**
     * 获取 MongoTemplate 对象
     */
    public abstract MongoTemplate getMongoTemplate() throws Exception;

    /**
     * 创建 MongoDbFactory 工厂:
     *      覆盖容器中默认的 MongoDbFactory Bean
     */
    public MongoDbFactory mongoDbFactory() {
        // MongoDB 地址列表
        List<ServerAddress> serverAddresses = new ArrayList<ServerAddress>();

        for (String address : addresses) {
            String[] hostAndPort = address.split(":");
            String host = hostAndPort[0];
            Integer port = Integer.parseInt(hostAndPort[1]);
            ServerAddress serverAddress = new ServerAddress(host, port);
            serverAddresses.add(serverAddress);
        }

        // 创建非认证客户端
//        MongoClient mongoClient = new MongoClient(serverAddresses);

        // 使用 MongoClientURI 方式创建
//        MongoClient mongoClient = new MongoClient(new MongoClientURI(uri));

        // 使用 MongoCredential 方式创建
        // 连接认证
        MongoCredential mongoCredential = MongoCredential.createCredential(username, authsource, password.toCharArray());
        // 创建认证客户端
        MongoClient mongoClient = new MongoClient(serverAddresses, Arrays.asList(mongoCredential));

        // 创建MongoDbFactory
        MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClient, database);
        return mongoDbFactory;
    }
}
  • step4:创建 MongoDBTest1Config,继承 AbstractMongoConfig 类
package com.awen.day201220mongodbconnect.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;

/**
 * test1 MongoTemplate 配置
 */
@Configuration
@ConfigurationProperties(prefix = "spring.data.mongodb.test1")
public class MongoDBTest1Config extends AbstractMongoConfig {

    @Override
    @Bean(name = "test1MongoTemplate")
    public MongoTemplate getMongoTemplate() throws Exception {
        return new MongoTemplate(mongoDbFactory());
    }
}
  • step5:创建 MongoDBTest2Config,继承 AbstractMongoConfig 类
package com.awen.day201220mongodbconnect.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;

/**
 * test2 MongoTemplate 配置
 */
@Configuration
@ConfigurationProperties(prefix = "spring.data.mongodb.test2")
public class MongoDBTest2Config extends AbstractMongoConfig {

    @Override
    @Bean(name = "test2MongoTemplate")
    public MongoTemplate getMongoTemplate() throws Exception {
        return new MongoTemplate(mongoDbFactory());
    }
}
  • step6:添加 Controller 类 测试
package com.awen.day201220mongodbconnect.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;

/**
 * 测试 mongodb 查询
 */
@RestController
@RequestMapping("test")
public class MongoTestController {
    private final static Logger logger = LoggerFactory.getLogger(MongoTestController.class);

    @Resource
    @Qualifier("test1MongoTemplate")
    MongoTemplate test1MongoTemplate;

    @Resource
    @Qualifier("test2MongoTemplate")
    MongoTemplate test2MongoTemplate;

    @GetMapping("query1")
    public List<Map> queryTest1() {
        List<Map> userList = test1MongoTemplate.findAll(Map.class, "user");
        return userList;
    }
}
  • step7:启动类添加注解
    • 去掉 mongodb 自动配置:@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
    • 经测试,不加 (exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) 也可以启动成功,且可以访问。
package com.awen.day201220mongodbconnect;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;

// 去掉 mongodb 的自动配置
@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
public class Day201220MongodbConnectApplication {

	public static void main(String[] args) {
		SpringApplication.run(Day201220MongodbConnectApplication.class, args);
	}

}
  • step8:测试

访问 http://127.0.0.1:8080/mongodb-connect/test/query1 返回结果:[{"_id":{"timestamp":1608460199,"machineIdentifier":300955,"processIdentifier":7148,"counter":4866,"time":1608460199000,"date":"2020-12-20T10:29:59.000+0000","timeSecond":1608460199},"username":"awen","age":18.0}]