自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

SpringBoot讀寫分離組件開(kāi)發(fā)詳解

開(kāi)發(fā) 前端
本篇詳細(xì)介紹關(guān)于SpringBoot讀寫分離組件開(kāi)發(fā)的相關(guān)內(nèi)容,一寫多讀,讀可以任意配置多個(gè),默認(rèn)都是從寫庫(kù)中進(jìn)行操作,只有符合條件的方法(指定的目標(biāo)方法或者標(biāo)有指定注解的方法才會(huì)從讀庫(kù)中操作)。獨(dú)立打成一個(gè)jar包放入本地倉(cāng)庫(kù)。

[[389704]]

環(huán)境:springboot2.2.6RELEASE

實(shí)現(xiàn)目標(biāo):一寫多讀,讀可以任意配置多個(gè),默認(rèn)都是從寫庫(kù)中進(jìn)行操作,只有符合條件的方法(指定的目標(biāo)方法或者標(biāo)有指定注解的方法才會(huì)從讀庫(kù)中操作)。獨(dú)立打成一個(gè)jar包放入本地倉(cāng)庫(kù)。

實(shí)現(xiàn)原理:通過(guò)aop。

1.pom.xml配置文件

  1. <dependency> 
  2.             <groupId>org.springframework.boot</groupId> 
  3.             <artifactId>spring-boot-starter</artifactId> 
  4. </dependency> 
  5. <dependency> 
  6.             <groupId>org.springframework.boot</groupId> 
  7.             <artifactId>spring-boot-starter-data-jpa</artifactId> 
  8. </dependency> 
  9. <dependency> 
  10.             <groupId>org.springframework.boot</groupId> 
  11.             <artifactId>spring-boot-configuration-processor</artifactId> 
  12.             <optional>true</optional> 
  13. </dependency> 

 2.application.yml配置文件

  1. pack: 
  2.   datasource: 
  3.     pointcut: execution(public * net.greatsoft.service.base.*.*(..)) || execution(public * net.greatsoft.service.xxx.*.*(..)) 
  4.     master: 
  5.       driverClassName: oracle.jdbc.driver.OracleDriver 
  6.       jdbcUrl: jdbc:oracle:thin:@10.100.102.113:1521/orcl 
  7.       username: test 
  8.       password: test 
  9.       minimumIdle: 10 
  10.       maximumPoolSize: 200 
  11.       autoCommit: true 
  12.       idleTimeout: 30000 
  13.       poolName: MbookHikariCP 
  14.       maxLifetime: 1800000 
  15.       connectionTimeout: 30000 
  16.       connectionTestQuery: SELECT 1 FROM DUAL   
  17.     slaves: 
  18.       - driverClassName: oracle.jdbc.driver.OracleDriver 
  19.         jdbcUrl: jdbc:oracle:thin:@10.100.102.113:1521/orcl 
  20.         username: dc 
  21.         password: dc 
  22.         minimumIdle: 10 
  23.         maximumPoolSize: 200 
  24.         autoCommit: true 
  25.         idleTimeout: 30000 
  26.         poolName: MbookHikariCP 
  27.         maxLifetime: 1800000 
  28.         connectionTimeout: 30000 
  29.         connectionTestQuery: SELECT 1 FROM DUAL 
  30.       - driverClassName: oracle.jdbc.driver.OracleDriver 
  31.         jdbcUrl: jdbc:oracle:thin:@10.100.102.113:1521/orcl 
  32.         username: empi 
  33.         password: empi 
  34.         minimumIdle: 10 
  35.         maximumPoolSize: 200 
  36.         autoCommit: true 
  37.         idleTimeout: 30000 
  38.         poolName: MbookHikariCP 
  39.         maxLifetime: 1800000 
  40.         connectionTimeout: 30000 
  41.         connectionTestQuery: SELECT 1 FROM DUAL 

 pointcut:定義切點(diǎn),那些方法是需要攔截(從讀庫(kù)中操作)。

master:寫庫(kù)配置。

slaves:讀庫(kù)配置(List集合)。

3.屬性配置類

  1. @Component 
  2. @ConfigurationProperties(prefix = "pack.datasource"
  3. public class RWDataSourceProperties { 
  4.      
  5.     private String pointcut ; 
  6.     private HikariConfig master ; 
  7.     private List<HikariConfig> slaves = new ArrayList<>(); 
  8.      

 4.讀寫配置類

  1. public class RWConfig  { 
  2.      
  3.     private static Logger logger = LoggerFactory.getLogger(RWConfig.class) ; 
  4.  
  5.     @Bean 
  6.     public HikariDataSource masterDataSource(RWDataSourceProperties rwDataSourceProperties) { 
  7.         return new HikariDataSource(rwDataSourceProperties.getMaster()) ; 
  8.     } 
  9.      
  10.     @Bean 
  11.     public List<HikariDataSource> slaveDataSources(RWDataSourceProperties rwDataSourceProperties) { 
  12.         List<HikariDataSource> lists = new ArrayList<>() ; 
  13.         for(HikariConfig config : rwDataSourceProperties.getSlaves()) { 
  14.             lists.add(new HikariDataSource(config)) ; 
  15.         } 
  16.         return lists ; 
  17.     } 
  18.      
  19.     @Bean 
  20.   @Primary 
  21.     @DependsOn({"masterDataSource""slaveDataSources"}) 
  22.     public AbstractRoutingDataSource routingDataSource(@Qualifier("masterDataSource")DataSource masterDataSource, 
  23.             @Qualifier("slaveDataSources")List<HikariDataSource> slaveDataSources) { 
  24.         BaseRoutingDataSource ds = new BaseRoutingDataSource() ; 
  25.         Map<Object, Object> targetDataSources = new HashMap<>(2) ; 
  26.         targetDataSources.put("master", masterDataSource) ; 
  27.         for (int i = 0; i < slaveDataSources.size(); i++) { 
  28.             targetDataSources.put("slave-" + i, slaveDataSources.get(i)) ; 
  29.         } 
  30.         ds.setDefaultTargetDataSource(masterDataSource) ; 
  31.         ds.setTargetDataSources(targetDataSources) ; 
  32.         return ds ; 
  33.     } 
  34.      

 5.數(shù)據(jù)源路由

  1. public class BaseRoutingDataSource extends AbstractRoutingDataSource { 
  2.  
  3.     @Resource 
  4.     private DataSourceHolder holder; 
  5.      
  6.     @Override 
  7.     protected Object determineCurrentLookupKey() { 
  8.         return holder.get() ; 
  9.     } 
  10.      

  1. public class DataSourceHolder { 
  2.      
  3.     private ThreadLocal<Integer> context = new ThreadLocal<Integer>() { 
  4.         @Override 
  5.         protected Integer initialValue() { 
  6.             return 0 ; 
  7.         } 
  8.     }; 
  9.      
  10.     @Resource 
  11.     private BaseSlaveLoad slaveLoad ; 
  12.      
  13.     public String get() { 
  14.         Integer type = context.get() ; 
  15.         return type == null || type == 0 ? "master" : "slave-" + slaveLoad.load() ; 
  16.     } 
  17.      
  18.     public void set(Integer type) { 
  19.         context.set(type) ; 
  20.     } 
  21.      

 通過(guò)aop動(dòng)態(tài)設(shè)置context的內(nèi)容值,0為從寫庫(kù)中操作,其它的都在讀庫(kù)中操作。

BaseSlaveLoad類為到底從那個(gè)讀庫(kù)中選取的一個(gè)算法類,默認(rèn)實(shí)現(xiàn)使用的是輪詢算法。

  1. public interface BaseSlaveLoad { 
  2.  
  3.     int load() ; 
  4.      

  1. public abstract class AbstractSlaveLoad implements BaseSlaveLoad { 
  2.  
  3.     @Resource 
  4.     protected List<HikariDataSource> slaveDataSources ; 
  5.      

 這里定義一個(gè)抽象類注入了讀庫(kù)列表,所有的實(shí)現(xiàn)類從該類中繼承即可。

  1. public class PollingLoad extends AbstractSlaveLoad { 
  2.      
  3.     private int index = 0 ; 
  4.     private int size = 1 ; 
  5.      
  6.     @PostConstruct 
  7.     public void init() { 
  8.         size = slaveDataSources.size() ; 
  9.     } 
  10.      
  11.     @Override 
  12.     public int load() { 
  13.         int n = index ; 
  14.         synchronized (this) { 
  15.             index = (++index) % size ; 
  16.         } 
  17.         return n ; 
  18.     } 
  19.      

 配置成Bean

  1. @Bean 
  2.     @ConditionalOnMissingBean 
  3.     public BaseSlaveLoad slaveLoad() { 
  4.         return new PollingLoad() ; 
  5.     } 
  6.      
  7.     @Bean 
  8.     public DataSourceHolder dataSourceHolder() { 
  9.         return new DataSourceHolder() ; 
  10.     } 

 6.數(shù)據(jù)源AOP

  1. public class DataSourceAspect implements MethodInterceptor { 
  2.  
  3.     private DataSourceHolder holder ; 
  4.      
  5.     public DataSourceAspect(DataSourceHolder holder) { 
  6.         this.holder = holder ; 
  7.     } 
  8.      
  9.     @Override 
  10.     public Object invoke(MethodInvocation invocation) throws Throwable { 
  11.         Method method = invocation.getMethod() ; 
  12.         String methodName = method.getName() ; 
  13.         SlaveDB slaveDB = method.getAnnotation(SlaveDB.class) ; 
  14.         if (slaveDB == null) { 
  15.             slaveDB = method.getDeclaringClass().getAnnotation(SlaveDB.class) ; 
  16.         } 
  17.         if (methodName.startsWith("find")  
  18.                 || methodName.startsWith("get"
  19.                 || methodName.startsWith("query"
  20.                 || methodName.startsWith("select"
  21.                 || methodName.startsWith("list"
  22.                 || slaveDB != null) { 
  23.             holder.set(1) ; 
  24.         } else { 
  25.             holder.set(0) ; 
  26.         } 
  27.         return invocation.proceed(); 
  28.     } 
  29.  

 應(yīng)該切點(diǎn)需要?jiǎng)討B(tài)配置,所以這里采用spring aop的方式來(lái)配置

  1. @Bean 
  2.     public AspectJExpressionPointcutAdvisor logAdvisor(RWDataSourceProperties props, DataSourceHolder holder) { 
  3.         AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor() ; 
  4.         logger.info("執(zhí)行表達(dá)式:{}", props.getPointcut()) ; 
  5.         advisor.setExpression(props.getPointcut()) ; 
  6.         advisor.setAdvice(new DataSourceAspect(holder)) ; 
  7.         return advisor ; 
  8.     } 

 7.Enable開(kāi)啟功能

  1. public class RWImportSelector implements ImportSelector { 
  2.  
  3.     @Override 
  4.     public String[] selectImports(AnnotationMetadata importingClassMetadata) { 
  5.         return new String[] {RWConfig.class.getName()} ; 
  6.     } 
  7.  

 這里的RWConfig為我們上面的配置類

  1. @Retention(RetentionPolicy.RUNTIME) 
  2. @Target(ElementType.TYPE) 
  3. @Documented 
  4. @Import({RWImportSelector.class}) 
  5. public @interface EnableRW { 

  1. @Documented 
  2. @Retention(RUNTIME) 
  3. @Target({ TYPE, METHOD }) 
  4. public @interface SlaveDB { 

 有@SlaveDB的注解方法會(huì)類都會(huì)從讀庫(kù)中操作。

到此讀寫分離組件開(kāi)發(fā)完成。

8.打包安裝到本地倉(cāng)庫(kù)

  1. mvn install -Dmaven.test.skip=true 

9.新建base-web項(xiàng)目

引入依賴

  1. <dependency> 
  2.             <groupId>com.pack</groupId> 
  3.             <artifactId>xg-component-rw</artifactId> 
  4.             <version>1.0.0</version> 
  5. </dependency> 

 啟動(dòng)類添加注解開(kāi)啟讀寫分離功能

  1. @SpringBootApplication 
  2. @EnableRW 
  3. public class BaseWebApplication { 
  4.  
  5.     public static void main(String[] args) { 
  6.         SpringApplication.run(BaseWebApplication.class, args); 
  7.     } 
  8.  

 測(cè)試:

第一次查詢:

第二次查詢:

為了區(qū)別兩個(gè)從庫(kù)設(shè)置不同的數(shù)據(jù)

這里是寫庫(kù)

完畢!?。?/p>

 

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2023-07-07 08:36:45

配置注解jar

2020-04-23 15:08:41

SpringBootMyCatJava

2021-06-25 10:05:58

SpringBootMySQL數(shù)據(jù)庫(kù)

2024-05-31 13:34:57

2011-08-30 12:49:59

Mysql ProxyLua分離

2019-09-30 09:19:54

Redis分離云數(shù)據(jù)庫(kù)

2011-08-22 12:01:38

iPhone開(kāi)發(fā)文件

2018-10-16 16:45:05

數(shù)據(jù)庫(kù)讀寫分離

2011-08-10 16:27:07

Cocoa TouchPlist

2009-04-10 09:06:16

Windows Emb

2017-05-25 10:22:13

NoSQL數(shù)據(jù)庫(kù)主主備份

2022-04-25 08:03:57

MySQL中間件MyCat

2009-05-04 09:13:52

PHPMySQL讀寫分離

2017-09-04 09:53:58

MySQLAtlasNavicat

2018-01-01 05:23:13

服務(wù)化讀寫分離架構(gòu)

2010-05-17 11:19:44

MySQL proxy

2009-09-16 13:05:32

C#組件開(kāi)發(fā)

2020-02-28 19:06:21

緩存讀寫Redis

2023-02-01 07:34:41

讀寫分離數(shù)據(jù)庫(kù)

2021-09-08 10:23:08

讀寫分離Java數(shù)據(jù)庫(kù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)