Spring Data Mongo(升至3.0.3配置)多数据源,SSL链接,实现无实体类映射主从读写分离

博客有个好处,就是可以在涨人气的同时当个备忘录用。

最近有个需求,有一个远程的mongo数据库,里面有好几个集合,需要每天定时增量更新到本地数据库,同时要保证数据的安全性,防止中途被抓包暴露。

实现思路就是多数据源,设置定时器,主读从写,然后使用SSL加密。然而以前mongo用的很少,就是一个简单的CRUD功能,所以一开始就遇到很多坑。

一、SpringBoot配置多数据源

首先在pom中导入依赖

<!-- mongodb -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

然后在application.properties中配置相关数据源

spring.data.mongodb.primary.host=远程数据库主机
spring.data.mongodb.primary.port=远程数据库端口
spring.data.mongodb.primary.database=远程数据库名称
spring.data.mongodb.primary.username=账号
spring.data.mongodb.primary.password=密码

spring.data.mongodb.secondary.host=127.0.0.1
spring.data.mongodb.secondary.port=27017
spring.data.mongodb.secondary.database=本地数据库名称
spring.data.mongodb.secondary.username=账号
spring.data.mongodb.secondary.password=密码

之后创建一个数据源抽象类

/*
    数据源抽象类
 */
@Data
public abstract class AbstractMongoConfig {
    private String host, database, username, password;
    private int port;

    public MongoDbFactory secMongoDbFactory() {
        String url = "mongodb://"+username+":"+password+"@"+host+":"+port+"/"+database;
        MongoClientURI uri = new MongoClientURI(url);
        return new SimpleMongoDbFactory(new MongoClient(uri),database);
    }

    public abstract MongoTemplate getMongoTemplate() throws Exception;

}

设置主从数据源,从application.properties中读取连接信息

/*
    配置远程数据库数据源
 */
@Configuration
@ConfigurationProperties(prefix = "spring.data.mongodb.primary")
public class PrimaryMongoConfig extends AbstractMongoConfig{

    @Primary
    @Override
    public @Bean(name = "primaryMongoTemplate") MongoTemplate getMongoTemplate(){
        return new MongoTemplate(priMongoDbFactory());
    }

}
/*
    配置本地数据库数据源
 */
@Configuration
@ConfigurationProperties(prefix = "spring.data.mongodb.secondary")
public class SecondaryMongoConfig extends  AbstractMongoConfig {

    @Override
    public @Bean(name = "secondaryMongoTemplate") MongoTemplate getMongoTemplate(){
        return new MongoTemplate(secMongoDbFactory());
    }

}

为了方式SpringBoot自动注入mongotemplate,还要在启动类上增加内容

@SpringBootApplication(exclude={MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) //排除自动注入mongoTemplate

二、使用多数据源

使用时,指明要使用哪个数据源就可以了,如要对远程数据库操作,就使用primaryMongoTemplate。

在对mongo进行操作的使用,也可以使用实体类映射,但是要加上@Document注解,如果属性名和字段名不同,那么要加上@Field注解,如

@Data
@Document("test") // 对应集合名
public class BackUpEntity {

    @Field("update_time") // 对应字段名
    private Long updateTime;

}

然而mongo中可能有很多的内嵌文档等,有些复杂的表很难建立实体类映射,但是mongo简单在,可以使用json类型数据进行操作,不需要考虑实体类构造,简化代码如下。

@Repository
public class CommonRepository {

    @Autowired
    @Qualifier(value = "primaryMongoTemplate")
    private MongoTemplate primaryMongoTemplate;

    @Autowired
    @Qualifier(value = "secondaryMongoTemplate")
    private MongoTemplate secondaryMongoTemplate;

    /*
        查询远程数据库数据
     */
    public JSONArray findSecondaryAll(String collectionName){
 
            JSONArray json = JSONArray.parseArray(JSON.toJSONString(primaryMongoTemplate.findAll(String.class,collectionName)));
            return json;
       
    }

     /*
        备份远程数据库数据到本地
     */
    public String backUpMongo(List<Object> list, String collectionName){
            
            secondaryMongoTemplate.insert(list,collectionName);
            return "备份集合"+collectionName+"成功";
   
    }
}

在本地数据库写入数据的时候要先将查询到的JSONArray数据转成List再传入

List<Object> list = JSONObject.parseArray(findJson.toJSONString(), Object.class);

再写入的时候遇到了一个坑,报错信息

Exception authenticating MongoCredential{mechanism=SCRAM-SHA-1, userName='root', source='ys_pbx_data_test', password=<hidden>, mechanismProperties=<hidden>};

这是因为本地安装mongo的时候,并没有生成对应的管理员用户,所以要对数据库先生成管理员,赋予权限,然后在配置文件中填入账号密码,没有的话就会报错。

 

 

之后编写service层和controller层,调用repository,传入collectionName就可以了。

三、配置MongoDB SSL

因为数据比较重要,所以要对其进行加密。mongo使用的是tcp传输,但是支持ssl加密。使用Wireshark进行抓包时,可以发现传输过程中的确都是明文。一开始理解错需求,使用了AES加密了接口返回数据,数据包还是明文的,不过也防止了查询接口直接暴露数据。

我的远程数据库是阿里云的,SSL配置可以参考:

官方文档:http://mongodb.github.io/mongo-java-driver/3.0/driver/reference/connecting/ssl/

阿里云:https://www.alibabacloud.com/help/zh/doc-detail/89245.htm?spm=a2c63.p38356.879954.6.5e4261d9OMoRgd#concept-v1g-vyv-y2b

https://www.alibabacloud.com/help/zh/doc-detail/89276.html

具体过程如下

第一步是改造远程数据库的数据源配置,新建一个配置类

@Configuration
public class MongoSSLConfig {

    @Bean
    public static MongoClient createNetworkMongoClient() {
        MongoCredential credentials = getCredentials();
        String host = "主机名";
        int port = "端口";
        List<ServerAddress> addrs = Collections.singletonList(new ServerAddress(host, port));
        System.setProperty("javax.net.ssl.trustStore","证书路径,注意使用jks文件");
        System.setProperty("javax.net.ssl.trustStorePassword","信任库密码");
        MongoClientOptions options = MongoClientOptions.builder()
                .sslEnabled(true) //开启SSL连接
                .sslInvalidHostNameAllowed(true) //不检查证书域名
                .build();
        return new MongoClient(addrs, credentials, options);
    }

    private static MongoCredential getCredentials() {
        String username = "用户名";
        String database = "数据库名";
        String pass = "密码";
        char[] password = pass.toCharArray();
        return MongoCredential.createCredential(username, database, password);
    }
}

修改 数据源抽象类 配置远程数据库新连接

public MongoDbFactory priMongoDbFactory() {
        MongoClient mongoClient = MongoSSLConfig.createNetworkMongoClient();
        return new SimpleMongoDbFactory(mongoClient,database);
    }

 在primaryMongoConfig中调用新方法

public @Bean(name = "primaryMongoTemplate") MongoTemplate getMongoTemplate(){
        return new MongoTemplate(priMongoDbFactory());
    }

第二步就是生成远程数据库的信任证书并下载到本地。

第三步将证书入本机信赖库,具体操作可以看官方文档,并将jks证书路径填入上面的代码中,如果使用pem等格式证书可能报错。

最后重启项目,可以正常运作,再次抓包,发现明文数据已经被加密。

三、Spring Data Mongo升级

spring data mongo 升级至了3.0.3版本,很多东西都被弃用了,相关方面文档,这边修改上文代码,即可重新配置数据源

直接连接数据库

import lombok.Data;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;


/*
 *   mongodb数据源抽象类
 */
@Data
public abstract class AbstractMongoConfig {

    private String host;
    private int port;

    private String database;

    private String username;
    private String  password;

    public MongoDatabaseFactory mongoDatabaseFactory() {
        String url = "mongodb://"+username+":"+password+"@"+host+":"+port+"/"+database;
        return new SimpleMongoClientDatabaseFactory(url);
    }


    public abstract MongoTemplate getMongoTemplate() throws Exception;

}

配置SSL连接

public MongoDatabaseFactory mongoDatabaseFactory() {
        MongoClient mongoClient = MongoSSLConfig.createNetworkMongoClient(host,database,username,password,port);
        return new SimpleMongoClientDatabaseFactory(mongoClient,database);
    }

同时需要改写MongoSSLConfig类

import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.yeastar.dataplatform.analyze.util.CommonUtil;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
/**
 * MongoSSL连接配置类
 * @author: liaoyuan
 **/
@Configuration
public class MongoSSLConfig {

    public static MongoClient createNetworkMongoClient(String host, String database, String username, String password, int port){

        // 传入证书
        System.setProperty("javax.net.ssl.trustStore", "证书位置");
        System.setProperty("javax.net.ssl.trustStorePassword","");

        MongoCredential credential = getCredentials(username, database, password);

        MongoClientSettings settings = MongoClientSettings.builder()
                .credential(credential)
                .applyToSslSettings(builder -> {
                    builder.enabled(true); // 开启ssl连接
                    builder.invalidHostNameAllowed(true); // 禁用主机名验证
                })
                .applyToClusterSettings(builder ->
                        builder.hosts(Arrays.asList(new ServerAddress(host, port))))
                .build();

        MongoClient mongoClient = MongoClients.create(settings);

        return mongoClient;
    }


    private static MongoCredential getCredentials(String username, String database, String pass) {
        char[] password = pass.toCharArray();
        return MongoCredential.createCredential(username, database, password);
    }


}

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Spring Data MongoDB是一个用于与MongoDB数据库进行交互的框架。它提供了一个简化和高效的方式来访问和操作MongoDB数据库,并使开发人员能够更容易地使用Spring框架来开发MongoDB应用程序。 Spring Data MongoDB的核心组件是MongoTemplate,它是一个线程安全的MongoDB操作模板类。通过MongoTemplate,我们可以进行诸如查询、插入、更新和删除等常见的数据库操作。 使用MongoTemplate,我们可以使用MongoDB的查询语言来进行数据库查询。通过构建一个查询对象,我们可以指定要查询的集合、查询的条件和排序等。除了基本的查询外,MongoTemplate还提供了一些更高级的查询方法,如聚合查询、分页查询和地理位置查询等。 对于插入、更新和删除操作,MongoTemplate提供了各种方法来执行这些操作。我们可以使用save()方法来插入或更新一个文档,使用delete()方法来删除一个或多个文档,并使用update()方法来更新一个或多个文档的值。 除了基本的操作外,MongoTemplate还提供了一些其他功能,如文档映射、索引管理和事务支持等。我们可以通过配置注解来定义文档和集合之间的映射关系,通过索引注解来定义索引,以提高查询性能。此外,Spring Data MongoDB还提供了对事务管理的支持,以确保在多个操作之间的一致性。 总之,Spring Data MongoDB是一个强大而灵活的框架,它为开发人员提供了一套简化和高效的API,用于与MongoDB数据库进行交互。通过MongoTemplate,我们可以轻松地进行查询、插入、更新和删除等常见的数据库操作,并享受到Spring框架的许多好处。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值