精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

SpringBoot+AOP構建多數據源的切換實踐

開發 后端
下邊我將通過一個簡單的基于springboot+aop的案例來實現如何通過自定義注解切換不同的數據源進行讀數據操作,同時也將結合部分源碼的內容進行講解。

 [[318595]]

針對微服務架構中常用的設計模塊,通常我們都會需要使用到druid作為我們的數據連接池,當架構發生擴展的時候 ,通常面對的數據存儲服務器也會漸漸增加,從原本的單庫架構逐漸擴展為復雜的多庫架構。

當在業務層需要涉及到查詢多種同數據庫的場景下,我們通常需要在執行sql的時候動態指定對應的datasource。

而Spring的AbstractRoutingDataSource則正好為我們提供了這一功能點,下邊我將通過一個簡單的基于springboot+aop的案例來實現如何通過自定義注解切換不同的數據源進行讀數據操作,同時也將結合部分源碼的內容進行講解。

首先我們需要自定義一個專門用于申明當前java應用程序所需要使用到哪些數據源信息: 

  1. package mutidatasource.annotation;  
  2. import mutidatasource.config.DataSourceConfigRegister;  
  3. import mutidatasource.enums.SupportDatasourceEnum;  
  4. import org.springframework.context.annotation.Import;  
  5. import org.springframework.stereotype.Component;  
  6. import java.lang.annotation.*;  
  7. /**  
  8.  * 注入數據源  
  9.  *  
  10.  * @author idea  
  11.  * @data 2020/3/7  
  12.  */  
  13. @Target({ElementType.METHOD,ElementType.TYPE})  
  14. @Retention(RetentionPolicy.RUNTIME)  
  15. @Documented  
  16. @Import(DataSourceConfigRegister.class)  
  17. public @interface AppDataSource {  
  18.     SupportDatasourceEnum[] datasourceType();  

這里為了方便,我將測試中使用的數據源地址都配置在來enum里面,如果后邊需要靈活處理的話,可以將這些配置信息抽取出來放在一些配置中心上邊。 

  1. package mutidatasource.enums;  
  2. import lombok.AllArgsConstructor;  
  3. import lombok.Getter;  
  4. import lombok.NoArgsConstructor;  
  5. /**  
  6.  * 目前支持的數據源信息  
  7.  *  
  8.  * @author idea  
  9.  * @data 2020/3/7  
  10.  */  
  11. @AllArgsConstructor  
  12. @Getter  
  13. public enum SupportDatasourceEnum {  
  14.     PROD_DB("jdbc:mysql://localhost:3306/db-prod?useUnicode=true&characterEncoding=utf8","root","root","db-prod"), 
  15.     DEV_DB("jdbc:mysql://localhost:3306/db-dev?useUnicode=true&characterEncoding=utf8","root","root","db-dev"),  
  16.     PRE_DB("jdbc:mysql://localhost:3306/db-pre?useUnicode=true&characterEncoding=utf8","root","root","db-pre");  
  17.     String url;  
  18.     String username;  
  19.     String password;  
  20.     String databaseName;  
  21.     @Override  
  22.     public String toString() {  
  23.         return super.toString().toLowerCase();  
  24.     }  

之所以要創建這個@AppDataSource注解,是要在springboot的啟動類上邊進行標注: 

  1. package mutidatasource;  
  2. import mutidatasource.annotation.AppDataSource;  
  3. import mutidatasource.enums.SupportDatasourceEnum;  
  4. import org.springframework.boot.SpringApplication;  
  5. import org.springframework.boot.autoconfigure.SpringBootApplication;  
  6. /**  
  7.  * @author idea  
  8.  * @data 2020/3/7  
  9.  */  
  10. @SpringBootApplication  
  11. @AppDataSource(datasourceType = {SupportDatasourceEnum.DEV_DB, SupportDatasourceEnum.PRE_DB, SupportDatasourceEnum.PROD_DB})  
  12. public class SpringApplicationDemo {  
  13.     public static void main(String[] args) {  
  14.         SpringApplication.run(SpringApplicationDemo.class);  
  15.     }  

借助springboot的ImportSelector 自定義一個注冊器來獲取啟動類頭部的注解所指定的數據源類型: 

  1. package mutidatasource.config;  
  2. import lombok.extern.slf4j.Slf4j;  
  3. import mutidatasource.annotation.AppDataSource;  
  4. import mutidatasource.core.DataSourceContextHolder;  
  5. import mutidatasource.enums.SupportDatasourceEnum;  
  6. import org.springframework.context.annotation.ImportSelector;  
  7. import org.springframework.core.annotation.AnnotationAttributes;  
  8. import org.springframework.core.type.AnnotationMetadata;  
  9. import org.springframework.stereotype.Component;  
  10. /**  
  11.  * @author idea  
  12.  * @data 2020/3/7  
  13.  */  
  14. @Slf4j  
  15. @Component  
  16. public class DataSourceConfigRegister implements ImportSelector {  
  17.     @Override  
  18.     public String[] selectImports(AnnotationMetadata annotationMetadata) {  
  19.         AnnotationAttributes attributes = AnnotationAttributes.fromMap(annotationMetadata.getAnnotationAttributes(AppDataSource.class.getName())); 
  20.          System.out.println("#######  datasource import #######");  
  21.         if (null != attributes) {  
  22.             Object object = attributes.get("datasourceType");  
  23.             SupportDatasourceEnum[] supportDatasourceEnums = (SupportDatasourceEnum[]) object;  
  24.             for (SupportDatasourceEnum supportDatasourceEnum : supportDatasourceEnums) {  
  25.                 DataSourceContextHolder.addDatasource(supportDatasourceEnum);  
  26.             }  
  27.         }  
  28.         return new String[0];  
  29.     }  

好的,現在我們已經能夠獲取到對應的數據源類型信息了,這里你會看到一個叫做DataSourceContextHolder的角色。這個對象主要是用于對每個請求線程的數據源信息做統一的分配和管理。

在多并發場景下,為了防止不同線程請求的數據源出現“互竄”情況,通常我們都會使用到threadlocal來做處理。為每一個線程都分配一個指定的,屬于其內部的副本變量,當當前線程結束之前,記得將對應的線程副本也進行銷毀。 

  1. package mutidatasource.core;  
  2. import mutidatasource.enums.SupportDatasourceEnum;  
  3. import java.util.HashSet;  
  4. /**  
  5.  * @author idea  
  6.  * @data 2020/3/7  
  7.  */  
  8. public class DataSourceContextHolder {  
  9.     private static final HashSet<SupportDatasourceEnum> dataSourceSet = new HashSet<>();  
  10.     private static final ThreadLocal<String> databaseHolder = new ThreadLocal<>();  
  11.     public static void setDatabaseHolder(SupportDatasourceEnum supportDatasourceEnum) {  
  12.         databaseHolder.set(supportDatasourceEnum.toString()); 
  13.     }  
  14.     /**  
  15.      * 取得當前數據源  
  16.      *  
  17.      * @return  
  18.      */  
  19.     public static String getDatabaseHolder() {  
  20.         return databaseHolder.get();  
  21.     }  
  22.     /**  
  23.      * 添加數據源  
  24.      *  
  25.      * @param supportDatasourceEnum  
  26.      */  
  27.     public static void addDatasource(SupportDatasourceEnum supportDatasourceEnum) {  
  28.         dataSourceSet.add(supportDatasourceEnum);  
  29.     }  
  30.     /**  
  31.      * 獲取當期應用所支持的所有數據源  
  32.      *  
  33.      * @return  
  34.      */  
  35.     public static HashSet<SupportDatasourceEnum> getDataSourceSet() {  
  36.         return dataSourceSet;  
  37.     }  
  38.     /**  
  39.      * 清除上下文數據  
  40.      */  
  41.     public static void clear() {  
  42.         databaseHolder.remove();  
  43.     }  

spring內部的AbstractRoutingDataSource動態路由數據源里面有一個抽象方法叫做

determineCurrentLookupKey,這個方法適用于提供給開發者自定義對應數據源的查詢key。 

  1. package mutidatasource.core;  
  2. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;  
  3. /**  
  4.  * @author idea  
  5.  * @data 2020/3/7  
  6.  */  
  7. public class DynamicDataSource extends AbstractRoutingDataSource {  
  8.     @Override  
  9.     protected Object determineCurrentLookupKey() {  
  10.         String dataSource = DataSourceContextHolder.getDatabaseHolder();  
  11.         return dataSource;  
  12.     }  

這里我使用的druid數據源,所以配置數據源的配置類如下:這里面我默認該應用配置類PROD數據源,用于測試使用。 

  1. package mutidatasource.core;  
  2. import com.alibaba.druid.pool.DruidDataSource;  
  3. import lombok.extern.slf4j.Slf4j;  
  4. import mutidatasource.enums.SupportDatasourceEnum;  
  5. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;  
  6. import org.springframework.context.annotation.Bean;  
  7. import org.springframework.context.annotation.Primary;  
  8. import org.springframework.stereotype.Component;  
  9. import javax.sql.DataSource;  
  10. import java.util.HashMap;  
  11. import java.util.HashSet;  
  12. /**  
  13.  * @author idea  
  14.  * @data 2020/3/7  
  15.  */  
  16. @Slf4j  
  17. @Component  
  18. public class DynamicDataSourceConfiguration {  
  19.     @Bean  
  20.     @Primary  
  21.     @ConditionalOnMissingBean  
  22.     public DataSource dataSource() {  
  23.         System.out.println("init datasource");  
  24.         DynamicDataSource dynamicDataSource = new DynamicDataSource();  
  25.         //設置原始數據源  
  26.         HashMap<Object, Object> dataSourcesMap = new HashMap<>();  
  27.         HashSet<SupportDatasourceEnum> dataSet = DataSourceContextHolder.getDataSourceSet();  
  28.         for (SupportDatasourceEnum supportDatasourceEnum : dataSet) {  
  29.             DataSource dataSource = this.createDataSourceProperties(supportDatasourceEnum);  
  30.             dataSourcesMap.put(supportDatasourceEnum.toString(), dataSource); 
  31.         }  
  32.         dynamicDataSource.setTargetDataSources(dataSourcesMap);  
  33.         dynamicDataSource.setDefaultTargetDataSource(createDataSourceProperties(SupportDatasourceEnum.PRE_DB));  
  34.         return dynamicDataSource;  
  35.     }  
  36.     private synchronized DataSource createDataSourceProperties(SupportDatasourceEnum supportDatasourceEnum) {  
  37.         DruidDataSource druidDataSource = new DruidDataSource();  
  38.         druidDataSource.setUrl(supportDatasourceEnum.getUrl());  
  39.         druidDataSource.setUsername(supportDatasourceEnum.getUsername());  
  40.         druidDataSource.setPassword(supportDatasourceEnum.getPassword());  
  41.         //具體配置  
  42.         druidDataSource.setMaxActive(100);  
  43.         druidDataSource.setInitialSize(5);  
  44.         druidDataSource.setMinIdle(1);  
  45.         druidDataSource.setMaxWait(30000);  
  46.         //間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒  
  47.         druidDataSource.setTimeBetweenConnectErrorMillis(60000);  
  48.         return druidDataSource;  
  49.     }  

好了現在一個基礎的數據源注入已經可以了,那么我們該如何借助注解來實現動態切換數據源的操作呢?

為此,我設計了一個叫做UsingDataSource的注解,通過利用該注解來識別當前線程所需要使用的數據源操作: 

  1. package mutidatasource.annotation;  
  2. import mutidatasource.enums.SupportDatasourceEnum;  
  3. import java.lang.annotation.*;  
  4. /**  
  5.  * @author idea  
  6.  * @data 2020/3/7  
  7.  */  
  8. @Target({ElementType.METHOD,ElementType.TYPE})  
  9. @Retention(RetentionPolicy.RUNTIME)  
  10. @Documented  
  11. public @interface UsingDataSource {  
  12.     SupportDatasourceEnum type()  ;  

然后,借助了spring的aop來做切面攔截: 

  1. package mutidatasource.core;  
  2. import lombok.extern.slf4j.Slf4j;  
  3. import mutidatasource.annotation.UsingDataSource;  
  4. import org.aspectj.lang.JoinPoint;  
  5. import org.aspectj.lang.ProceedingJoinPoint;  
  6. import org.aspectj.lang.Signature;  
  7. import org.aspectj.lang.annotation.*;  
  8. import org.aspectj.lang.reflect.MethodSignature;  
  9. import org.springframework.context.annotation.Configuration;  
  10. import org.springframework.core.annotation.AnnotationUtils;  
  11. import org.springframework.core.annotation.Order;  
  12. import org.springframework.stereotype.Component;  
  13. import java.lang.reflect.Method;  
  14. import java.util.Arrays;  
  15. /**  
  16.  * @author idea  
  17.  * @data 2020/3/7  
  18.  */  
  19. @Slf4j  
  20. @Aspect  
  21. @Configuration  
  22. public class DataSourceAspect {  
  23.     public DataSourceAspect(){  
  24.         System.out.println("this is init");  
  25.     }  
  26.     @Pointcut("@within(mutidatasource.annotation.UsingDataSource) || " +  
  27.             "@annotation(mutidatasource.annotation.UsingDataSource)")  
  28.     public void pointCut(){  
  29.     }  
  30.     @Before("pointCut() && @annotation(usingDataSource)")  
  31.     public void doBefore(UsingDataSource usingDataSource){  
  32.         log.debug("select dataSource---"+usingDataSource.type());  
  33.         DataSourceContextHolder.setDatabaseHolder(usingDataSource.type()); 
  34.     }  
  35.     @After("pointCut()")  
  36.     public void doAfter(){  
  37.         DataSourceContextHolder.clear();  
  38.     }  

測試類如下所示: 

  1. package mutidatasource.controller;  
  2. import lombok.extern.slf4j.Slf4j;  
  3. import mutidatasource.annotation.UsingDataSource;  
  4. import mutidatasource.enums.SupportDatasourceEnum;  
  5. import org.springframework.beans.factory.annotation.Autowired;  
  6. import org.springframework.jdbc.core.JdbcTemplate;  
  7. import org.springframework.web.bind.annotation.GetMapping;  
  8. import org.springframework.web.bind.annotation.RequestMapping;  
  9. import org.springframework.web.bind.annotation.RestController;  
  10. /**  
  11.  * @author idea  
  12.  * @data 2020/3/8  
  13.  */  
  14. @RestController  
  15. @RequestMapping(value = "/test" 
  16. @Slf4j  
  17. public class TestController {  
  18.     @Autowired  
  19.     private JdbcTemplate jdbcTemplate;  
  20.     @GetMapping(value = "/testDev" 
  21.     @UsingDataSource(type=SupportDatasourceEnum.DEV_DB)  
  22.     public void testDev() {  
  23.         showData();  
  24.     }  
  25.     @GetMapping(value = "/testPre" 
  26.     @UsingDataSource(type=SupportDatasourceEnum.PRE_DB)  
  27.     public void testPre() {  
  28.         showData();  
  29.     }  
  30.     private void showData() {  
  31.         jdbcTemplate.queryForList("select * from test1").forEach(row -> log.info(row.toString()));  
  32.     }  

最后 啟動springboot服務,通過使用注解即可測試對應功能。

關于AbstractRoutingDataSource 動態路由數據源的注入原理,

可以看到這個內部類里面包含了多種用于做數據源映射的map數據結構。

在該類的最底部,有一個determineCurrentLookupKey函數,也就是上邊我們所提及的使用于查詢當前數據源key的方法。

具體代碼如下:

  1. /**  
  2.    * Retrieve the current target DataSource. Determines the  
  3.    * {@link #determineCurrentLookupKey() current lookup key}, performs  
  4.    * a lookup in the {@link #setTargetDataSources targetDataSources} map,  
  5.    * falls back to the specified  
  6.    * {@link #setDefaultTargetDataSource default target DataSource} if necessary. 
  7.    * @see #determineCurrentLookupKey()  
  8.    */  
  9.   protected DataSource determineTargetDataSource() {  
  10.       Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");  
  11.       //這里面注入我們當前線程使用的數據源  
  12.       Object lookupKey = determineCurrentLookupKey();  
  13.       //在初始化數據源的時候需要我們去給resolvedDataSources進行注入  
  14.       DataSource dataSource = this.resolvedDataSources.get(lookupKey);  
  15.       if (dataSource == null && (this.lenientFallback || lookupKey == null)) {  
  16.           dataSource = this.resolvedDefaultDataSource;  
  17.       }  
  18.       if (dataSource == null) {  
  19.           throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");  
  20.       }  
  21.       return dataSource;  
  22.   }  
  23.   /**  
  24.    * Determine the current lookup key. This will typically be  
  25.    * implemented to check a thread-bound transaction context.  
  26.    * <p>Allows for arbitrary keys. The returned key needs  
  27.    * to match the stored lookup key type, as resolved by the  
  28.    * {@link #resolveSpecifiedLookupKey} method.  
  29.    */  
  30.   @Nullable  
  31.   protected abstract Object determineCurrentLookupKey(); 

而在該類的afterPropertiesSet里面,又有對于初始化數據源的注入操作,這里面的targetDataSources 正是上文中我們對在初始化數據源時候注入的信息。   

  1. @Override  
  2.     public void afterPropertiesSet() {  
  3.         if (this.targetDataSources == null) {  
  4.             throw new IllegalArgumentException("Property 'targetDataSources' is required");  
  5.         }  
  6.         this.resolvedDataSources = new HashMap<>(this.targetDataSources.size());  
  7.         this.targetDataSources.forEach((key, value) -> {  
  8.             Object lookupKey = resolveSpecifiedLookupKey(key);  
  9.             DataSource dataSource = resolveSpecifiedDataSource(value);  
  10.             this.resolvedDataSources.put(lookupKey, dataSource);  
  11.         });  
  12.         if (this.defaultTargetDataSource != null) {  
  13.             this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);  
  14.         }  
  15.     }  

 

責任編輯:龐桂玉 來源: Java知音
相關推薦

2023-01-04 09:33:31

SpringBootMybatis

2024-10-30 10:22:17

2023-09-07 08:39:39

copy屬性數據源

2023-06-07 08:08:37

MybatisSpringBoot

2023-02-06 14:44:00

嚴選數據源DB

2020-06-02 07:55:31

SpringBoot多數據源

2022-05-10 10:43:35

數據源動態切換Spring

2020-12-31 07:55:33

spring bootMybatis數據庫

2023-11-27 07:33:55

2023-10-31 07:52:53

多數據源管理后端

2009-08-14 10:26:27

ibatis多數據源

2020-11-24 09:56:12

數據源讀寫分離

2025-04-14 01:00:00

Calcite電商系統MySQL

2022-05-18 12:04:19

Mybatis數據源Spring

2022-12-19 07:21:35

Hutool-db數據庫JDBC

2025-01-17 09:11:51

2025-08-26 01:15:00

Spring項目數據源

2017-07-21 14:50:15

數據庫DB分庫事務處理

2017-09-04 14:52:51

Tomcat線程數據源

2023-10-18 15:25:29

數據源數據庫
點贊
收藏

51CTO技術棧公眾號

女人黄色一级片| 日韩中文字幕三区| 亚洲精品一区二区三区蜜桃| 在线视频观看日韩| 亚洲欧美激情一区| 日韩免费高清在线| 一色桃子av在线| 成人av电影免费在线播放| 奇门遁甲1982国语版免费观看高清 | 欧美视频一区二区| 欧美极品少妇无套实战| 蜜桃视频在线观看网站| 国产又粗又猛又爽又黄91精品| 欧美激情2020午夜免费观看| 天天操天天干天天操天天干| 国产人妖ts一区二区| 欧美在线制服丝袜| 免费看国产一级片| 91精品久久久久久粉嫩| 久久久电影一区二区三区| 不卡视频一区二区三区| 日韩av大片在线观看| 午夜欧美在线| 国产亚洲精品久久| 成人性生活免费看| 国产精品一区免费在线 | 在线观看中文字幕网站| 国产精品日本欧美一区二区三区| 美女av一区二区三区| 在线观看免费小视频| 首页亚洲中字| 欧美草草影院在线视频| www.超碰97.com| 欧美人体一区二区三区| 亚洲成人av福利| 黄黄视频在线观看| 乱人伦中文视频在线| 26uuu亚洲综合色欧美| 国产富婆一区二区三区| 精品国自产拍在线观看| 久久成人免费网| 国产99久久精品一区二区 夜夜躁日日躁 | 26uuu亚洲伊人春色| 国产五月天婷婷| 欧美激情麻豆| 欧美成人免费播放| 91嫩草丨国产丨精品| 97偷自拍亚洲综合二区| 色诱女教师一区二区三区| 亚洲图片另类小说| 蜜臀91精品国产高清在线观看| 亚洲电影免费观看高清完整版在线观看 | 黑人巨大精品一区二区在线| 91精品国产视频| 久久精品国产2020观看福利| 久草手机视频在线观看| 91麻豆精品国产91久久久平台 | 深夜福利视频一区二区| 精品国产电影一区| 国产原创中文在线观看| 极品在线视频| 欧美日韩中文在线观看| 欧美国产日韩在线播放| 亚洲承认视频| 欧美日韩国产影片| 欧美激情第四页| 伊人久久影院| 亚洲精品福利视频| 永久免费看mv网站入口78| 国产亚洲一区| zzijzzij亚洲日本成熟少妇| 精品自拍偷拍视频| 韩国在线一区| 日本午夜精品理论片a级appf发布| 天干夜夜爽爽日日日日| 免费高清在线视频一区·| 成人精品视频久久久久| 亚洲xxx在线| 久久免费看少妇高潮| 亚洲精品电影在线一区| av观看在线| 黄色成人av网| 亚洲少妇第一页| 精品视频一区二区三区在线观看| 欧美成人一级视频| 蜜桃无码一区二区三区| 欧洲毛片在线视频免费观看| 久久视频在线播放| 成人免费看片98欧美| 青青国产91久久久久久| 91入口在线观看| 精品福利视频导航大全| 亚洲靠逼com| 黄色片视频在线免费观看| 欧美videos粗暴| 亚洲福利小视频| 人妻无码一区二区三区免费| 亚洲视频日本| 国产精品激情av电影在线观看| av男人天堂网| 国产欧美日韩麻豆91| 国产精品视频二| 欧美高清免费| 精品国产免费一区二区三区香蕉| 久久亚洲无码视频| 激情欧美一区| 国产精品久久久久免费a∨大胸 | av日韩在线看| 在线看片国产福利你懂的| 91麻豆精品久久久久蜜臀| 最新中文字幕视频| 国内综合精品午夜久久资源| 国产精品天天狠天天看| av女名字大全列表| 一区二区三区**美女毛片| 毛片毛片毛片毛片毛片毛片毛片毛片毛片| 美女精品视频在线| 色爱精品视频一区| 四虎成人永久免费视频| 国产suv精品一区二区6| www亚洲国产| 日韩漫画puputoon| 国产视频丨精品|在线观看| 国产午夜精品理论片在线| 日本怡春院一区二区| 麻豆成人小视频| 国产美女一区视频| 欧美一级夜夜爽| 超碰人人人人人人人| 久久精品综合| 久久99精品久久久久久青青日本| 七七久久电影网| 欧美一区二区三区在线| 成人无码精品1区2区3区免费看 | 美国一级片在线免费观看视频 | 国产精品伦一区二区三区| 国产午夜亚洲精品理论片色戒| 一本久道高清无码视频| 国产精品45p| 久久久久久av| 丰满肥臀噗嗤啊x99av| 亚洲精选免费视频| 超碰在线免费av| 性xxxx欧美老肥妇牲乱| 成人免费观看网址| 黄色成年人视频在线观看| 欧美日韩精品欧美日韩精品| 欧美成人另类视频| 热久久国产精品| 亚洲乱码国产乱码精品天美传媒| 一二区成人影院电影网| 一区二区欧美亚洲| 中文字幕资源网| 国产精品国产三级国产三级人妇| 黄色三级视频在线| 97国产精品| 91久久久久久久一区二区| 国内精品久久久久久野外| 日韩一区二区中文字幕| 久久综合加勒比| 99精品视频一区二区| 黄色一级片播放| 国产调教一区二区三区| 成人一区二区电影| 青草在线视频在线观看| 日韩av在线网址| 日本黄色一级视频| 国产精品三级电影| 交换做爰国语对白| 亚洲天堂男人| 欧美另类高清视频在线| 久久久久毛片| 欧美日本啪啪无遮挡网站| 手机在线观看毛片| 在线观看亚洲精品| 少妇aaaaa| 国产成人精品1024| av免费中文字幕| 日韩精品永久网址| 成人h视频在线观看| 日韩精品美女| 色噜噜久久综合伊人一本| 午夜精品久久久久久久爽 | 日本一区二区在线不卡| 午夜一级免费视频| 99精品热视频只有精品10| 日韩.欧美.亚洲| 日韩视频在线直播| 日韩av观看网址| 污污的网站在线看| 国产一区二区久久精品| 亚洲AV无码乱码国产精品牛牛 | 国产老女人乱淫免费| 午夜伦理一区二区| 欧日韩不卡视频| 99久久伊人久久99| 中文字幕 欧美日韩| 性色一区二区| 男人草女人视频| 免费国产自久久久久三四区久久| 91久久国产婷婷一区二区| 中文不卡1区2区3区| 欧美精品亚州精品| 1769在线观看| 亚洲精品国产电影| 精品国产999久久久免费| 色婷婷精品大视频在线蜜桃视频| 欧美精品一区二区蜜桃| 国产女同互慰高潮91漫画| 国产清纯白嫩初高中在线观看性色| 日本在线不卡视频一二三区| 婷婷无套内射影院| 亚洲高清影视| 视频一区在线免费观看| 群体交乱之放荡娇妻一区二区| 91亚洲va在线va天堂va国| 亚洲精品国产嫩草在线观看| 韩国一区二区电影| 羞羞的网站在线观看| 日韩网站在线观看| av影片在线看| 亚洲欧洲一区二区三区久久| 国产小视频一区| 日韩一级片网址| 亚洲一级黄色大片| 欧美艳星brazzers| 国产真人无遮挡作爱免费视频| 亚洲成人一二三| 久久久久久久黄色| 亚洲精品写真福利| 顶臀精品视频www| 中文字幕亚洲不卡| 人成免费在线视频| 日本一区二区动态图| 久久精品国产亚洲av久| 久久综合久久综合亚洲| 亚洲精品视频大全| 97aⅴ精品视频一二三区| 日本少妇xxxx| 99久久精品久久久久久清纯| 国产原创剧情av| 成人精品国产免费网站| 69xxx免费视频| 成人av免费观看| 在线xxxxx| 99视频精品在线| 成人网站免费观看| 久久久91精品国产一区二区精品| 青青草福利视频| 国产亚洲综合av| 女人裸体性做爰全过| 亚洲日本一区二区三区| 欧美日韩免费做爰视频| 亚洲国产成人av网| 久草手机在线观看| 色综合久久天天综合网| 伊人久久中文字幕| 欧美久久一区二区| 国产aⅴ一区二区三区| 欧美精品一区二区三区久久久| 日本韩国免费观看| 亚洲乱码一区二区| 91大神在线网站| 不卡av电影院| 国产美女高潮在线观看| 日本精品一区二区三区在线播放视频| 婷婷激情一区| 91美女片黄在线观| 第一区第二区在线| 欧洲视频一区二区三区| 久久影院100000精品| 91国在线高清视频| 国产精品一二| 在线观看av网页| 国产成人亚洲综合a∨猫咪| 精品国产一区在线| 中文一区在线播放| 久草中文在线视频| 91黄色在线观看| 国产三区在线播放| 亚洲精品久久7777777| 国产高清视频在线| 欧美老少做受xxxx高潮| 波多视频一区| 91网站在线免费观看| 亚洲a级精品| 日本女人高潮视频| 国产亚洲欧洲| 久久综合在线观看| 91色porny| 91嫩草|国产丨精品入口| 欧美日韩精品在线观看| 国产在成人精品线拍偷自揄拍| 亚洲精品在线免费播放| 一广人看www在线观看免费视频| 色综合久久88色综合天天看泰| 97se综合| 成人3d动漫一区二区三区91| 成人影院天天5g天天爽无毒影院| 国产在线视频在线| 日本不卡123| 国产亚洲无码精品| 一区二区三区在线视频观看| 免费av中文字幕| 欧美精品一区二区三区蜜桃视频 | 久久久久久网址| 国产精品99| 欧美日韩在线精品| 在线亚洲伦理| 精品人妻无码中文字幕18禁| 国产精品久久久久久久蜜臀| 青青国产在线观看| 精品久久久久99| 成人短视频在线| 国产噜噜噜噜久久久久久久久| 色老板在线视频一区二区| 大桥未久一区二区三区| 青青草伊人久久| 在线不卡av电影| 欧美日韩国产页| 欧美 日韩 中文字幕| 欧美床上激情在线观看| 欧美综合影院| 婷婷五月色综合| 视频一区二区三区在线| 亚洲av无码一区二区三区网址| 一区二区视频在线看| 国产免费久久久| 日韩在线视频导航| 成人性片免费| 亚洲国产一区二区三区在线播 | gogo亚洲国模私拍人体| 国产精品毛片久久久久久| 亚洲av无码乱码国产精品fc2| 亚洲毛片在线免费观看| 深夜av在线| 久久综合一区| 免费视频一区| 少妇久久久久久久久久| 在线免费视频一区二区| 黄色小视频在线免费观看| 日韩av观看网址| 欧美在线色图| www.国产视频.com| 亚洲视频小说图片| 国产同性人妖ts口直男| 欧美精品亚州精品| 波多野结衣欧美| 免费国产a级片| 久久这里都是精品| 欧美性猛交xxxx乱大交hd | 精品视频导航| 麻豆精品网站| 欧美成人国产精品一区二区| 欧美亚洲国产一区二区三区 | 欧美极品少妇xxxxⅹ裸体艺术| 亚洲成人黄色| 日本a视频在线观看| 92国产精品观看| 国产午夜麻豆影院在线观看| 在线观看日韩视频| 国产精品久久久久久久久久辛辛| 女人床在线观看| 97久久超碰国产精品电影| 一级黄色在线视频| 色偷偷888欧美精品久久久| 国产中文欧美日韩在线| 日韩日韩日韩日韩日韩| 久久午夜电影网| 亚洲一区二区色| 久久久久久亚洲精品不卡| 欧美女王vk| 天天综合成人网| 天天av天天翘天天综合网| 国产高清视频在线观看| 95av在线视频| 性伦欧美刺激片在线观看| 91大神福利视频| 亚洲成人网在线| 成人国产一区| 欧美日韩福利在线| 中文字幕av资源一区| 亚洲精品综合网| 国产极品jizzhd欧美| 欧美99在线视频观看| 亚洲av无码国产精品久久| 在线不卡中文字幕播放| 国产在线看片免费视频在线观看| 天天久久人人| 大桥未久av一区二区三区中文| av片免费观看| 欧美精品xxx| 久久一级电影| 成年人网站免费看| 日韩一级精品视频在线观看| 亚洲四虎影院| 成人在线播放网址| 亚洲婷婷综合久久一本伊一区| 亚洲三级黄色片| 99se婷婷在线视频观看|