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

聊聊防御式編程

開發 前端
防御式編程的核心思想是:程序應該能夠在面對非法輸入、異常環境或其他意外情況時,依然能夠保持穩定運行,或者以可控的方式失敗。有些小伙伴在工作中可能會說:"我的代碼已經處理了所有正常情況,為什么還需要防御?"

前言

有些小伙伴在工作中,可能經常遇到這樣的場景:線上系統突然崩潰,排查發現是因為一個預料之外的輸入參數;或者用戶反饋某個功能異常,最終定位到是外部服務返回了異常數據。

這些問題往往不是核心邏輯的錯誤,而是因為我們沒有做好充分的防御。

作為一名老司機,我見證過太多因為缺乏防御意識導致的線上事故。

今天我就從淺入深,帶你徹底掌握防御式編程的精髓,希望對你會有所幫助。

1. 什么是防御式編程?

在深入具體技術之前,我們先明確防御式編程的概念。

防御式編程不是一種具體的技術,而是一種編程哲學和思維方式。

核心理念

防御式編程的核心思想是:程序應該能夠在面對非法輸入、異常環境或其他意外情況時,依然能夠保持穩定運行,或者以可控的方式失敗。

有些小伙伴在工作中可能會說:"我的代碼已經處理了所有正常情況,為什么還需要防御?"

這是因為在復雜的生產環境中,我們無法預知所有可能的情況:

  • 用戶可能輸入我們未曾預料的數據
  • 外部服務可能返回異常響應
  • 網絡可能突然中斷
  • 磁盤可能空間不足
  • 內存可能耗盡

為什么需要防御式編程?

從架構師的角度看,防御式編程的價值體現在:

  • 提高系統穩定性:減少因邊緣情況導致的系統崩潰
  • 提升可維護性:清晰的錯誤處理讓問題定位更簡單
  • 增強用戶體驗:優雅的降級比直接崩潰更好
  • 降低維護成本:預防性代碼減少線上緊急修復

讓我們通過一個簡單的例子來感受防御式編程的差異:

// 非防御式編程
public class UserService {
    public void updateUserAge(User user, int newAge) {
        user.setAge(newAge);  // 如果user為null,這里會拋出NPE
        userRepository.save(user);
    }
}

// 防御式編程
public class UserService {
    public void updateUserAge(User user, int newAge) {
        if (user == null) {
            log.warn("嘗試更新年齡時用戶對象為空");
            return;
        }
        
        if (newAge < 0 || newAge > 150) {
            log.warn("無效的年齡輸入: {}", newAge);
            throw new IllegalArgumentException("年齡必須在0-150之間");
        }
        
        user.setAge(newAge);
        userRepository.save(user);
    }
}

看到區別了嗎?

防御式編程讓我們提前發現問題,而不是等到異常發生。

好了,讓我們開始今天的主菜。

我將從最基本的參數校驗,逐步深入到復雜的系統級防御,確保每個知識點都講透、講懂。

2.防御式編程的核心原則

防御式編程不是隨意地添加if判斷,而是有章可循的。

下面我總結了幾大核心原則。

原則一:對輸入保持懷疑態度

這是防御式編程的第一原則:永遠不要信任任何外部輸入

無論是用戶輸入、外部API響應、還是配置文件,都應該進行驗證。

示例代碼

public class UserRegistrationService {
    
    // 非防御式寫法
    public void registerUser(String username, String email, Integer age) {
        User user = new User(username, email, age);
        userRepository.save(user);
    }
    
    // 防御式寫法
    public void registerUserDefensive(String username, String email, Integer age) {
        // 1. 檢查必需參數
        if (StringUtils.isBlank(username)) {
            throw new IllegalArgumentException("用戶名不能為空");
        }
        
        if (StringUtils.isBlank(email)) {
            throw new IllegalArgumentException("郵箱不能為空");
        }
        
        if (age == null) {
            throw new IllegalArgumentException("年齡不能為空");
        }
        
        // 2. 檢查參數格式
        if (username.length() < 3 || username.length() > 20) {
            throw new IllegalArgumentException("用戶名長度必須在3-20個字符之間");
        }
        
        if (!isValidEmail(email)) {
            throw new IllegalArgumentException("郵箱格式不正確");
        }
        
        // 3. 檢查業務規則
        if (age < 0 || age > 150) {
            throw new IllegalArgumentException("年齡必須在0-150之間");
        }
        
        if (userRepository.existsByUsername(username)) {
            throw new IllegalArgumentException("用戶名已存在");
        }
        
        // 4. 執行業務邏輯
        User user = new User(username.trim(), email.trim().toLowerCase(), age);
        userRepository.save(user);
    }
    
    private boolean isValidEmail(String email) {
        String emailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$";
        return email != null && email.matches(emailRegex);
    }
}

深度剖析

有些小伙伴在工作中可能會覺得這些校驗很繁瑣,但其實它們各自有重要作用:

  • 空值檢查:防止NPE,這是Java中最常見的異常
  • 格式驗證:確保數據符合預期格式,避免后續處理出錯
  • 業務規則驗證:在數據進入核心業務前就發現問題
  • 數據清理:去除前后空格、統一格式等

重要原則:校驗要盡早進行,在數據進入系統邊界時就完成驗證。

為了更直觀理解輸入驗證的層次,我畫了一個驗證流程圖:

圖片圖片

原則二:善用斷言和異常

斷言和異常是防御式編程的重要工具,但它們的使用場景有所不同。

斷言(Assertions)

斷言用于檢查在代碼正確的情況下永遠不應該發生的條件。

public class Calculator {
    
    public double divide(double dividend, double divisor) {
        // 使用斷言檢查內部不變性
        assert divisor != 0 : "除數不能為0,這應該在調用前被檢查";
        
        // 但對外部輸入,我們仍然需要正常檢查
        if (divisor == 0) {
            thrownew IllegalArgumentException("除數不能為0");
        }
        
        return dividend / divisor;
    }
    
    public void processPositiveNumber(int number) {
        // 這個斷言表達:這個方法只應該處理正數
        // 如果傳入負數,說明調用方有bug
        assert number > 0 : "輸入必須為正數: " + number;
        
        // 業務邏輯
    }
}

注意:Java斷言默認是關閉的,需要通過-ea參數啟用。在生產環境中,通常不建議依賴斷言。

異常處理

異常應該根據情況分層處理:

public class FileProcessor {
    
    // 不好的異常處理
    public void processFile(String filePath) {
        try {
            String content = Files.readString(Path.of(filePath));
            // 處理內容...
        } catch (Exception e) {  // 捕獲過于寬泛
            e.printStackTrace(); // 在生產環境中無效
        }
    }
    
    // 好的異常處理
    public void processFileDefensive(String filePath) {
        // 1. 參數校驗
        if (StringUtils.isBlank(filePath)) {
            throw new IllegalArgumentException("文件路徑不能為空");
        }
        
        try {
            // 2. 讀取文件
            String content = Files.readString(Path.of(filePath));
            
            // 3. 處理內容
            processContent(content);
            
        } catch (NoSuchFileException e) {
            log.error("文件不存在: {}", filePath, e);
            throw new BusinessException("文件不存在: " + filePath, e);
        } catch (AccessDeniedException e) {
            log.error("沒有文件訪問權限: {}", filePath, e);
            throw new BusinessException("沒有文件訪問權限: " + filePath, e);
        } catch (IOException e) {
            log.error("讀取文件失敗: {}", filePath, e);
            throw new BusinessException("讀取文件失敗: " + filePath, e);
        }
    }
    
    private void processContent(String content) {
        if (StringUtils.isBlank(content)) {
            log.warn("文件內容為空");
            return;
        }
        
        try {
            // 解析JSON等可能拋出異常的操作
            JsonObject json = JsonParser.parseString(content).getAsJsonObject();
            // 處理JSON...
        } catch (JsonSyntaxException e) {
            log.error("文件內容不是有效的JSON", e);
            throw new BusinessException("文件格式不正確", e);
        }
    }
}

深度剖析

有些小伙伴在工作中可能會混淆檢查型異常和非檢查型異常的使用場景:

  • 檢查型異常:調用方應該能夠預期并處理的異常(如IOException)
  • 非檢查型異常:通常是編程錯誤,調用方不應該捕獲(如IllegalArgumentException)

最佳實踐

  • 使用具體的異常類型,而不是通用的Exception
  • 提供有意義的錯誤信息
  • 保持異常鏈,不要丟失根因
  • 在系統邊界處統一處理異常

原則三:資源管理和清理

資源泄漏是系統不穩定的常見原因。

防御式編程要求我們確保資源被正確釋放。

示例代碼

public class ResourceService {
    
    // 不好的資源管理
    public void copyFileUnsafe(String sourcePath, String targetPath) throws IOException {
        FileInputStream input = new FileInputStream(sourcePath);
        FileOutputStream output = new FileOutputStream(targetPath);
        
        byte[] buffer = newbyte[1024];
        int length;
        while ((length = input.read(buffer)) > 0) {
            output.write(buffer, 0, length);
        }
        
        // 如果中間拋出異常,資源不會被關閉!
        input.close();
        output.close();
    }
    
    // 傳統的防御式資源管理
    public void copyFileTraditional(String sourcePath, String targetPath) throws IOException {
        FileInputStream input = null;
        FileOutputStream output = null;
        
        try {
            input = new FileInputStream(sourcePath);
            output = new FileOutputStream(targetPath);
            
            byte[] buffer = newbyte[1024];
            int length;
            while ((length = input.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
            
        } finally {
            // 確保資源被關閉
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    log.error("關閉輸入流失敗", e);
                }
            }
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    log.error("關閉輸出流失敗", e);
                }
            }
        }
    }
    
    // 使用try-with-resources(推薦)
    public void copyFileModern(String sourcePath, String targetPath) throws IOException {
        try (FileInputStream input = new FileInputStream(sourcePath);
             FileOutputStream output = new FileOutputStream(targetPath)) {
            
            byte[] buffer = newbyte[1024];
            int length;
            while ((length = input.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
        } // 資源會自動關閉,即使拋出異常
    }
    
    // 復雜資源管理場景
    public void processWithMultipleResources() {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        
        try {
            conn = dataSource.getConnection();
            stmt = conn.prepareStatement("SELECT * FROM users WHERE age > ?");
            stmt.setInt(1, 18);
            rs = stmt.executeQuery();
            
            while (rs.next()) {
                // 處理結果
            }
            
        } catch (SQLException e) {
            log.error("數據庫操作失敗", e);
            throw new BusinessException("數據查詢失敗", e);
        } finally {
            // 按創建順序的逆序關閉資源
            closeQuietly(rs);
            closeQuietly(stmt);
            closeQuietly(conn);
        }
    }
    
    private void closeQuietly(AutoCloseable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (Exception e) {
                log.warn("關閉資源時發生異常", e);
                // 靜默處理,不掩蓋主要異常
            }
        }
    }
}

深度剖析

有些小伙伴在工作中可能沒有意識到,資源管理不當會導致:

  1. 文件句柄泄漏:最終導致"Too many open files"錯誤
  2. 數據庫連接泄漏:連接池耗盡,系統無法響應
  3. 內存泄漏:對象無法被GC回收

防御式資源管理要點

  • 使用try-with-resources(Java 7+)
  • 在finally塊中關閉資源
  • 關閉資源時處理可能的異常
  • 按創建順序的逆序關閉資源

為了理解資源管理的正確流程,我畫了一個資源生命周期圖:

圖片圖片

防御式編程的高級技巧

掌握了基本原則后,我們來看看一些高級的防御式編程技巧。

使用Optional避免空指針

Java 8引入的Optional是防御空指針的利器。

public class OptionalExample {
    
    // 不好的做法:多層null檢查
    public String getUserEmailBad(User user) {
        if (user != null) {
            Profile profile = user.getProfile();
            if (profile != null) {
                Contact contact = profile.getContact();
                if (contact != null) {
                    return contact.getEmail();
                }
            }
        }
        return null;
    }
    
    // 使用Optional的防御式寫法
    public Optional<String> getUserEmailGood(User user) {
        return Optional.ofNullable(user)
                .map(User::getProfile)
                .map(Profile::getContact)
                .map(Contact::getEmail)
                .filter(email -> !email.trim().isEmpty());
    }
    
    // 使用方法
    public void processUser(User user) {
        Optional<String> emailOpt = getUserEmailGood(user);
        
        // 方式1:如果有值才處理
        emailOpt.ifPresent(email -> {
            sendNotification(email, "歡迎使用我們的服務");
        });
        
        // 方式2:提供默認值
        String email = emailOpt.orElse("default@example.com");
        
        // 方式3:如果沒有值,拋出特定異常
        String requiredEmail = emailOpt.orElseThrow(() -> 
            new BusinessException("用戶郵箱不能為空")
        );
    }
}

不可變對象的防御價值

不可變對象天生具有防御性,因為它們的狀態在創建后就不能被修改。

// 可變對象 - 容易在不知情的情況下被修改
public class MutableConfig {
    private Map<String, String> settings = new HashMap<>();
    
    public Map<String, String> getSettings() {
        return settings; // 危險!調用方可以修改內部狀態
    }
    
    public void setSettings(Map<String, String> settings) {
        this.settings = settings; // 危險!外部map的修改會影響內部
    }
}

// 不可變對象 - 防御式設計
public final class ImmutableConfig {
    private final Map<String, String> settings;
    
    public ImmutableConfig(Map<String, String> settings) {
        // 防御性拷貝
        this.settings = Collections.unmodifiableMap(new HashMap<>(settings));
    }
    
    public Map<String, String> getSettings() {
        // 返回不可修改的視圖
        return settings;
    }
    
    // 沒有setter方法,對象創建后不可變
}

// 使用Builder模式創建復雜不可變對象
public final class User {
    private final String username;
    private final String email;
    private final int age;
    
    private User(String username, String email, int age) {
        this.username = username;
        this.email = email;
        this.age = age;
    }
    
    // getters...
    
    public static class Builder {
        private String username;
        private String email;
        private int age;
        
        public Builder username(String username) {
            this.username = Objects.requireNonNull(username, "用戶名不能為空");
            return this;
        }
        
        public Builder email(String email) {
            this.email = Objects.requireNonNull(email, "郵箱不能為空");
            if (!isValidEmail(email)) {
                throw new IllegalArgumentException("郵箱格式不正確");
            }
            return this;
        }
        
        public Builder age(int age) {
            if (age < 0 || age > 150) {
                throw new IllegalArgumentException("年齡必須在0-150之間");
            }
            this.age = age;
            return this;
        }
        
        public User build() {
            // 在build時進行最終驗證
            if (username == null || email == null) {
                throw new IllegalStateException("用戶名和郵箱必須設置");
            }
            return new User(username, email, age);
        }
    }
}

深度剖析

有些小伙伴在工作中可能覺得不可變對象創建麻煩,但它們帶來的好處是巨大的:

  1. 線程安全:無需同步,可以在多線程間安全共享
  2. 易于緩存:可以安全地緩存,因為狀態不會改變
  3. 避免意外的狀態修改:不會被其他代碼意外修改
  4. 簡化推理:對象的狀態是確定的

系統級的防御式編程

除了代碼層面的防御,我們還需要在系統架構層面考慮防御措施。

斷路器模式

在微服務架構中,斷路器是重要的防御機制。

// 簡化的斷路器實現
public class CircuitBreaker {
    private final String name;
    private final int failureThreshold;
    private final long timeout;
    
    private State state = State.CLOSED;
    private int failureCount = 0;
    private long lastFailureTime = 0;
    
    enum State { CLOSED, OPEN, HALF_OPEN }
    
    public CircuitBreaker(String name, int failureThreshold, long timeout) {
        this.name = name;
        this.failureThreshold = failureThreshold;
        this.timeout = timeout;
    }
    
    public <T> T execute(Supplier<T> supplier) {
        if (state == State.OPEN) {
            // 檢查是否應該嘗試恢復
            if (System.currentTimeMillis() - lastFailureTime > timeout) {
                state = State.HALF_OPEN;
                log.info("斷路器 {} 進入半開狀態", name);
            } else {
                throw new CircuitBreakerOpenException("斷路器開啟,拒絕請求");
            }
        }
        
        try {
            T result = supplier.get();
            
            // 請求成功,重置狀態
            if (state == State.HALF_OPEN) {
                state = State.CLOSED;
                failureCount = 0;
                log.info("斷路器 {} 恢復關閉狀態", name);
            }
            
            return result;
            
        } catch (Exception e) {
            handleFailure();
            throw e;
        }
    }
    
    private void handleFailure() {
        failureCount++;
        lastFailureTime = System.currentTimeMillis();
        
        if (state == State.HALF_OPEN || failureCount >= failureThreshold) {
            state = State.OPEN;
            log.warn("斷路器 {} 開啟,失敗次數: {}", name, failureCount);
        }
    }
}

// 使用示例
public class UserServiceWithCircuitBreaker {
    private final CircuitBreaker circuitBreaker;
    private final RemoteUserService remoteService;
    
    public UserServiceWithCircuitBreaker() {
        this.circuitBreaker = new CircuitBreaker("UserService", 5, 60000);
        this.remoteService = new RemoteUserService();
    }
    
    public User getUser(String userId) {
        return circuitBreaker.execute(() -> remoteService.getUser(userId));
    }
}

限流和降級

// 簡單的令牌桶限流
public class RateLimiter {
    private final int capacity;
    private final int tokensPerSecond;
    private double tokens;
    private long lastRefillTime;
    
    public RateLimiter(int capacity, int tokensPerSecond) {
        this.capacity = capacity;
        this.tokensPerSecond = tokensPerSecond;
        this.tokens = capacity;
        this.lastRefillTime = System.nanoTime();
    }
    
    public synchronized boolean tryAcquire() {
        refill();
        if (tokens >= 1) {
            tokens -= 1;
            returntrue;
        }
        returnfalse;
    }
    
    private void refill() {
        long now = System.nanoTime();
        double seconds = (now - lastRefillTime) / 1e9;
        tokens = Math.min(capacity, tokens + seconds * tokensPerSecond);
        lastRefillTime = now;
    }
}

// 使用限流和降級
public class OrderService {
    private final RateLimiter rateLimiter;
    private final PaymentService paymentService;
    
    public OrderService() {
        this.rateLimiter = new RateLimiter(100, 10); // 100容量,每秒10個令牌
        this.paymentService = new PaymentService();
    }
    
    public PaymentResult processPayment(Order order) {
        // 限流檢查
        if (!rateLimiter.tryAcquire()) {
            log.warn("系統繁忙,觸發限流");
            return PaymentResult.rateLimited();
        }
        
        try {
            return paymentService.process(order);
        } catch (Exception e) {
             log.error("支付服務異常,觸發降級", e);
            // 降級策略:返回排隊中狀態
            return PaymentResult.queued();
        }
    }
}

防御式編程的陷阱與平衡

防御式編程不是越多越好,過度防御也會帶來問題。

避免過度防御

// 過度防御的例子
public class OverDefensiveExample {
    
    // 過多的null檢查,使代碼難以閱讀
    public String processData(String data) {
        if (data == null) {
            returnnull;
        }
        
        String trimmed = data.trim();
        if (trimmed.isEmpty()) {
            return"";
        }
        
        // 即使知道trimmed不為空,還是繼續檢查...
        if (trimmed.length() > 1000) {
            log.warn("數據過長: {}", trimmed.length());
            // 但仍然繼續處理...
        }
        
        // 更多的檢查...
        return trimmed.toUpperCase();
    }
}

// 適度防御的例子
public class BalancedDefensiveExample {
    
    public String processData(String data) {
        // 在方法入口處統一驗證
        if (StringUtils.isBlank(data)) {
            return"";
        }
        
        String trimmed = data.trim();
        
        // 核心業務邏輯,假設數據現在是有效的
        return transformData(trimmed);
    }
    
    private String transformData(String data) {
        // 內部方法可以假設輸入是有效的
        if (data.length() > 1000) {
            // 記錄日志但繼續處理
            log.info("處理長數據: {}", data.length());
        }
        
        return data.toUpperCase();
    }
}

性能考量

防御性檢查會帶來性能開銷,需要在關鍵路徑上權衡。

public class PerformanceConsideration {
    
    // 在性能敏感的方法中,可以延遲驗證
    public void processBatch(List<String> items) {
        // 先快速處理,最后統一驗證
        List<String> results = new ArrayList<>();
        
        for (String item : items) {
            // 最小化的必要檢查
            if (item != null) {
                results.add(processItemFast(item));
            }
        }
        
        // 批量驗證結果
        validateResults(results);
    }
    
    private String processItemFast(String item) {
        // 假設這個方法很快,不做詳細驗證
        return item.toUpperCase();
    }
}

總結

經過以上詳細剖析,相信你對防御式編程有了更深入的理解。

下面是我總結的一些實用建議:

核心原則

  1. 對輸入保持懷疑:驗證所有外部輸入
  2. 明確失敗:讓失敗盡早發生,提供清晰的錯誤信息
  3. 資源安全:確保資源被正確釋放
  4. 優雅降級:在部分失敗時保持系統可用
  5. 適度防御:避免過度防御導致的代碼復雜

實踐指南

場景

防御措施

示例

方法參數

入口驗證

Objects.requireNonNull()

外部調用

異常處理

try-catch特定異常

資源操作

自動清理

try-with-resources

并發訪問

不可變對象

final字段、防御性拷貝

系統集成

斷路器

失敗閾值、超時控制

高并發

限流降級

令牌桶、服務降級

我的建議

有些小伙伴在工作中,可能一開始覺得防御式編程增加了代碼量,但從長期來看,它的收益是巨大的:

  1. 投資思維:前期的一點投入,避免后期的大規模故障
  2. 團隊共識:在團隊中建立防御式編程的文化和規范
  3. 工具支持:使用靜態分析工具發現潛在問題
  4. 代碼審查:在CR中重點關注防御性措施

記住,防御式編程的目標不是創建"完美"的代碼。

而是創建健壯的代碼——能夠在面對意外時依然保持穩定的代碼。

責任編輯:武曉燕 來源: 蘇三說技術
相關推薦

2016-11-23 13:46:08

Android

2025-05-06 00:12:10

2022-01-25 07:44:15

CSS防御式 CSSFlexbox

2021-08-10 19:15:17

語言編程應用

2021-06-02 09:01:19

JavaScript 前端異步編程

2023-04-02 17:53:10

多線程編程自測

2023-07-03 09:59:00

并發編程并發容器

2022-12-11 20:09:50

網絡編程通信

2025-07-11 01:24:00

C++防御性編程

2022-08-02 20:21:42

開源項目工具

2022-02-08 08:12:51

無鎖編程設計

2023-08-10 08:28:46

網絡編程通信

2023-12-15 08:17:13

防御性編程代碼

2021-06-15 11:16:24

網絡安全U盤軟件

2022-06-13 10:01:36

Apollo攜程框架

2023-02-10 00:04:53

2025-03-06 11:30:15

2024-04-24 12:34:08

Spring事務編程

2022-11-02 09:00:02

編程語言拓荒者

2021-11-08 07:41:16

Go流水線編程
點贊
收藏

51CTO技術棧公眾號

蜜桃av噜噜一区二区三区| 国产亚洲免费的视频看| 大荫蒂性生交片| 手机看片福利永久| 七七婷婷婷婷精品国产| 啊v视频在线一区二区三区| 色哟哟免费视频| 成人av观看| 亚洲精品国产无天堂网2021| 国产青春久久久国产毛片| 中国a一片一级一片| 国内自拍视频一区二区三区| 亚洲视频免费一区| 国产欧美视频一区| 免费成人高清在线视频| 久久天天久久| 韩国v欧美v亚洲v日本v| 68精品国产免费久久久久久婷婷| 毛片aaaaaa| 鲁大师精品99久久久| 精品视频123区在线观看| 成人性免费视频| 欧美三级黄网| 久久亚区不卡日本| 国产精品yjizz| 中文字幕视频二区| 久久精品30| 国语自产在线不卡| 暗呦丨小u女国产精品| 九九视频免费观看视频精品| 亚洲电影免费观看高清完整版在线观看 | 久久久久久国产免费| 在线观看亚洲大片短视频| 欧美理伦片在线播放| 日韩一区二区免费视频| jizzzz日本| 精品免费av在线 | 国产91沈先生在线播放| 一区二区xxx| 久久亚洲天堂网| 国产精品观看| 欧美成人精品三级在线观看| 国产黄色录像视频| 在线日本制服中文欧美| 精品视频久久久久久久| 中文字幕乱码一区| 第四色中文综合网| 精品久久久三级丝袜| 熟妇无码乱子成人精品| 91成人福利社区| 欧美日本一区二区在线观看| 天天综合网日韩| 成人国产激情在线| 欧美日韩一二三区| 激情五月俺来也| 成人在线中文| 欧美精品 国产精品| 奇米视频888| av成人在线网站| 欧美一区二区免费观在线| 中文字幕在线视频一区二区三区| 亚洲老司机网| 欧美一区二区三区在线观看| 秋霞午夜鲁丝一区二区| 一区中文字幕电影| 亚洲国产成人在线视频| 国产精品揄拍100视频| 精品一区在线| 日韩在线视频一区| 成年人av电影| 99国产精品久久久久久久| 91av在线国产| 日韩欧美国产另类| 久久成人久久爱| 91中文字幕在线| 日本国产在线观看| 久久免费电影网| 综合久久国产| 爱情岛亚洲播放路线| 天天操天天综合网| 色国产在线视频| 少妇人妻无码专区视频| 国产高清在线a视频大全| 婷婷久久综合九色综合伊人色| 国产午夜福利在线播放| 亚洲日本在线观看视频| 欧美一区二区三区四区高清| 男人网站在线观看| 不卡中文一二三区| 欧美日本精品在线| 中文字幕免费观看| 国产一区二区久久| 精品久久一区二区三区蜜桃| www.av在线| 亚洲福中文字幕伊人影院| 人人爽人人av| 日韩高清一区| 亚洲人成在线播放| 欧美另类视频在线观看| 日韩中文字幕av电影| 91美女片黄在线观看游戏| 欧美一级性视频| 国产精品久久久久久久蜜臀| 又大又硬又爽免费视频| 国产成+人+综合+亚洲欧美| 精品久久免费看| 中文字幕观看av| 亚洲一区一卡| 97视频中文字幕| www亚洲人| 婷婷成人综合网| 福利视频999| 国产一区二区三区91| 欧美激情区在线播放| 伊人色综合久久久| 91蜜桃传媒精品久久久一区二区| 四虎精品欧美一区二区免费| 欧美亚洲韩国| 亚洲国产91精品在线观看| 91日韩中文字幕| 日本一不卡视频| 婷婷六月综合网| 法国空姐在线观看免费| 亚洲人免费短视频| 亚洲第一区第二区| 欧美极品视频在线观看| 蜜桃91丨九色丨蝌蚪91桃色| 久久久人人爽| www在线观看黄色| 精品久久久影院| 青青草偷拍视频| 精品一区二区久久| 亚洲精品一区二| 日韩在线影院| 日韩精品免费在线视频观看| 久草精品视频在线观看| 国产精品一区二区三区四区| 欧美 日韩 国产 在线观看| 视频一区在线免费看| 亚洲日本aⅴ片在线观看香蕉| 亚洲激情视频一区| 高潮精品一区videoshd| 在线观看污视频| 国产精品一区二区精品| 日韩亚洲一区二区| 中文字幕有码视频| 国产精品久久久久久久裸模| 国产三级三级三级看三级| 国精一区二区| 国产精品久久久久久亚洲影视 | 久久亚洲综合av| 九色在线视频观看| 人人精品亚洲| 国内久久久精品| 五月天福利视频| 欧美午夜xxx| 四虎永久免费在线观看| 日韩中文字幕一区二区三区| 日韩精品一区二区三区外面| 色天使综合视频| 中文字幕精品av| 91九色蝌蚪91por成人| 日韩理论片网站| 久久久久亚洲av无码网站| 好看的日韩av电影| 乱一区二区三区在线播放| 成人性生活视频| 曰本色欧美视频在线| 亚洲一级在线播放| 电影一区二区三区久久免费观看| 亚洲午夜电影网| 老司机免费视频| 久久婷婷麻豆| 在线观看日韩片| 亚洲五码在线| 日本一本a高清免费不卡| 超碰在线国产| 欧美一级二级三级蜜桃| 久久狠狠高潮亚洲精品| 国产欧美日韩卡一| 91大神免费观看| 宅男噜噜噜66一区二区| 日韩色妇久久av| 日韩高清二区| 国产成人av在线| 国产网站在线免费观看| 亚洲精品美女久久久| 夜夜爽妓女8888视频免费观看| 国产精品护士白丝一区av| 国产乱淫av麻豆国产免费| 国产亚洲精品自拍| 中文字幕日韩精品一区二区| 激情亚洲另类图片区小说区| 国产精品一二区| 草美女在线观看| 中文日韩在线视频| 内射后入在线观看一区| 欧美日韩一区二区三区不卡| 日本系列第一页| 欧美国产1区2区| 在线免费看黄色片| 久久99日本精品| 亚洲中文字幕无码不卡电影| 亚洲中无吗在线| 欧美日本韩国在线| 日韩激情综合| 国产精品专区h在线观看| 俺来俺也去www色在线观看| 深夜精品寂寞黄网站在线观看| 理论片中文字幕| 在线电影院国产精品| 免费黄色网址在线| 一区2区3区在线看| 殴美一级黄色片| 久久久精品天堂| 日韩精品xxx| 麻豆免费看一区二区三区| 欧美色图另类小说| 激情成人亚洲| 看全色黄大色大片| 欧美电影《轻佻寡妇》| 欧美一区二区三区精美影视| 大奶在线精品| 在线综合视频播放| 干日本少妇首页| 影视一区二区| 一区二区三区在线观看www| 欧美猛男做受videos| 久久亚洲午夜电影| 久久综合社区| 国产一区在线免费观看| 欧美一区一区| 亚洲最大的网站| 99视频有精品高清视频| 国产欧美日韩精品专区| 精品国模一区二区三区| 国产97色在线|日韩| 天堂√8在线中文| 91超碰caoporn97人人| 里番在线播放| 久久免费观看视频| 黄色美女视频在线观看| 久久久久日韩精品久久久男男| 国产在线二区| 九色精品美女在线| 中文字幕伦理免费在线视频| 欧美成人精品三级在线观看| 高潮毛片在线观看| 欧美日本高清一区| h片精品在线观看| 国内精品久久久| www在线看| 91精品国产九九九久久久亚洲| 91破解版在线观看| 欧美亚洲国产视频小说| 中文不卡1区2区3区| 国产91免费看片| 国产一区高清| 91青草视频久久| 97se亚洲国产一区二区三区| 精品国产91亚洲一区二区三区www| 国产色噜噜噜91在线精品| 好看的日韩精品| 狠狠做六月爱婷婷综合aⅴ| 亚洲欧美在线网| 91av精品| 久久久久久免费看| 裸体一区二区| 奇米影视四色在线| 国产精品系列在线观看| 亚洲丝袜在线观看| aaa国产一区| 国产精品情侣呻吟对白视频| 亚洲男人的天堂在线aⅴ视频| 精品深夜av无码一区二区老年| 亚洲1区2区3区视频| 性色av免费观看| 欧美精品777| 日本免费一区视频| 永久免费精品影视网站| 成人福利在线观看视频| 97色在线观看| 欧美日韩破处视频| 国产三级精品在线不卡| 潘金莲一级黄色片| 99亚偷拍自图区亚洲| 精品无码一区二区三区| 国产精品成人网| 精品一区免费观看| 欧美亚洲一区二区在线| www.久久伊人| 中文字幕亚洲精品| 免费在线观看av电影| 国产精品久久久| 97久久亚洲| 伊人久久婷婷色综合98网| 亚洲一本视频| 超碰人人草人人| 91麻豆免费看| www欧美com| 欧美怡红院视频| 天堂中文在线看| 日韩视频免费看| 成人黄色免费短视频| 成人看片在线| 视频在线不卡免费观看| 女人和拘做爰正片视频| 国产精品一级二级三级| 人妻一区二区视频| 亚洲大片在线观看| 国产视频在线观看视频| 亚洲视频在线观看视频| 国产777精品精品热热热一区二区| 国产原创欧美精品| 国产一区二区三区四区大秀| 大伊香蕉精品视频在线| 精品无人码麻豆乱码1区2区| av在线网站观看| 亚洲v中文字幕| 成人免费视频国产| 久久av红桃一区二区小说| 国产 日韩 欧美一区| 久久伊人一区| 在线亚洲精品| 日本一卡二卡在线| 亚洲福利电影网| 亚洲欧美另类综合| 久久国产精品偷| 亚洲国产91视频| 亚洲一区二区三区涩| 日本怡春院一区二区| 亚洲精品国产熟女久久久| 精品福利免费观看| 人妻夜夜爽天天爽| 欧美—级a级欧美特级ar全黄| 精品中文在线| 国产专区在线视频| 国产呦萝稀缺另类资源| 午夜精品福利在线视频| 欧美久久久久久久久| 欧美激情办公室videoshd| 国产主播精品在线| 91久久国产| 精产国品一二三区| 亚洲美女视频一区| 国内精品偷拍视频| 欧美成人精品三级在线观看| 三级欧美日韩| 欧美一级爱爱视频| 国产精品69毛片高清亚洲| 精品爆乳一区二区三区无码av| 精品国产乱码久久| 在线观看av网页| 99精品视频在线观看| 可以免费看的av毛片| 亚洲人成电影网站色| 欧美暴力调教| 在线国产伦理一区| 国产精品66部| 国产高潮久久久| 国产香蕉97碰碰久久人人| 777午夜精品电影免费看| 亚洲精品一区二区三区蜜桃久| 精品在线免费视频| 黄色一级视频免费观看| 日韩黄在线观看| 欧美国产日韩电影| 日本xxxxx18| 99久久国产综合精品色伊| 日韩精品久久久久久免费| 中文字幕精品av| 91蝌蚪精品视频| 国产乱子夫妻xx黑人xyx真爽| 国产精品无圣光一区二区| 国产女人18毛片水18精| 久久久久久网址| 蜜桃视频欧美| 一区二区久久精品| 亚洲成人av在线电影| 国产爆初菊在线观看免费视频网站| 国产情人节一区| 欧美日韩中文| 日本高清www| 欧美一区二区视频免费观看| 激情视频网站在线播放色| 亚洲三区在线观看| 国产69精品久久99不卡| 日本黄色中文字幕| 欧美大片欧美激情性色a∨久久| 美女毛片一区二区三区四区最新中文字幕亚洲 | 国产精品羞羞答答| 亚洲一级影院| 日韩在线观看免| 精品爽片免费看久久| 亚洲国产伊人| 成人在线看视频| 亚洲制服丝袜一区| av在线资源网| 精品国产乱码久久久久久久软件| 久草中文综合在线|