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

配置屬性熱更新:基于 WatchService 實現(xiàn)方案

開發(fā) 前端
Spring Boot的ConfigurationProperties注解提供了將外部配置綁定到JavaBean的能力,實現(xiàn)了類型安全的配置訪問。它支持分層結構的配置,并提供了屬性校驗等功能,是Spring應用中管理配置的推薦方式。

前言

在現(xiàn)代應用開發(fā)中,配置屬性的動態(tài)更新能力已成為系統(tǒng)靈活性和可維護性的重要指標。傳統(tǒng)的配置方式往往需要重啟應用才能使新配置生效,這在生產(chǎn)環(huán)境中可能造成不必要的服務中斷。

雖然Spring Cloud ConfigApollo這類配置中心能解決問題,但對于中小項目來說太重了——要部署服務,成本太高。

本文將詳細介紹如何結合Java NIOWatchServiceSpringEnvironmentConfigurationProperties 以及ApplicationEvent,構建一套完整的配置屬性熱更新解決方案。

效果圖

圖片圖片

組件解析

WatchService:文件系統(tǒng)監(jiān)聽機制

WatchServiceJava NIO提供的文件系統(tǒng)監(jiān)聽服務,能夠實時監(jiān)測指定目錄或文件的變化,包括創(chuàng)建、修改和刪除等操作。它采用了高效的操作系統(tǒng)原生通知機制,相比傳統(tǒng)的輪詢方式具有更低的資源消耗和更高的響應速度。

try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
    Path path = Paths.get("config");
    path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
    
    while (true) {
        WatchKey key = watchService.poll(1, TimeUnit.SECONDS);
        if (key == null) continue;
        
        for (WatchEvent<?> event : key.pollEvents()) {
            WatchEvent.Kind<?> kind = event.kind();
            if (kind == StandardWatchEventKinds.OVERFLOW) continue;
            
            Path changedFile = (Path) event.context();
            if (changedFile.endsWith("application.properties")) {
                // 處理配置文件變更
                handleConfigChange();
            }
        }
        
        boolean valid = key.reset();
        if (!valid) break;
    }
} catch (Exception e) {
    // 異常處理
}

Environment:配置訪問的核心接口

SpringEnvironment接口是訪問應用配置的集中點,它整合了各種配置源(如.properties文件、系統(tǒng)環(huán)境變量、命令行參數(shù)等),并提供了統(tǒng)一的訪問方式。通過Environment,我們可以獲取到最新的配置屬性值。

@Autowired
private Environment environment;

public String getConfigValue(String key) {
    return environment.getProperty(key);
}

ConfigurationProperties:類型安全的配置綁定

Spring BootConfigurationProperties注解提供了將外部配置綁定到JavaBean的能力,實現(xiàn)了類型安全的配置訪問。它支持分層結構的配置,并提供了屬性校驗等功能,是Spring應用中管理配置的推薦方式。

@ConfigurationProperties(prefix = "app")
@Component
public class AppConfig {
    private String name;
    private int timeout;
    private List<String> allowedOrigins;
    
    // getters and setters
}

ApplicationEvent:配置變更的通知機制

Spring的事件機制允許我們定義和發(fā)布自定義事件,實現(xiàn)組件間的解耦通信。在配置熱更新場景中,我們可以通過發(fā)布配置變更事件,通知系統(tǒng)中依賴該配置的各個組件及時更新狀態(tài)。

// 自定義配置變更事件
public class ConfigChangedEvent extends ApplicationEvent {
    private final String configKey;
    private final String oldValue;
    private final String newValue;
    
    public ConfigChangedEvent(Object source, String configKey, String oldValue, String newValue) {
        super(source);
        this.configKey = configKey;
        this.oldValue = oldValue;
        this.newValue = newValue;
    }
    
    // getters
}

// 發(fā)布事件
@Autowired
private ApplicationEventPublisher publisher;

public void publishConfigChange(String key, String oldValue, String newValue) {
    publisher.publishEvent(new ConfigChangedEvent(this, key, oldValue, newValue));
}

// 監(jiān)聽事件
@Component
public class ConfigChangeListener {
    @EventListener
    public void handleConfigChange(ConfigChangedEvent event) {
        // 處理配置變更
        log.info("Config {} changed from {} to {}", 
                 event.getConfigKey(), 
                 event.getOldValue(), 
                 event.getNewValue());
    }
}

實現(xiàn)方案

結合上述技術組件,我們可以構建一個完整的配置熱更新解決方案,其核心流程如下:

  • 使用WatchService監(jiān)聽配置文件的變化
  • 當配置文件發(fā)生變更時,重新加載配置
  • 更新Environment中的配置值
  • 刷新ConfigurationProperties綁定的Bean
  • 發(fā)布配置變更事件,通知相關組件

配置文件監(jiān)聽服務

首先實現(xiàn)一個配置文件監(jiān)聽服務,使用WatchService監(jiān)測配置文件的變化:

@Component
public class ConfigFileWatcher implements CommandLineRunner, DisposableBean {
    private static final Logger log = LoggerFactory.getLogger(ConfigFileWatcher.class);

    private final WatchService watchService;
    private final Path configPath;
    private final ConfigReloader configReloader;
    private volatile boolean running = true;
    private Thread watchThread;

    public ConfigFileWatcher(ConfigReloader configReloader) throws IOException {
        this.watchService = FileSystems.getDefault().newWatchService();
        this.configPath = Paths.get("D:\\gitee\\self-learn\\01_springboot\\test-demo\\src\\main\\resources");
        this.configReloader = configReloader;

        // 確保配置目錄存在
        if (!configPath.toFile().exists()) {
            boolean created = configPath.toFile().mkdirs();
            if (created) {
                log.info("Created config directory: {}", configPath);
            }
        }

        // 注冊監(jiān)聽事件
        configPath.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
    }

    @Override
    public void run(String... args) {
        watchThread = new Thread(this::watch);
        watchThread.setDaemon(true);
        watchThread.start();
        log.info("Config file watcher started, monitoring: {}", configPath.toAbsolutePath());
    }

    private void watch() {
        while (running) {
            try {
                WatchKey key = watchService.poll(1, TimeUnit.SECONDS);
                if (key == null) continue;

                for (WatchEvent<?> event : key.pollEvents()) {
                    WatchEvent.Kind<?> kind = event.kind();
                    if (kind == StandardWatchEventKinds.OVERFLOW) continue;

                    @SuppressWarnings("unchecked")
                    WatchEvent<Path> pathEvent = (WatchEvent<Path>) event;
                    Path changedFile = pathEvent.context();

                    if (isConfigFile(changedFile.toString())) {
                        log.info("Detected change in config file: {}", changedFile);
                        File file = configPath.resolve(changedFile).toFile();
                        configReloader.reloadConfig(file);
                    }
                }

                boolean valid = key.reset();
                if (!valid) break;
            } catch (Exception e) {
                log.error("Error watching config files", e);
            }
        }
    }

    private boolean isConfigFile(String fileName) {
        return fileName.endsWith(".properties") ||
                fileName.endsWith(".yml") ||
                fileName.endsWith(".yaml");
    }

    @Override
    public void destroy() throws Exception {
        running = false;
        if (watchThread != null) {
            watchThread.join();
        }
        watchService.close();
        log.info("Config file watcher stopped");
    }
}

配置重新加載器

實現(xiàn)配置重新加載器,負責讀取更新后的配置并更新Environment

@Component
public class ConfigReloader {
    private static final Logger log = LoggerFactory.getLogger(ConfigReloader.class);

    private final Environment environment;
    private final ApplicationEventPublisher eventPublisher;
    private final ConfigurableApplicationContext applicationContext;
    private final Map<String, String> currentConfig = new ConcurrentHashMap<>();

    public ConfigReloader(Environment environment,
                          ApplicationEventPublisher eventPublisher,
                          ConfigurableApplicationContext applicationContext) {
        this.environment = environment;
        this.eventPublisher = eventPublisher;
        this.applicationContext = applicationContext;
    }

    @PostConstruct
    public void init() {
        // 初始化當前配置
        loadInitialConfig();
    }

    private void loadInitialConfig() {
        // 從Environment加載初始配置
        if (environment instanceof ConfigurableEnvironment) {
            ConfigurableEnvironment env = (ConfigurableEnvironment) environment;
            for (PropertySource<?> propertySource : env.getPropertySources()) {
                loadPropertySource(propertySource);
            }
        }
    }

    private void loadPropertySource(PropertySource<?> propertySource) {
        try {
            if (propertySource.getSource() instanceof Map) {
                Map<?, ?> sourceMap = (Map<?, ?>) propertySource.getSource();
                sourceMap.forEach((k, v) -> {
                    if (k != null && v != null) {
                        currentConfig.put(k.toString(), v.toString());
                    }
                });
            }
        } catch (Exception e) {
            log.error("Error loading property source: {}", propertySource.getName(), e);
        }
    }

    public void reloadConfig(File configFile) {
        try {
            if (!configFile.exists()) {
                log.warn("Config file not found: {}", configFile.getAbsolutePath());
                return;
            }

            Properties newProperties = loadProperties(configFile);
            if (newProperties == null) {
                return;
            }

            // 比較新舊配置,找出變更項
            Map<String, String> changedProperties = new HashMap<>();

            newProperties.forEach((k, v) -> {
                String key = k.toString();
                String value = v.toString();
                String oldValue = currentConfig.get(key);

                if (!Objects.equals(oldValue, value)) {
                    changedProperties.put(key, value);
                    log.info("Config changed: {} = {}", key, value);
                }
            });

            if (!changedProperties.isEmpty()) {
                // 更新Environment
                updateEnvironment(changedProperties);

                // 刷新ConfigurationProperties
                refreshConfigurationProperties();

                // 發(fā)布配置變更事件
                publishConfigChangeEvents(changedProperties);
            } else {
                log.info("No changes detected in config file: {}", configFile.getName());
            }

        } catch (Exception e) {
            log.error("Error reloading config file: {}", configFile.getAbsolutePath(), e);
        }
    }

    private Properties loadProperties(File configFile) throws IOException {
        if (configFile.getName().endsWith(".yml") || configFile.getName().endsWith(".yaml")) {
            YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
            yamlFactory.setResources(new FileSystemResource(configFile));
            return yamlFactory.getObject();
        } else {
            Properties properties = new Properties();
            try (FileInputStream fis = new FileInputStream(configFile)) {
                properties.load(fis);
            }
            return properties;
        }
    }

    private void updateEnvironment(Map<String, String> changedProperties) {
        if (environment instanceof ConfigurableEnvironment) {
            ConfigurableEnvironment env = (ConfigurableEnvironment) environment;

            // 添加一個新的PropertySource覆蓋舊值
            MapPropertySource newPropertySource = new MapPropertySource(
                    "dynamic-config-" + System.currentTimeMillis(),
                    new HashMap<>(changedProperties)
            );

            env.getPropertySources().addFirst(newPropertySource);
            log.info("Updated environment with {} changed properties", changedProperties.size());
        }
    }

    private void refreshConfigurationProperties() {
        // 獲取所有@ConfigurationProperties Bean并刷新
        Map<String, Object> configBeans = applicationContext.getBeansWithAnnotation(org.springframework.boot.context.properties.ConfigurationProperties.class);
        configBeans.values().forEach(bean -> {
            ConfigurationPropertiesBindingPostProcessor binder =
                    applicationContext.getBean(ConfigurationPropertiesBindingPostProcessor.class);
            try {
                binder.postProcessBeforeInitialization(bean, bean.getClass().getName());
            } catch (Exception e) {
                log.error("Error refreshing configuration bean: {}", bean.getClass().getSimpleName(), e);
            }
        });
        log.info("Refreshed {} configuration properties beans", configBeans.size());
    }

    private void publishConfigChangeEvents(Map<String, String> changedProperties) {
        changedProperties.forEach((key, value) -> {
            String oldValue = currentConfig.get(key);
            eventPublisher.publishEvent(new ConfigChangedEvent(this, key, oldValue, value));
        });
    }

    public String getCurrentConfigValue(String key) {
        return currentConfig.get(key);
    }
}

配置變更事件與監(jiān)聽器

完善配置變更事件和監(jiān)聽器,實現(xiàn)配置變更的通知機制:

public class ConfigChangedEvent extends ApplicationEvent {
    private final String configKey;
    private final String oldValue;
    private final String newValue;

    public ConfigChangedEvent(Object source, String configKey, String oldValue, String newValue) {
        super(source);
        this.configKey = configKey;
        this.oldValue = oldValue;
        this.newValue = newValue;
    }

    public String getConfigKey() {
        return configKey;
    }

    public String getOldValue() {
        return oldValue;
    }

    public String getNewValue() {
        return newValue;
    }
}
@Component
public class ConfigChangeLogger {
    private static final Logger log = LoggerFactory.getLogger(ConfigChangeLogger.class);

    @EventListener
    public void logConfigChange(ConfigChangedEvent event) {
        log.info("Configuration changed - Key: {}, Old Value: {}, New Value: {}",
                event.getConfigKey(),
                event.getOldValue(),
                event.getNewValue());
    }
}
@Component
public class TimeoutConfigListener {
    private static final Logger log = LoggerFactory.getLogger(TimeoutConfigListener.class);
    private int currentTimeout;

    @EventListener
    public void handleTimeoutChange(ConfigChangedEvent event) {
        if ("app.timeout".equals(event.getConfigKey())) {
            try {
                int newTimeout = Integer.parseInt(event.getNewValue());
                currentTimeout = newTimeout;
                log.info("Updating service timeout to {}ms", newTimeout);
                // 這里可以添加實際更新服務超時設置的邏輯
            } catch (NumberFormatException e) {
                log.error("Invalid timeout value: {}", event.getNewValue());
            }
        }
    }

    public int getCurrentTimeout() {
        return currentTimeout;
    }
}

配置屬性 Bean 示例

@Data
@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig {
    private static final Logger log = LoggerFactory.getLogger(AppConfig.class);

    private String name;
    private int timeout = 30;
    private List<String> allowedOrigins = new ArrayList<>();
    private Map<String, String> features = new HashMap<>();

    @PostConstruct
    public void init() {
        log.info("Initializing AppConfig: {}", this);
    }

    @PreDestroy
    public void destroy() {
        log.info("Destroying AppConfig");
    }
}


責任編輯:武曉燕 來源: 一安未來
相關推薦

2024-07-31 08:02:26

Prometheus服務器代碼

2024-04-18 15:22:54

2021-08-03 08:35:36

Vuex數(shù)據(jù)熱更新

2019-11-11 10:38:06

日志配置技術

2025-01-21 11:46:26

2024-07-18 00:05:58

Vite代碼前端

2021-04-15 21:21:59

代碼熱Python函數(shù)

2009-06-14 16:59:16

ibmdwWebSphere

2021-04-19 10:45:52

Webpack熱更新前端

2017-06-16 10:39:51

雙機熱備軟件

2024-05-20 09:07:03

2021-01-20 05:39:50

NacosConfig服務端

2019-09-23 10:51:14

JavaJava虛擬機Linux

2014-09-12 10:30:51

HTML5熱力圖

2021-01-29 10:36:20

Bundle文件Apple

2023-10-12 22:38:18

SpringBoot熱部署

2023-09-11 08:31:12

自動配置熱部署DevTools

2016-09-29 15:44:18

開源上網(wǎng)管理

2023-01-06 09:19:12

Seata分布式事務

2011-04-13 11:33:37

HSRP
點贊
收藏

51CTO技術棧公眾號

日本不卡一二三| 亚洲黄色在线播放| 手机在线电影一区| 欧美tk丨vk视频| 免费黄色福利视频| 国产网友自拍视频导航网站在线观看| 福利视频网站一区二区三区| 91成人在线观看国产| 久久久久麻豆v国产| 国产91精品入| 欧美丰满少妇xxxxx高潮对白| 一卡二卡三卡视频| 伊人免费在线| 久久久精品天堂| 国产传媒一区二区三区| 中文在线最新版天堂| 亚洲特级毛片| 俺也去精品视频在线观看| 美女露出粉嫩尿囗让男人桶| 激情小说亚洲| 狠狠做深爱婷婷久久综合一区| 久久久一二三四| 黄色av网站在线看| 97久久超碰国产精品电影| 91免费的视频在线播放| 久久精品偷拍视频| 欧美亚洲免费| 国语自产在线不卡| 久草国产在线视频| 久久精品欧美一区| 中国china体内裑精亚洲片| 国产网站无遮挡| 国产精品sss在线观看av| 欧美男男青年gay1069videost| 成人小视频在线看| 国产99在线观看| 亚洲高清免费观看高清完整版在线观看| 亚洲欧洲一区二区| 国产乱子伦三级在线播放| 99re在线精品| 国产一区二区三区四区hd| 亚洲成人777777| 国产精品538一区二区在线| 国产欧美精品久久久| 亚洲无码精品一区二区三区| 亚洲在线观看| 欧美一区二区三区……| 欧美三级韩国三级日本三斤在线观看 | 一本久道中文字幕精品亚洲嫩| 亚洲人精品午夜射精日韩| 国产羞羞视频在线播放| 亚洲综合一区在线| 日b视频免费观看| 性网站在线观看| 伊人一区二区三区| 丁香六月激情婷婷| 国产夫妻在线播放| 一本久道中文字幕精品亚洲嫩| 日韩a在线播放| 成人日韩在线| 在线观看91精品国产麻豆| 91看片破解版| 视频精品二区| 亚洲精品久久在线| 夜夜春很很躁夜夜躁| 久久精品国产亚洲夜色av网站| 视频一区视频二区国产精品| 老湿机69福利| 在线精品亚洲| 国产成人精品视频在线观看| 人妻中文字幕一区二区三区| 久草热8精品视频在线观看| 91久久国产综合久久91精品网站| 不卡的日韩av| 99re视频精品| 亚洲国产午夜伦理片大全在线观看网站| 999在线视频| 一区二区三区中文在线观看| 久久视频这里有精品| 国产日韩另类视频一区| 欧美日韩国产精品成人| 久久久久亚洲AV成人网人人小说| 日韩在线麻豆| www.亚洲人.com| 成人免费精品动漫网站| 99成人免费视频| 国产精品丝袜久久久久久高清 | 蜜桃网站在线观看| 阿v视频在线| 欧美老人xxxx18| 日本黄色录像片| 手机在线电影一区| 午夜精品视频在线| 国产又粗又长又大视频| 成人av午夜电影| 色一情一乱一伦一区二区三区丨 | 日韩综合一区| 97精品伊人久久久大香线蕉| 中文在线观看av| 99国产欧美久久久精品| 亚洲一区二区三区涩| www.九色在线| 欧美一级日韩不卡播放免费| 法国伦理少妇愉情| 国产一区美女| 成人黄色av网站| 国外av在线| 亚洲无人区一区| 中文字幕成人免费视频| 日韩高清成人在线| 久久成人综合视频| 性色av一区二区三区四区| 成人午夜激情在线| 中文字幕成人一区| 欧美三区四区| 亚洲精品理论电影| 成人免费看片98| 精品亚洲免费视频| 日本免费高清一区二区| av剧情在线观看| 日韩一级大片在线观看| 久久一级免费视频| 天堂久久久久va久久久久| 国产精品v欧美精品∨日韩| 老司机福利在线视频| 一本色道久久综合亚洲精品按摩| 国产婷婷在线观看| 欧美午夜不卡| 91在线免费视频| 亚洲搞黄视频| 欧美三级三级三级爽爽爽| 国产亚洲精品熟女国产成人| 国产人成精品一区二区三| 国产激情美女久久久久久吹潮| 国产在线激情| 欧美久久久久免费| 青青草自拍偷拍| 人人精品人人爱| 日韩影片在线播放| 456成人影院在线观看| 亚洲欧美一区二区三区情侣bbw| 在线看成人av| 99精品视频免费在线观看| 国产在线播放观看| 美女视频免费精品| 18性欧美xxxⅹ性满足| 姝姝窝人体www聚色窝| 五月天国产精品| 国产成人无码一区二区在线观看| 一本色道久久综合亚洲精品高清| 久久精品ww人人做人人爽| 色老头在线一区二区三区| 日韩精品视频在线免费观看| 午夜毛片在线观看| 久久网这里都是精品| www.国产区| 成人综合久久| 成人a级免费视频| 主播国产精品| 欧美精品一区二区三区一线天视频 | 少妇性l交大片7724com| 午夜日韩福利| 精品麻豆av| 午夜精品成人av| 日韩视频免费中文字幕| 亚洲第一黄色片| 五月天丁香久久| 日本少妇xxxxx| 国产最新精品免费| 国产成人一区二区三区别| 欧美wwwsss9999| 国产精品国产三级国产aⅴ9色 | 日韩精品中文字幕第1页| 成人午夜两性视频| 97天天综合网| 中文字幕精品av| www.国产视频| 一本一本大道香蕉久在线精品| 91久久久久久久久久久久久久| 国产成人激情av| 国内外成人免费激情视频| 欧美国产偷国产精品三区| 99国产在线观看| 在线看欧美视频| 欧美成人精品在线播放| 日本一级在线观看| 欧美乱妇20p| 久久露脸国语精品国产91| 亚洲国产精品二十页| 俄罗斯黄色录像| 日韩电影在线观看网站| 亚洲爆乳无码精品aaa片蜜桃| 一本久久青青| 999国产视频| 国产91欧美| 69国产精品成人在线播放| 老司机福利在线视频| 国产视频一区在线| 国产超碰人人模人人爽人人添| 色欧美乱欧美15图片| 欧美黄色免费在线观看| 国产免费成人在线视频| 国产精品入口麻豆| 国产在线精品一区二区| 日本黄色三级大片| 影音先锋久久久| 自拍另类欧美| 日本久久综合| 免费国产在线精品一区二区三区| 久久精品一级| 成人黄在线观看| 亚洲高清黄色| **欧美日韩vr在线| √最新版天堂资源网在线| 美女扒开尿口让男人操亚洲视频网站| 九色网友自拍视频手机在线| 亚洲高清免费观看高清完整版| 国产不卡精品视频| 4438成人网| 在线观看毛片网站| 在线影视一区二区三区| 97久久久久久久| 午夜久久久久久久久久一区二区| 加勒比婷婷色综合久久| 国产精品久久网站| 成人午夜免费影院| 国产精品美女久久久久久久| 日本少妇高潮喷水xxxxxxx| 99久久精品费精品国产一区二区| 苍井空张开腿实干12次| 国产精品18久久久久| 日本精品一区在线| 精品一区二区三区免费| 亚洲综合婷婷久久| 美女久久久精品| 无限资源日本好片| 日本成人在线不卡视频| 色七七在线观看| 日本欧美一区二区在线观看| 成人在线免费播放视频| 久久精品一区| 婷婷激情四射五月天| 日韩精品成人一区二区三区| www.日日操| 奇米综合一区二区三区精品视频| 无码少妇一区二区三区芒果| 久久综合九色综合欧美狠狠| aaa毛片在线观看| 丝袜美腿亚洲综合| 久久精品影视大全| 久久精品国产亚洲高清剧情介绍 | 久久黄色av网站| 精品黄色免费中文电影在线播放| 久久精品国产精品| 香蕉成人app免费看片| 欧美日韩成人在线播放| 日韩另类在线| 国产91精品黑色丝袜高跟鞋| 欧美羞羞视频| 国产精品视频一区国模私拍 | 波多野结衣不卡视频| 亚洲久本草在线中文字幕| 免费视频网站www| 亚洲国产人成综合网站| 午夜影院免费在线观看| 欧美亚洲综合另类| 国产高清在线免费| 日韩av最新在线| av一区在线观看| 九九久久久久久久久激情| 九色porny自拍视频在线观看 | 久久99国产精品自在自在app | 日韩亚洲欧美在线观看| 日本美女一级视频| 亚洲丝袜一区在线| 国产原创视频在线观看| 91av视频在线| 欧美日韩国产网站| 国产精品国产精品| 国产欧美日韩精品一区二区三区 | 69xxx免费| 亚洲综合图片区| 波多野结衣视频在线观看| 欧美一级在线视频| 国产三级电影在线| 久久777国产线看观看精品| 日韩av福利| 亚洲影视九九影院在线观看| 青青草成人激情在线| 日韩性xxxx| 亚洲欧美中文字幕在线一区| 日本www在线| 午夜精品视频在线| 欧美成人家庭影院| 激情五月综合色婷婷一区二区| 欧美一级淫片| 九色自拍视频在线观看| 老司机精品视频在线| 亚洲精品视频中文字幕| 国外av在线| 欧美精品第一页在线播放| 韩国主播福利视频一区二区三区| 成人羞羞视频播放网站| 国产麻豆日韩| 99久久这里只有精品| 自慰无码一区二区三区| 国内不卡的二区三区中文字幕| 成人免费网站黄| 亚洲午夜免费电影| 国产免费高清av| 中文字幕av一区中文字幕天堂 | 91麻豆国产自产在线观看亚洲| 激情伊人五月天| 国产激情91久久精品导航| 熟女少妇内射日韩亚洲| 狠狠久久亚洲欧美专区| 亚洲精品.www| 欧美乱人伦中文字幕在线| 日韩成人高清| 欧美一区观看| 国产精品入口| 六十路息与子猛烈交尾| 一区二区三区中文免费| av免费在线不卡| 另类天堂视频在线观看| 日本免费成人| 亚洲草草视频| 日韩高清一区二区| www.av天天| 一本久久综合亚洲鲁鲁五月天| 天天色综合久久| 国内揄拍国内精品少妇国语| 亚洲不卡视频| 激情五月六月婷婷| 国产.欧美.日韩| 国产在线视频卡一卡二| 精品美女在线观看| 好看的中文字幕在线播放| 99精品国产高清一区二区| 欧美黄在线观看| 国产成人精品综合久久久久99 | 虎白女粉嫩尤物福利视频| 26uuu久久天堂性欧美| 国语对白永久免费| 亚洲男女性事视频| 最新日韩三级| 亚洲人成网站在线观看播放| 麻豆高清免费国产一区| 日韩在线视频网址| 欧美一区二区三区不卡| 视频在线观看入口黄最新永久免费国产| 亚洲精品欧美极品| 国产精品v亚洲精品v日韩精品| 美女搡bbb又爽又猛又黄www| 午夜免费久久看| 激情小视频在线| 国产精品一区二区三区久久| 久久久久久久久久久妇女| 日韩a一级欧美一级| 一区二区久久久久久| 天天操天天干天天干| 日本欧美一级片| 国产二区精品| 成年人小视频在线观看| 欧美日韩国产精品一区| 国产粉嫩一区二区三区在线观看| 国产剧情日韩欧美| 国一区二区在线观看| 国产网站无遮挡| 欧美日韩国产一二三| 污视频免费在线观看| 黄色99视频| 久久精品国产在热久久| 免费观看一级视频| 亚洲午夜未删减在线观看| 91精品网站在线观看| 成人免费视频91| 欧美激情一区不卡| 成 人 免费 黄 色| 国产成人激情视频| 一区二区国产在线| 法国伦理少妇愉情| 日韩午夜在线播放| 欧美大片免费| 欧美性猛交内射兽交老熟妇| 久久免费精品国产久精品久久久久| 91精品国产乱码久久久| 97视频在线观看视频免费视频| 成人国产精品一级毛片视频| 日本一区二区在线观看视频| 欧美在线制服丝袜| av免费不卡国产观看| 亚洲制服欧美久久| 久久亚洲综合av| www.爱爱.com| 国产精品一区久久久| 日韩网站在线| 黄色在线观看免费| 在线视频精品一| 台湾佬综合网|