Spring boot AOP 配置MongoDB多数据源


    org.springframework.boot
    spring-boot-starter-data-mongodb
    2.7.7

1、首先配置application.yml

spring:
  data:
   # 默认用户mongodb库
   mongodb:
     user-mongo:
       host: 192.168.1.2
       port: 27017
       username: root
       password: root
       database: user
     # 订单mongodb库
     order-mongo:
       host: 192.168.1.3
       port: 27017
       username: root
       password: root
       database: order

2、配置连接参数信息Properties

package com.ruoyi.framework.config.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties
public class MongoDBSourceProperties {
    private String host;
    private Integer port;
    private String username;
    private String password;
    private String database;
}

3、配置Config文件

package com.ruoyi.framework.config;


import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.ruoyi.framework.config.properties.MongoDBSourceProperties;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Configuration
@Component
public class MongoDBSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.data.mongodb.user-mongo")
    public MongoDBSourceProperties userMongodbProperties() {
        return new MongoDBSourceProperties();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.data.mongodb.order-mongo")
    public MongoDBSourceProperties orderMongodbProperties() {
        return new MongoDBSourceProperties();
    }


    /**
     * 用户Mongodb
     */
    @Bean
    @Primary
    @Qualifier("userMongoTemplate")
    public MongoTemplate userMongoTemplate(@Qualifier("userMongodbProperties") MongoDBSourceProperties mongodbUserProperties) {
        return mongoClient(mongodbUserProperties);
    }

    /**
     * 订单Mongodb
     */
    @Bean
    @Qualifier("orderMongoTemplate")
    public MongoTemplate orderMongoTemplate(@Qualifier("orderMongodbProperties") MongoDBSourceProperties mongodbOrderProperties) {
       return mongoClient(mongodbOrderProperties);
    }

    private MongoTemplate mongoClient(MongoDBSourceProperties properties){
        MongoCredential credential = MongoCredential.createCredential(properties.getUsername(), properties.getDatabase(), properties.getPassword().toCharArray());

        MongoClientSettings settings = MongoClientSettings.builder().credential(credential)
                .applyToClusterSettings(builder ->
                        builder.hosts(Arrays.asList(new ServerAddress(properties.getHost(), properties.getPort()))))
                .build();
        MongoClient mongoClient = MongoClients.create(settings);
        return new MongoTemplate(mongoClient, properties.getDatabase());
    }

}

 4、创建自定义注解MongoDBSource

package com.ruoyi.common.annotation;

import java.lang.annotation.*;


@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MongoDBSource {
    /**
     * 切换数据源名称
     */
    public String value() default "";
}

5、创建ContextHolder

package com.ruoyi.framework.datasource;

import com.alibaba.ttl.TransmittableThreadLocal;
import org.springframework.data.mongodb.core.MongoTemplate;

public class DynamicMongoDBContextHolder {

    private static final TransmittableThreadLocal contextHolder = new TransmittableThreadLocal<>();

    public static void setMongoDB(MongoTemplate mongoTemplate) {
        contextHolder.set(mongoTemplate);
    }

    /**
     * 获取数据源名
     */
    public static MongoTemplate getMongoDB() {
        return (contextHolder.get());
    }

    public static void removeMongoDB() {
        contextHolder.remove();
    }
}

6、创建AOP切面

package com.ruoyi.framework.aspectj;

import com.ruoyi.common.annotation.MongoDBSource;
import com.ruoyi.framework.datasource.DynamicMongoDBContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

import java.util.Objects;

@Aspect
@Order(1)
@Component
public class MongoDBSourceAspect implements ApplicationContextAware {
    protected Logger logger = LoggerFactory.getLogger(getClass());

    private ApplicationContext applicationContext;

    @Pointcut("@annotation(com.ruoyi.common.annotation.MongoDBSource)"
            + "|| @within(com.ruoyi.common.annotation.MongoDBSource)")
    public void mongoDBSourcePointCut() {

    }

    @Around("mongoDBSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        try {
            MongoDBSource dataSource = getMongoDBSource(point);
            if (null == dataSource) {
                logger.error("获取mongodb数据源失败---------");
                throw new RuntimeException();
            }
            String value = dataSource.value();
            MongoTemplate template = applicationContext.getBean(value, MongoTemplate.class);
            DynamicMongoDBContextHolder.setMongoDB(template);
            logger.info("切换到mongodb数据源,{}", value);
            return point.proceed();
        } catch (Exception e) {
            logger.error("获取mongodb数据源异常---------" + e.getMessage());
            throw new RuntimeException();
        } finally {
            DynamicMongoDBContextHolder.removeMongoDB();
        }
    }

    private MongoDBSource getMongoDBSource(ProceedingJoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        MongoDBSource mongoDBSource = AnnotationUtils.findAnnotation(signature.getMethod(), MongoDBSource.class);
        if (Objects.nonNull(mongoDBSource)) {
            return mongoDBSource;
        }
        return null;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

7、创建MongoDB模版

package com.ruoyi.framework.cache;

import com.ruoyi.framework.datasource.DynamicMongoDBContextHolder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;

import java.util.List;

@SuppressWarnings(value = {"unchecked", "rawtypes"})
@Component
public class MongoDBSourceCache {

    private final MongoTemplate templateMongodb;

    //默认读取用户MongoDB库
    public MongoDBSourceCache(@Qualifier("userMongoTemplate") MongoTemplate template) {
        this.templateMongodb = template;
    }


    private MongoTemplate getTemplateMongodb() {
        MongoTemplate template = DynamicMongoDBContextHolder.getMongoDB();
        if (null == template) {
            DynamicMongoDBContextHolder.setMongoDB(templateMongodb);
            return templateMongodb;
        }
        return template;
    }

    /**
     * 根据条件查询出指定数据
     */
    public  T findById(Object id, Class entityClass) {
        return getTemplateMongodb().findById(id,entityClass);
    }

    /**
     * 指定集合 根据条件查询出符合的第一条数据
     */
    public  T findById(Object id, Class entityClass, String collectionName){
        return getTemplateMongodb().findById(id,entityClass,collectionName);
    }

    /**
     * 对数据进行聚合操作
     */
    public  AggregationResults aggregate(Aggregation aggregation, String collectionName, Class outputType) {
        return getTemplateMongodb().aggregate(aggregation, collectionName, outputType);
    }

    /**
     * 根据条件查询出符合的第一条数据
     */
    public  T findOne(Query query, Class entityClass) {
        return getTemplateMongodb().findOne(query, entityClass);
    }

    /**
     * 指定集合 根据条件查询出符合的第一条数据
     */
    public  T findOne(Query query, Class entityClass, String collectionName){
        return getTemplateMongodb().findOne(query, entityClass,collectionName);
    }

    /**
     * 根据条件查询出所有结果集
     */
    public  List find(Query query, Class entityClass) {
        return getTemplateMongodb().find(query, entityClass);
    }

    /**
     * 指定集合 根据条件查询出所有结果集
     */
    public  List find(Query query, Class entityClass, String collectionName){
        return getTemplateMongodb().find(query, entityClass,collectionName);
    }

}

8、调用@MongoDBSource

(1)@Autowired注入

    @Autowired
    private MongoDBSourceCache mongoDBSourceCache;

    @Override
    @MongoDBSource("userMongoTemplate")
    public SysUserMongoDB selectUserById()
    {
        SysUserMongoDB sysUser = mongoDBSourceCache.findById("63f4d5f15d99ae37e27c397b", SysUserMongoDB.class);
        return sysUser;
    }

(2)构造器注入

    //在需要使用多数据源构造器上添加@Qualifier,其中value用来表示数据源
    private final MongoDBSourceCache mongoDBSourceCache;
    public OrderMongoMapperImpl(@Qualifier("userMongoTemplate")MongoDBSourceCache mongoDBSourceCache) {
        this.mongoDBSourceCache= mongoDBSourceCache;
        }

仅供参考,希望对您有所帮助,感谢阅读。


注:本文章,是从各大网站、各位道友以及老师等处学习,自己总结做的一些笔记,不对的地方望海涵,如有问题,请及时联系。

你可能感兴趣的:(学习笔记,mongodb,spring,boot,database,java,后端)