国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java秒殺系統:web層詳解

Java秒殺系統:web層詳解

2022-02-13 14:58hqinglau~ Java教程

本文主要介紹了如何設計一個秒殺系統的web層相關知識。具有很好的參考價值。下面跟著小編一起來看下吧,希望能夠給你帶來幫助

 

設計Restful接口

根據需求設計前端交互流程。

三個職位:

  • 產品:解讀用戶需求,搞出需求文檔
  • 前端:不同平臺的頁面展示
  • 后端:存儲、展示、處理數據

前端頁面流程:

Java秒殺系統:web層詳解

詳情頁流程邏輯:

Java秒殺系統:web層詳解

標準系統時間從服務器獲取。

Restful:一種優雅的URI表述方式、資源的狀態和狀態轉移。

Restful規范:

  • GET 查詢操作
  • POST 添加/修改操作(非冪等)
  • PUT 修改操作(冪等,沒有太嚴格區分)
  • DELETE 刪除操作

URL設計:

/模塊/資源/{標示}/集合/...
/user/{uid}/friends -> 好友列表
/user/{uid}/followers -> 關注者列表

秒殺API的URL設計

GET /seckill/list 秒殺列表
GET /seckill/{id}/detail 詳情頁
GET /seckill/time/now 系統時間
POST /seckill/{id}/exposer 暴露秒殺
POST /seckill/{id}/{md5}/execution 執行秒殺

下一步就是如何實現這些URL接口。

 

SpringMVC

理論

Java秒殺系統:web層詳解

適配器模式(Adapter Pattern),把一個類的接口變換成客戶端所期待的另一種接口, Adapter模式使原本因接口不匹配(或者不兼容)而無法在一起工作的兩個類能夠在一起工作。

SpringMVC的handlerControllerHttpRequestHandlerServlet等)有多種實現方式,例如繼承Controller的,基于注解控制器方式的,HttpRequestHandler方式的。由于實現方式不一樣,調用方式就不確定了。

看HandlerAdapter接口有三個方法:

// 判斷該適配器是否支持這個HandlerMethod
boolean supports(Object handler);
// 用來執行控制器處理函數,獲取ModelAndView 。就是根據該適配器調用規則執行handler方法。
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
long getLastModified(HttpServletRequest request, Object handler);

問流程如上圖,用戶訪問一個請求,首先經過DispatcherServlet轉發。利用HandlerMapping得到想要的HandlerExecutionChain(里面包含handler和一堆攔截器)。然后利用handler,得到HandlerAdapter,遍歷所有注入的HandlerAdapter,依次使用supports方法尋找適合這個handler的適配器子類。最后通過這個獲取的適配器子類運用handle方法調用控制器函數,返回ModelAndView。

注解映射技巧

  • 支持標準的URL
  • ?和*和**等字符,如/usr/*/creation會匹配/usr/AAA/creation和/usr/BBB/creation等。/usr/**/creation會匹配/usr/creation和/usr/AAA/BBB/creation等URL。帶{xxx}占位符的URL。
  • 如/usr/{userid}匹配/usr/123、/usr/abc等URL.

請求方法細節處理

  • 請求參數綁定
  • 請求方式限制
  • 請求轉發和重定向
  • 數據模型賦值
  • 返回json數據
  • cookie訪問

Java秒殺系統:web層詳解

返回json數據

Java秒殺系統:web層詳解

cookie訪問:

Java秒殺系統:web層詳解

 

項目整合SpringMVC

web.xml下配置springmvc需要加載的配置文件:

<!--?xml version="1.0" encoding="UTF-8"?-->
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" metadata-complete="true">
  <!--修改servlet版本為3.1-->
   <!--配置DispatcherServlet-->
  <servlet>
    <servlet-name>seckill-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--配置springmvc需要加載的配置文件
        spring-dao.xml spring-service.xml spring-web.xml-->
    <!--整合:mybatis -> spring -> springmvc-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/spring-*.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>seckill-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

在resources文件夾下的spring文件夾添加spring-web.xml文件:

<!--?xml version="1.0" encoding="UTF-8"?-->
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemalocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--配置springmvc-->
    <!--1. 開啟springmvc注解模式-->
    <!-- 簡化配置,
        自動注冊handlermapping,handleradapter
        默認提供了一系列功能:數據綁定,數字和日期的format,xml和json的讀寫支持
     -->
    <mvc:annotation-driven>
      <!--servlet-mapping 映射路徑:"/"-->
    <!--2. 靜態資源默認servlet配置
        靜態資源處理:js,gif,png..
        允許使用/做整體映射
    -->
    <mvc:default-servlet-handler>
     <!--3. jsp的顯示viewResolver-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView">
        <property name="prefix" value="/WEB-INF/jsp">
        <property name="suffix" value=".jsp">
    </property></property></property></bean>
     <!--4. 掃描web相關的bean-->
    <context:component-scan base-package="cn.orzlinux.web">
</context:component-scan></mvc:default-servlet-handler></mvc:annotation-driven></beans>

 

使用SpringMVC實現Restful接口

新建文件:

Java秒殺系統:web層詳解

首先是SeckillResult.java,這個保存controller的返回結果,做一個封裝。

// 所有ajax請求返回類型,封裝json結果
public class SeckillResult<t> {
    private boolean success; //是否執行成功
    private T data; // 攜帶數據
    private String error; // 錯誤信息
    // getter setter contructor
}

在Seckillcontroller.java中,實現了我們之前定義的幾個URL:

GET /seckill/list 秒殺列表
GET /seckill/{id}/detail 詳情頁
GET /seckill/time/now 系統時間
POST /seckill/{id}/exposer 暴露秒殺
POST /seckill/{id}/{md5}/execution 執行秒殺

具體代碼如下:

@Controller // @Service @Component放入spring容器
@RequestMapping("/seckill") // url:模塊/資源/{id}/細分
public class SeckillController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private SecKillService secKillService;
    @RequestMapping(value = "/list",method = RequestMethod.GET)
    public String list(Model model) {
        // list.jsp + model = modelandview
        List<seckill> list = secKillService.getSecKillList();
        model.addAttribute("list",list);
        return "list";
    }
     @RequestMapping(value = "/{seckillId}/detail", method = RequestMethod.GET)
    public String detail(@PathVariable("seckillId") Long seckillId, Model model) {
        if (seckillId == null) {
            // 0. 不存在就重定向到list
            // 1. 重定向訪問服務器兩次
            // 2. 重定向可以重定義到任意資源路徑。
            // 3. 重定向會產生一個新的request,不能共享request域信息與請求參數
            return "redrict:/seckill/list";
         }
        SecKill secKill = secKillService.getById(seckillId);
        if (secKill == null) {
            // 0. 為了展示效果用forward
            // 1. 轉發只訪問服務器一次。
            // 2. 轉發只能轉發到自己的web應用內
            // 3. 轉發相當于服務器跳轉,相當于方法調用,在執行當前文件的過程中轉向執行目標文件,
            //      兩個文件(當前文件和目標文件)屬于同一次請求,前后頁 共用一個request,可以通
            //      過此來傳遞一些數據或者session信息
            return "forward:/seckill/list";
        }
        model.addAttribute("seckill",secKill);
        return "detail";
    }
     // ajax json
    @RequestMapping(value = "/{seckillId}/exposer",
            method = RequestMethod.POST,
            produces = {"application/json;charset=UTF8"})
    @ResponseBody
    public SeckillResult<exposer> exposer(Long seckillId) {
        SeckillResult<exposer> result;
        try {
            Exposer exposer = secKillService.exportSecKillUrl(seckillId);
            result = new SeckillResult<exposer>(true,exposer);
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            result = new SeckillResult<>(false,e.getMessage());
        }
        return result;
    }
     @RequestMapping(value = "/{seckillId}/{md5}/execution",
        method = RequestMethod.POST,
        produces = {"application/json;charset=UTF8"})
    public SeckillResult<seckillexecution> execute(
            @PathVariable("seckillId") Long seckillId,
            // required = false表示cookie邏輯由我們程序處理,springmvc不要報錯
            @CookieValue(value = "killPhone",required = false) Long userPhone,
            @PathVariable("md5") String md5) {
        if (userPhone == null) {
            return new SeckillResult<seckillexecution>(false, "未注冊");
        }
        SeckillResult<seckillexecution> result;
        try {
            SeckillExecution execution = secKillService.executeSeckill(seckillId, userPhone, md5);
            result = new SeckillResult<seckillexecution>(true, execution);
            return result;
        } catch (SeckillCloseException e) { // 秒殺關閉
            SeckillExecution execution = new SeckillExecution(seckillId, SecKillStatEnum.END);
            return new SeckillResult<seckillexecution>(false,execution);
        } catch (RepeatKillException e) { // 重復秒殺
            SeckillExecution execution = new SeckillExecution(seckillId, SecKillStatEnum.REPEAT_KILL);
            return new SeckillResult<seckillexecution>(false,execution);
        } catch (Exception e) {
            // 不是重復秒殺或秒殺結束,就返回內部錯誤
            logger.error(e.getMessage(), e);
            SeckillExecution execution = new SeckillExecution(seckillId, SecKillStatEnum.INNER_ERROR);
            return new SeckillResult<seckillexecution>(false,execution);
        }
     }
     @RequestMapping(value = "/time/now",method = RequestMethod.GET)
    @ResponseBody
    public SeckillResult<long> time() {
        Date now = new Date();
        return new SeckillResult<long>(true,now.getTime());
    }
}

頁面

Java秒殺系統:web層詳解

這里修改數據庫為合適的時間來測試我們的代碼。

點擊后跳轉到詳情頁。

Java秒殺系統:web層詳解

詳情頁涉及到比較多的交互邏輯,如cookie,秒殺成功失敗等等。放到邏輯交互一節來說。

運行時發現jackson版本出現問題,pom.xml修改為:

<dependency>
  <groupid>com.fasterxml.jackson.core</groupid>
  <artifactid>jackson-databind</artifactid>
  <version>2.10.2</version>
</dependency>

list.jsp代碼為:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入jstl--%>
<%--標簽通用頭,寫在一個具體文件,直接靜態包含--%>
<%@include file="common/tag.jsp"%>
 
     <title>Bootstrap 模板</title>
    <%--靜態包含:會合并過來放到這,和當前文件一起作為整個輸出--%>
    <%@include file="common/head.jsp"%>
 
    <%--頁面顯示部分--%>
    <div class="container">
        <div class="panel panel-default">
            <div class="panel panel-heading text-center">
                <h1>秒殺列表</h1>
            </div>
            <div class="panel-body">
                <c:foreach var="sk" items="${list}">
                            </c:foreach><table class="table table-hover">
                    <thead>
                        <tr>
                            <th>名稱</th>
                            <th>庫存</th>
                            <th>開始時間</th>
                            <th>結束時間</th>
                            <th>創建時間</th>
                            <th>詳情頁</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                                <td>${sk.name}</td>
                                <td>${sk.number}</td>
                                <td>
                                    <fmt:formatdate value="${sk.startTime}" pattern="yyyy-MM-dd HH:mm:ss">
                                </fmt:formatdate></td>
                                <td>
                                    <fmt:formatdate value="${sk.endTime}" pattern="yyyy-MM-dd HH:mm:ss">
                                </fmt:formatdate></td>
                                <td>
                                    <fmt:formatdate value="${sk.createTime}" pattern="yyyy-MM-dd HH:mm:ss">
                                </fmt:formatdate></td>
                                <td>
                                    <a class="btn btn-info" href="/seckill/${sk.seckillId}/detail" target="_blank">
                                        link
                                    </a>
                                </td>
                            </tr>
                     </tbody>
                </table>
            </div>
        </div>
    </div>
 <!-- jQuery (Bootstrap 的 JavaScript 插件需要引入 jQuery) -->
<script src="https://code.jquery.com/jquery.js"></script>
<!-- 包括所有已編譯的插件 -->
<script src="js/bootstrap.min.js"></script>
 

Java秒殺系統:web層詳解

 

邏輯交互

 

身份認證

cookie中沒有手機號要彈窗,手機號不正確(11位數字)要提示錯誤:

Java秒殺系統:web層詳解

選擇提交之后要能夠在cookie中看到:

Java秒殺系統:web層詳解

目前為止detail.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
 
     <title>秒殺詳情頁</title>
    <%--靜態包含:會合并過來放到這,和當前文件一起作為整個輸出--%>
    <%@include file="common/head.jsp"%>
    <link href="https://cdn.bootcdn.net/ajax/libs/jquery-countdown/2.1.0/css/jquery.countdown.css" rel="stylesheet">
 
    <%--<input type="hidden" id="basePath" value="${basePath}">--%>
    <div class="container">
        <div class="panel panel-default text-center">
            <h1>
                <div class="panel-heading">${seckill.name}</div>
            </h1>
         </div>
        <div class="panel-body">
            <h2 class="text-danger">
                <!-- 顯示time圖標 -->
                <span class="glyphicon glyphicon-time"></span>
                <!-- 展示倒計時 -->
                <span class="glyphicon" id="seckillBox"></span>
            </h2>
        </div>
    </div>
    <!-- 登錄彈出層,輸入電話 bootstrap里面的-->
    <div id="killPhoneModal" class="modal fade bs-example-modal-lg">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h3 class="modal-title text-center">
                        <span class="glyphicon glyphicon-phone"></span>秒殺電話:
                    </h3>
                </div>
                <div class="modal-body">
                    <div class="row">
                        <div class="col-xs-8 col-xs-offset-2">
                            <input type="text" name="killphone" id="killphoneKey" placeholder="填手機號^O^" class="form-control">
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <span id="killphoneMessage" class="glyphicon"></span>
                    <button type="button" id="killPhoneBtn" class="btn btn-success">
                        <span class="glyphicon glyphicon-phone"></span> Submit
                    </button>
                </div>
            </div>
        </div>
    </div>
 
    <!-- jQuery文件。務必在bootstrap.min.js 之前引入 -->
    <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    <!-- jQuery cookie操作插件 -->
    <script src="//cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
    <!-- jQery countDonw倒計時插件  -->
    <script src="//cdn.bootcss.com/jquery.countdown/2.1.0/jquery.countdown.min.js"></script>
 <%--開始寫交互邏輯--%>
<script src="/resources/script/seckill.js" type="text/javascript"></script>
<script type="text/javascript">
    $(function () {
        seckill.detail.init({
            seckillId: ${seckill.seckillId},
            startTime: ${seckill.startTime.time}, // 轉化為毫秒,方便比較
            endTime: ${seckill.endTime.time},
        });
    });
</script>
 

我們的邏輯主要寫在另外的js文件中:

seckill.js

// 存放主要交互邏輯js
// javascript 模塊化
var seckill={
    // 封裝秒殺相關ajax的URL
    URL:{
     },
    // 驗證手機號
    validatePhone: function (phone) {
        if(phone && phone.length==11 && !isNaN(phone)) {
            return true;
        } else {
            return false;
        }
    },
    // 詳情頁秒殺邏輯
    detail: {
        // 詳情頁初始化
        init: function (params) {
            // 手機驗證和登錄,計時交互
            // 規劃交互流程
            // 在cookie中查找手機號
            var killPhone = $.cookie("killPhone");
            var startTime = params["startTime"];
            var endTime = params["endTime"];
            var seckillId = params["seckillId"];
            // 驗證手機號
            if(!seckill.validatePhone(killPhone)) {
                // 綁定手機號,獲取彈窗輸入手機號的div id
                var killPhoneModal = $("#killPhoneModal");
                killPhoneModal.modal({
                    show: true, //顯示彈出層
                    backdrop: "static",//禁止位置關閉
                    keyboard: false, //關閉鍵盤事件
                });
                $("#killPhoneBtn").click(function () {
                    var inputPhone = $("#killphoneKey").val();
                    // 輸入格式什么的ok了就刷新頁面
                    if(seckill.validatePhone(inputPhone)) {
                        // 將電話寫入cookie
                        $.cookie("killPhone",inputPhone,{expires:7,path:"/seckill"});
                        window.location.reload();
                    } else {
                        // 更好的方式是把字符串寫入字典再用
                        $("#killphoneMessage").hide().html("<label class="label label-danger">手機號格式錯誤</label>").show(500);
                    }
                });
            }
            // 已經登錄
         }
    }
}

 

計時面板

在登錄完成后,處理計時操作:

// 已經登錄
// 計時交互
$.get(seckill.URL.now(),{},function (result) {
    if(result && result["success"]) {
        var nowTime = result["data"];
        // 寫到函數里處理
        seckill.countdown(seckillId,nowTime,startTime,endTime);
    } else {
        console.log("result: "+result);
    }
});

在countdown函數里,有三個判斷,未開始、已經開始、結束。

URL:{
    now: function () {
        return "/seckill/time/now";
    }
},
 handleSeckill: function () {
    // 處理秒殺邏輯
},
 countdown: function (seckillId,nowTime,startTime,endTime) {
    var seckillBox = $("#seckillBox");
    if(nowTime>endTime) {
        seckillBox.html("秒殺結束!");
    } else  if(nowTime<starttime) {="" 秒殺未開始,計時="" var="" killtime="new" date(starttime="" +="" 1000);="" seckillbox.countdown(killtime,function="" (event)="" 控制時間格式="" format="event.strftime("秒殺開始倒計時:%D天" %h時="" %m分="" %s秒");="" seckillbox.html(format);="" 時間完成后回調事件="" }).on("finish.countdown",="" function="" ()="" 獲取秒殺地址,控制顯示邏輯,執行秒殺="" seckill.handleseckill();="" })="" }="" else="" 秒殺開始="" },="" ```="" 總體就是一個顯示操作,用了jquery的countdown倒計時插件。="" <img="" src="https://gitee.com/hqinglau/img/raw/master/img/20211006194407.png" ### 秒殺交互
 
 秒殺之前:
 ![image-20211006202253376](https://img-blog.csdnimg.cn/img_convert/7609c513cb3b64f4e710d879e57c1651.png)
 詳情頁:
 <img src="https://gitee.com/hqinglau/img/raw/master/img/20211006201149.png" 點擊開始秒殺:
 <img src="https://gitee.com/hqinglau/img/raw/master/img/20211006202320.png" 列表頁刷新:
 ![image-20211006202306300](https://img-blog.csdnimg.cn/img_convert/272dac0d7f6d4a2910614551f4580aac.png)
 
 運行時發現controller忘了寫`@ResponseBody`了,這里返回的不是jsp是json,需要加上。
 ```java
@ResponseBody
public SeckillResult<seckillexecution> execute(
        @PathVariable("seckillId") Long seckillId,
        // required = false表示cookie邏輯由我們程序處理,springmvc不要報錯
        @CookieValue(value = "killPhone",required = false) Long userPhone,
        @PathVariable("md5") String md5)

在seckill.js中,補全秒殺邏輯:

// 封裝秒殺相關ajax的URL
URL:{
    now: function () {
        return "/seckill/time/now";
    },
    exposer: function(seckillId) {
        return "/seckill/"+seckillId+"/exposer";
    },
     execution: function (seckillId,md5) {
        return "/seckill/"+seckillId+"/"+md5+"/execution";
    }
},
 
// id和顯示計時的那個模塊
handleSeckill: function (seckillId,node) {
    // 處理秒殺邏輯
    // 在計時的地方顯示一個秒殺按鈕
    node.hide()
        .html("<button class="btn btn-primary btn-lg" id="killBtn">開始秒殺</button>");
    // 獲取秒殺地址
    $.post(seckill.URL.exposer(),{seckillId},function (result) {
        if(result && result["success"]) {
            var exposer = result["data"];
            if(exposer["exposed"]) {
                // 如果開啟了秒殺
                // 獲取秒殺地址
                var md5 = exposer["md5"];
                var killUrl = seckill.URL.execution(seckillId,md5);
                console.log("killurl: "+killUrl);
               // click永遠綁定,one只綁定一次
                $("#killBtn").one("click",function () {
                    // 執行秒殺請求操作
                    // 先禁用按鈕
                    $(this).addClass("disabled");
                    // 發送秒殺請求
                    $.post(killUrl,{},function (result) {
                        if(result) {
                             var killResult = result["data"];
                            var state = killResult["state"];
                            var stateInfo = killResult["stateInfo"];
                            // 顯示秒殺結果
                            if(result["success"]) {
                                node.html("<span class="label label-success">"+stateInfo+"</span>");
                            } else {
                                node.html("<span class="label label-danger">"+stateInfo+"</span>");
                            }
 
                        }
                        console.log(result);
                    })
                });
                node.show();
            } else {
                // 未開始秒殺,這里是因為本機顯示時間和服務器時間不一致
                // 可能瀏覽器認為開始了,服務器其實還沒開始
                var now = exposer["now"];
                var start = exposer["start"];
                var end = exposer["end"];
                // 重新進入倒計時邏輯
                seckill.countdown(seckillId,now,start,end);
            }
        } else {
            console.log("result="+result);
        }
    })
},

秒殺成功后再次進行秒殺則不成功:

Java秒殺系統:web層詳解

輸出:

Java秒殺系統:web層詳解

在庫存不夠時也返回秒殺結束:

Java秒殺系統:web層詳解

Java秒殺系統:web層詳解

至此,功能方面已經實現了,后面還剩下優化部分。

 

總結

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!

原文鏈接:https://www.cnblogs.com/hqinglau-orzlinux/p/javaseckill3.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 综合二区 | 国产美女一区二区三区 | 亚洲一本 | 91成人小视频| 一级二级黄色大片 | 欧美电影免费观看高清 | 欧美成人a | 久久久久久久av | 91精品免费| 亚洲天堂一区二区 | 亚洲久草 | 国产美女精品视频免费观看 | 一区二区三区四区av | 成人片网址 | 午夜精品福利在线观看 | 一区二区三区日韩 | 亚洲成人黄色 | 在线观看中文字幕 | 韩日免费视频 | 国产片在线免费观看 | 欧美在线视频一区 | 91免费视频在线 | 成人精品一区二区三区 | 成人看片免费 | 在线激情网站 | 欧美一级欧美三级在线观看 | 中文字幕在线观看视频地址二 | 欧美色欧美亚洲另类七区 | 97久久精品午夜一区二区 | 亚洲视频一区二区三区在线观看 | 人人澡人人透人人爽 | 国产精品国产三级国产aⅴ中文 | 日韩免费| 国产成人精品一区二 | 亚洲精品成人 | 日韩美女毛片 | 国产精品无码久久久久 | 成人午夜精品视频 | 国产成人免费在线 | 99热在线播放 | 日本成人一区 |