背景
用户自定义设置数据库路由
Spring boot提供了AbstractRoutingDataSource根据用户定义的规则选择当前的数据库,这样我们可以在执行查询之前,设置读取从库,在执行完成后,恢复到主库。
实现可动态路由的数据源,在每次数据库查询操作前执行
ReadWriteSplitRoutingDataSource.java
				?
			
| 
								1
 
								2
 
								3
 
								4
 
								5
 
								6
 
								7
 
								8
 
								9
 
								10
 
								11
 
								12
						 | importorg.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/*** @author songrgg* @since 1.0*/publicclassReadWriteSplitRoutingDataSource extendsAbstractRoutingDataSource {@OverrideprotectedObject determineCurrentLookupKey() {returnDbContextHolder.getDbType();}} | 
线程私有路由配置,用于ReadWriteSplitRoutingDataSource动态读取配置
DbContextHolder.java
				?
			
| 
								1
 
								2
 
								3
 
								4
 
								5
 
								6
 
								7
 
								8
 
								9
 
								10
 
								11
 
								12
 
								13
 
								14
 
								15
 
								16
 
								17
 
								18
 
								19
 
								20
 
								21
 
								22
 
								23
 
								24
 
								25
 
								26
 
								27
						 | /*** @author songrgg* @since 1.0*/publicclassDbContextHolder {publicenumDbType {MASTER,SLAVE}privatestaticfinalThreadLocal<DbType> contextHolder = newThreadLocal<>();publicstaticvoidsetDbType(DbType dbType) {if(dbType == null){thrownewNullPointerException();}contextHolder.set(dbType);}publicstaticDbType getDbType() {returncontextHolder.get() == null? DbType.MASTER : contextHolder.get();}publicstaticvoidclearDbType() {contextHolder.remove();}} | 
AOP优化代码
利用AOP将设置数据库的操作从代码中抽离,这里的粒度控制在方法级别,所以利用注解的形式标注这个方法涉及的数据库事务只读,走从库。
只读注解,用于标注方法的数据库操作只走从库。
ReadOnlyConnection.java
				?
			
| 
								1
 
								2
 
								3
 
								4
 
								5
 
								6
 
								7
 
								8
 
								9
 
								10
 
								11
 
								12
 
								13
 
								14
 
								15
 
								16
 
								17
						 | packagecom.wallstreetcn.hatano.config;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;/*** Indicates the database operations is bound to the slave database.* AOP interceptor will set the database to the slave with this interface.* @author songrgg* @since 1.0*/@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public@interfaceReadOnlyConnection {} | 
ReadOnlyConnectionInterceptor.java
				?
			
| 
								1
 
								2
 
								3
 
								4
 
								5
 
								6
 
								7
 
								8
 
								9
 
								10
 
								11
 
								12
 
								13
 
								14
 
								15
 
								16
 
								17
 
								18
 
								19
 
								20
 
								21
 
								22
 
								23
 
								24
 
								25
 
								26
 
								27
 
								28
 
								29
 
								30
 
								31
 
								32
 
								33
 
								34
 
								35
 
								36
 
								37
 
								38
						 | importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.core.Ordered;importorg.springframework.stereotype.Component;/*** Intercept the database operations, bind database to read-only database as this annotation* is applied.* @author songrgg* @since 1.0*/@Aspect@ComponentpublicclassReadOnlyConnectionInterceptor implementsOrdered {privatestaticfinalLogger logger = LoggerFactory.getLogger(ReadOnlyConnectionInterceptor.class);@Around("@annotation(readOnlyConnection)")publicObject proceed(ProceedingJoinPoint proceedingJoinPoint, ReadOnlyConnection readOnlyConnection) throwsThrowable {try{logger.info("set database connection to read only");DbContextHolder.setDbType(DbContextHolder.DbType.SLAVE);Object result = proceedingJoinPoint.proceed();returnresult;} finally{DbContextHolder.clearDbType();logger.info("restore database connection");}}@OverridepublicintgetOrder() {return0;}} | 
UserService.java
				?
			
                	
    
	
	
		
		
	
 
	
		
			
	
	 
     
	
			
                 
			
		
		
			
			
			
    
        
        
	
			
						
			
            			
    		
    		
		
	    
    	
    	
        
    	
    
| 
								1
 
								2
 
								3
 
								4
						 | @ReadOnlyConnectionpublicList<User> getUsers(Integer page, Integer limit) {returnrepository.findAll(newPageRequest(page, limit));} | 
配置Druid数据库连接池
build.gradle
compile("com.alibaba:druid:1.0.18")
groovy依赖注入
配置dataSource为可路由数据源
context.groovy
				?
			
	
						
						
						
						
						
						
						
																		
    
        
    
        
                        
                
                    
                
                
                
                    
                
                
                
                    
                
                
                
                    
                
                        
    
 																		
						
																		
    
        
 												
						
																		
	
	
		
				
			
																		
						
						
					
				
				                | 
								1
 
								2
 
								3
 
								4
 
								5
 
								6
 
								7
 
								8
 
								9
 
								10
 
								11
 
								12
 
								13
 
								14
 
								15
 
								16
 
								17
 
								18
 
								19
 
								20
 
								21
 
								22
 
								23
 
								24
						 | importcom.alibaba.druid.pool.DruidDataSourceimportDbContextHolderimportReadWriteSplitRoutingDataSource** SOME INITIALIZED CODE LOAD PROPERTIES **def dataSourceMaster = newDruidDataSource()dataSourceMaster.url = properties.get('datasource.master.url')println("master set to "+ dataSourceMaster.url)dataSourceMaster.username = properties.get('datasource.master.username')dataSourceMaster.password = properties.get('datasource.master.password')def dataSourceSlave = newDruidDataSource()dataSourceSlave.url = properties.get('datasource.slave.url')println("slave set to "+ dataSourceSlave.url)dataSourceSlave.username = properties.get('datasource.slave.username')dataSourceSlave.password = properties.get('datasource.slave.password') beans {dataSource(ReadWriteSplitRoutingDataSource) { bean ->targetDataSources = [(DbContextHolder.DbType.MASTER): dataSourceMaster,(DbContextHolder.DbType.SLAVE): dataSourceSlave]}} | 
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。
原文链接:http://www.cnblogs.com/pier2/p/spring-boot-read-write-split.html
相关文章
             猜你喜欢
        
        - 个人网站服务器域名解析设置指南:从购买到绑定全流程 2025-06-10
- 个人网站搭建:如何挑选具有弹性扩展能力的服务器? 2025-06-10
- 个人服务器网站搭建:如何选择适合自己的建站程序或框架? 2025-06-10
- 64M VPS建站:能否支持高流量网站运行? 2025-06-10
- 64M VPS建站:怎样选择合适的域名和SSL证书? 2025-06-10
			TA的动态
			
		
				- 2025-07-10 怎样使用阿里云的安全工具进行服务器漏洞扫描和修复?
- 2025-07-10 怎样使用命令行工具优化Linux云服务器的Ping性能?
- 2025-07-10 怎样使用Xshell连接华为云服务器,实现高效远程管理?
- 2025-07-10 怎样利用云服务器D盘搭建稳定、高效的网站托管环境?
- 2025-07-10 怎样使用阿里云的安全组功能来增强服务器防火墙的安全性?
快网idc优惠网
QQ交流群
				您的支持,是我们最大的动力!				
			
		
        热门文章
        
    
    - 
            2025-05-27 95
- 
            2025-05-29 81
- 
            2025-05-27 74
- 
            2025-05-29 99
- 
            2025-05-29 60
		热门评论
	
	 
        
 
    		 
            	 
															 
         
         
        
 
                        