springboot集成mongodb实现动态切换数据源
<p>主要实现原理,利用spring的aop 在切入点执行db操作之前 将数据库切换:</p><p>本例子采用aop在controller进行拦截 拦截到MongoTemplate.class 切换数据源后重新放回去 ,处理完成后将相关数据源的template删除</p>
<p> </p>
<p>引入mongodb相关依赖</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>org.springframework.boot<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>spring-boot-starter-data-mongodb<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">引入AOP依赖</span><span style="color: rgba(0, 128, 0, 1)">--></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>org.springframework.boot<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>spring-boot-starter-aop<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<pre>多数据源MultiMongoTemplate</pre>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> com.mongodb.client.MongoDatabase;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.Logger;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.LoggerFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.data.mongodb.MongoDbFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.data.mongodb.core.MongoTemplate;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MultiMongoTemplate <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> MongoTemplate {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> Logger logger= LoggerFactory.getLogger(MultiMongoTemplate.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">用来缓存当前MongoDbFactory</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> ThreadLocal<MongoDbFactory><span style="color: rgba(0, 0, 0, 1)"> mongoDbFactoryThreadLocal;
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> MultiMongoTemplate(MongoDbFactory mongoDbFactory){
</span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(mongoDbFactory);
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(mongoDbFactoryThreadLocal==<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
mongoDbFactoryThreadLocal </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> ThreadLocal<><span style="color: rgba(0, 0, 0, 1)">();
}
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setMongoDbFactory(MongoDbFactory factory){
mongoDbFactoryThreadLocal.set(factory);
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> removeMongoDbFactory(){
mongoDbFactoryThreadLocal.remove();
}
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> MongoDatabase getDb() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> mongoDbFactoryThreadLocal.get().getDb();
}
}</span></pre>
</div>
<p>aop 切片类MongoSwitch</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> cn.net.topnet.topfs.dynamicdb.MultiMongoTemplate;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> com.mongodb.MongoClient;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.aspectj.lang.ProceedingJoinPoint;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.aspectj.lang.annotation.Around;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.aspectj.lang.annotation.Aspect;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.aspectj.lang.annotation.Pointcut;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.Logger;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.LoggerFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.beans.factory.annotation.Autowired;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.beans.factory.annotation.Value;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.data.mongodb.MongoDbFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.data.mongodb.core.MongoTemplate;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.data.mongodb.core.SimpleMongoClientDbFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.data.mongodb.core.SimpleMongoDbFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.stereotype.Component;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.web.context.request.RequestContextHolder;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.springframework.web.context.request.ServletRequestAttributes;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> javax.servlet.http.HttpServletRequest;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.lang.reflect.Field;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.HashMap;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Map;
@Component
@Aspect
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MongoSwitch {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">final</span> Logger logger = LoggerFactory.getLogger(MongoSwitch.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
@Autowired
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> MongoDbFactory mongoDbFactory;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> Map<String,MongoDbFactory> templateMuliteMap=<span style="color: rgba(0, 0, 255, 1)">new</span> HashMap<><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取配置文件的副本集连接</span>
@Value("${spring.data.mongodb.uri}"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String uri;
@Pointcut(</span>"execution(* cn.net.topnet.topfs.controller..*.*(..))"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> routeMongoDB() {
}
@Around(</span>"routeMongoDB()"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Object routeMongoDB(ProceedingJoinPoint joinPoint) {
Object result </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
HttpServletRequest request </span>=<span style="color: rgba(0, 0, 0, 1)"> ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取需要访问的项目数据库</span>
String dbName = request.getRequestURI().trim().substring(1<span style="color: rgba(0, 0, 0, 1)">);
String name </span>=<span style="color: rgba(0, 0, 0, 1)"> joinPoint.getSignature().getName();
Object o </span>=<span style="color: rgba(0, 0, 0, 1)"> joinPoint.getTarget();
Field[] fields </span>=<span style="color: rgba(0, 0, 0, 1)"> o.getClass().getDeclaredFields();
MultiMongoTemplate mongoTemplate </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (Field field : fields) {
field.setAccessible(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
Object fieldObject </span>=<span style="color: rgba(0, 0, 0, 1)"> field.get(o);
Class fieldclass </span>=<span style="color: rgba(0, 0, 0, 1)"> fieldObject.getClass();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">找到Template的变量</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (fieldclass == MongoTemplate.<span style="color: rgba(0, 0, 255, 1)">class</span> || fieldclass == MultiMongoTemplate.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查找项目对应的MongFactory</span>
SimpleMongoClientDbFactory simpleMongoClientDbFactory=<span style="color: rgba(0, 0, 0, 1)">(SimpleMongoClientDbFactory)templateMuliteMap.get(dbName);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">实例化</span>
<span style="color: rgba(0, 0, 255, 1)">if</span>(simpleMongoClientDbFactory==<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){<br> <span style="color: rgba(153, 204, 0, 1)"> //替换数据源</span>
simpleMongoClientDbFactory </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> SimpleMongoClientDbFactory(<span style="color: rgba(0, 0, 255, 1)">this</span>.uri.replace("#"<span style="color: rgba(0, 0, 0, 1)">,dbName));
templateMuliteMap.put(dbName,simpleMongoClientDbFactory);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果第一次,赋值成自定义的MongoTemplate子类</span>
<span style="color: rgba(0, 0, 255, 1)">if</span>(fieldclass==MongoTemplate.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">){
mongoTemplate </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MultiMongoTemplate(simpleMongoClientDbFactory);
}</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span>(fieldclass==MultiMongoTemplate.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">){
mongoTemplate</span>=<span style="color: rgba(0, 0, 0, 1)">(MultiMongoTemplate)fieldObject;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置MongoFactory</span>
<span style="color: rgba(0, 0, 0, 1)"> mongoTemplate.setMongoDbFactory(simpleMongoClientDbFactory);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">重新赋值</span>
<span style="color: rgba(0, 0, 0, 1)"> field.set(o, mongoTemplate);
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
result </span>=<span style="color: rgba(0, 0, 0, 1)"> joinPoint.proceed();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">清理ThreadLocal的变量</span>
<span style="color: rgba(0, 0, 0, 1)"> mongoTemplate.removeMongoDbFactory();
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Throwable t) {
logger.error(</span>""<span style="color: rgba(0, 0, 0, 1)">, t);
}
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
logger.error(</span>""<span style="color: rgba(0, 0, 0, 1)">, e);
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> result;
}
}</span></pre>
</div>
<p>yml配置</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">spring:
data:
mongodb:
uri: mongodb:</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">bobo:bobo123@192.168.3.114:27017,192.168.3.114:27018,192.168.3.114:27019/#?connect=replicaSet&slaveOk=true&replicaSet=myrs</span></pre>
</div>
<p>测试controller</p>
<div class="cnblogs_code">
<pre> @GetMapping("/{dbName}"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 255, 1)">void</span> testMongoTemplate(@PathVariable("dbName"<span style="color: rgba(0, 0, 0, 1)">) String dbName){
Query query </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Query();
query.addCriteria(Criteria.where(</span>"display").is("测试"<span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> spring会将查询到的结果自动映射</span>
Domains one = mongoTemplate.findOne(query, Domains.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
System.out.println(one);
}</span></pre>
</div>
<p> </p><br><br>
来源:https://www.cnblogs.com/jiawen010/p/12664494.html
頁:
[1]