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

從0開始手寫一個Spring MVC框架,向高手進階!

開發 后端
Spring框架對于Java后端程序員來說再熟悉不過了,以前只知道它用的反射實現的,但了解之后才知道有很多巧妙的設計在里面。如果不看Spring的源碼,你將會失去一次和大師學習的機會:它的代碼規范,設計思想很值得學習。

Spring框架對于Java后端程序員來說再熟悉不過了,以前只知道它用的反射實現的,但了解之后才知道有很多巧妙的設計在里面。如果不看Spring的源碼,你將會失去一次和大師學習的機會:它的代碼規范,設計思想很值得學習。

我們程序員大部分人都是野路子,不懂什么叫代碼規范。寫了一個月的代碼,***還得其他老司機花3天時間重構,相信大部分老司機都很頭疼看新手的代碼。

廢話不多說,我們進入今天的正題,在Web應用程序設計中,MVC模式已經被廣泛使用。SpringMVC以DispatcherServlet為核心,負責協調和組織不同組件以完成請求處理并返回響應的工作,實現了MVC模式。點擊這里學習 Spring MVC 常用注解。

想要實現自己的SpringMVC框架,需要從以下幾點入手:

  • 了解SpringMVC運行流程及九大組件
  • 梳理自己的SpringMVC的設計思路
  • 實現自己的SpringMVC框架

一、了解SpringMVC運行流程及九大組件

1、SpringMVC的運行流程

 

⑴ 用戶發送請求至前端控制器DispatcherServlet

⑵ DispatcherServlet收到請求調用HandlerMapping處理器映射器。

⑶ 處理器映射器根據請求url找到具體的處理器,生成處理器對象及處理器攔截器(如果有則生成)一并返回給DispatcherServlet。

⑷ DispatcherServlet通過HandlerAdapter處理器適配器調用處理器

⑸ 執行處理器(Controller,也叫后端控制器)。

⑹ Controller執行完成返回ModelAndView

⑺ HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet

⑻ DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器

⑼ ViewReslover解析后返回具體View

⑽ DispatcherServlet對View進行渲染視圖(即將模型數據填充至視圖中)。

⑾ DispatcherServlet響應用戶。從上面可以看出,DispatcherServlet有接收請求,響應結果,轉發等作用。有了DispatcherServlet之后,可以減少組件之間的耦合度。

2、SpringMVC的九大組件 

  1. protected void initStrategies(ApplicationContext context) {    
  2. //用于處理上傳請求。處理方法是將普通的request包裝成            MultipartHttpServletRequest,后者可以直接調用getFile方法獲取File.  
  3.  initMultipartResolver(context);    
  4. //SpringMVC主要有兩個地方用到了Locale:一是ViewResolver視圖解析的時候;二是用到國際化資源或者主題的時候。  
  5.  initLocaleResolver(context);   
  6. //用于解析主題。SpringMVC中一個主題對應 一個properties文件,里面存放著跟當前主題相關的所有資源、//如圖片、css樣式等。SpringMVC的主題也支持國際化, 
  7.  initThemeResolver(context);    
  8. //用來查找Handler的。  
  9.  initHandlerMappings(context);    
  10. //從名字上看,它就是一個適配器。Servlet需要的處理方法的結構卻是固定的,都是以request和response為參數的方法。//如何讓固定的Servlet處理方法調用靈活的Handler來進行處理呢?這就是HandlerAdapter要做的事情  
  11.  initHandlerAdapters(context);    
  12. //其它組件都是用來干活的。在干活的過程中難免會出現問題,出問題后怎么辦呢?//這就需要有一個專門的角色對異常情況進行處理,在SpringMVC中就是HandlerExceptionResolver。  
  13.  initHandlerExceptionResolvers(context);    
  14. //有的Handler處理完后并沒有設置View也沒有設置ViewName,這時就需要從request獲取ViewName了,//如何從request中獲取ViewName就是RequestToViewNameTranslator要做的事情了。  
  15.  initRequestToViewNameTranslator(context);  
  16. //ViewResolver用來將String類型的視圖名和Locale解析為View類型的視圖。//View是用來渲染頁面的,也就是將程序返回的參數填入模板里,生成html(也可能是其它類型)文件。  
  17.  initViewResolvers(context);   
  18. //用來管理FlashMap的,FlashMap主要用在redirect重定向中傳遞參數。  
  19.  initFlashMapManager(context);   

二、梳理SpringMVC的設計思路

本文只實現自己的@Controller、@RequestMapping、@RequestParam注解起作用,其余SpringMVC功能讀者可以嘗試自己實現。

1、讀取配置

從圖中可以看出,SpringMVC本質上是一個Servlet,這個 Servlet 繼承自 HttpServlet。FrameworkServlet負責初始化SpringMVC的容器,并將Spring容器設置為父容器。因為本文只是實現SpringMVC,對于Spring容器不做過多講解。點擊這里學習 Spring MVC 常用注解。

為了讀取web.xml中的配置,我們用到ServletConfig這個類,它代表當前Servlet在web.xml中的配置信息。通過web.xml中加載我們自己寫的MyDispatcherServlet和讀取配置文件。

2、初始化階段

在前面我們提到DispatcherServlet的initStrategies方法會初始化9大組件,但是這里將實現一些SpringMVC的最基本的組件而不是全部,按順序包括:

  • 加載配置文件
  • 掃描用戶配置包下面所有的類
  • 拿到掃描到的類,通過反射機制,實例化。并且放到ioc容器中(Map的鍵值對  beanName-bean) beanName默認是首字母小寫
  • 初始化HandlerMapping,這里其實就是把url和method對應起來放在一個k-v的Map中,在運行階段取出

3、運行階段

每一次請求將會調用doGet或doPost方法,所以統一運行階段都放在doDispatch方法里處理,它會根據url請求去HandlerMapping中匹配到對應的Method,然后利用反射機制調用Controller中的url對應的方法,并得到結果返回。按順序包括以下功能:

  • 異常的攔截
  • 獲取請求傳入的參數并處理參數
  • 通過初始化好的handlerMapping中拿出url對應的方法名,反射調用。

三、實現自己的SpringMVC框架

工程文件及目錄:

 

首先,新建一個maven項目,在pom.xml中導入以下依賴: 

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" 
  2.  <modelVersion>4.0.0</modelVersion>  
  3.  <groupId>com.liugh</groupId>  
  4.  <artifactId>liughMVC</artifactId>  
  5.  <version>0.0.1-SNAPSHOT</version>  
  6.  <packaging>war</packaging>  
  7.    <properties>  
  8.    <project.build.sourceEncoding>UTF- 8</project.build.sourceEncoding>  
  9.    <maven.compiler.source>1.8</maven.compiler.source>  
  10.    <maven.compiler.target>1.8</maven.compiler.target>  
  11.    <java.version>1.8</java.version>  
  12.  </properties>  
  13.  <dependencies>  
  14.       <dependency>  
  15.         <groupId>javax.servlet</groupId>   
  16.       <artifactId>javax.servlet-api</artifactId>   
  17.       <version>3.0.1</version>   
  18.       <scope>provided</scope>  
  19.    </dependency>  
  20.       </dependencies>  
  21. </project> 

接著,我們在WEB-INF下創建一個web.xml,如下配置: 

  1. <?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.  xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
  3.  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
  4.  version="3.0" 
  5.  <servlet>  
  6.    <servlet-name>MySpringMVC</servlet-name 
  7.    <servlet-class>com.liugh.servlet.MyDispatcherServlet</servlet-class>  
  8.    <init-param>  
  9.      <param-name>contextConfigLocation</param-name 
  10.      <param-value>application.properties</param-value>  
  11.    </init-param>  
  12.    <load-on-startup>1</load-on-startup>  
  13.  </servlet>  
  14.  <servlet-mapping>  
  15.    <servlet-name>MySpringMVC</servlet-name 
  16.    <url-pattern>/*</url-pattern>  
  17.  </servlet-mapping></web-app> 

application.properties文件中只是配置要掃描的包到SpringMVC容器中。 

  1. scanPackage=com.liugh.core 

創建自己的Controller注解,它只能標注在類上面: 

  1. package com.liugh.annotation;  
  2. import java.lang.annotation.Documented;  
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Retention;  
  5. import java.lang.annotation.RetentionPolicy;  
  6. import java.lang.annotation.Target;  
  7.  
  8. @Target(ElementType.TYPE)  
  9. @Retention(RetentionPolicy.RUNTIME)  
  10. @Documented  
  11. public @interface MyController {  
  12.  /**  
  13.     * 表示給controller注冊別名  
  14.     * @return  
  15.     */  
  16.    String value() default "" 
  17.  
  18.  
  19. RequestMapping注解,可以在類和方法上:  
  20. RequestParam注解,只能注解在參數上  
  21. package com.liugh.annotation;  
  22. import java.lang.annotation.Documented;  
  23. import java.lang.annotation.ElementType;  
  24. import java.lang.annotation.Retention;  
  25. import java.lang.annotation.RetentionPolicy;  
  26. import java.lang.annotation.Target;  
  27.  
  28. @Target(ElementType.PARAMETER)  
  29. @Retention(RetentionPolicy.RUNTIME)  
  30. @Documented  
  31. public @interface MyRequestParam {  
  32.  /**  
  33.     * 表示參數的別名,必填  
  34.     * @return  
  35.     */  
  36.    String value();  

然后創建MyDispatcherServlet這個類,去繼承HttpServlet,重寫init方法、doGet、doPost方法,以及加上我們第二步分析時要實現的功能: 

  1. package com.liugh.servlet;  
  2. import java.io.File;  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.lang.reflect.Method;  
  6. import java.net.URL;  
  7. import java.util.ArrayList;  
  8. import java.util.Arrays;  
  9. import java.util.HashMap;  
  10. import java.util.List;  
  11. import java.util.Map;  
  12. import java.util.Map.Entry;  
  13. import java.util.Properties; 
  14.  
  15. import javax.servlet.ServletConfig;  
  16. import javax.servlet.ServletException;  
  17. import javax.servlet.http.HttpServlet;  
  18. import javax.servlet.http.HttpServletRequest;  
  19. import javax.servlet.http.HttpServletResponse;  
  20.  
  21. import com.liugh.annotation.MyController;  
  22. import com.liugh.annotation.MyRequestMapping;  
  23. public class MyDispatcherServlet extends HttpServlet{  
  24. private Properties properties = new Properties();  
  25.  
  26. private List<String> classNames = new ArrayList<>();    
  27. private Map<String, Object> ioc = new HashMap<>(); 
  28.  
  29. private Map<String, Method> handlerMapping = new  HashMap<>(); 
  30.  
  31. private Map<String, Object> controllerMap  =new HashMap<>();  
  32.  
  33. @Override  
  34. public void init(ServletConfig config) throws ServletException {    
  35.    //1.加載配置文件  
  36.   doLoadConfig(config.getInitParameter("contextConfigLocation"));   
  37.  
  38.   //2.初始化所有相關聯的類,掃描用戶設定的包下面所有的類  
  39.   doScanner(properties.getProperty("scanPackage"));   
  40.  
  41.   //3.拿到掃描到的類,通過反射機制,實例化,并且放到ioc容器中(k-v  beanName-bean) beanName默認是首字母小寫  
  42.   doInstance(); 
  43.  
  44.   //4.初始化HandlerMapping(將url和method對應上)  
  45.   initHandlerMapping(); 
  46.  
  47.  
  48.  
  49. @Override  
  50. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
  51.   this.doPost(req,resp);  
  52.  
  53. @Override  
  54. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
  55.   try {  
  56.     //處理請求 
  57.     doDispatch(req,resp);  
  58.   } catch (Exception e) {  
  59.     resp.getWriter().write("500!! Server Exception");  
  60.   } 
  61.  
  62.  
  63. private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {  
  64.   if(handlerMapping.isEmpty()){  
  65.     return 
  66.   } 
  67.  
  68.   String url =req.getRequestURI();  
  69.   String contextPath = req.getContextPath();   
  70.  
  71.   url=url.replace(contextPath, "").replaceAll("/+""/");   
  72.  
  73.   if(!this.handlerMapping.containsKey(url)){  
  74.     resp.getWriter().write("404 NOT FOUND!");  
  75.     return 
  76.   }  
  77.   Method method =this.handlerMapping.get(url); 
  78.   //獲取方法的參數列表  
  79.   Class<?>[] parameterTypes = method.getParameterTypes();  
  80.  
  81.   //獲取請求的參數  
  82.   Map<String, String[]> parameterMap = req.getParameterMap(); 
  83.  
  84.   //保存參數值  
  85.   Object [] paramValues= new Object[parameterTypes.length]; 
  86.   //方法的參數列表  
  87.       for (int i = 0; i<parameterTypes.length; i++){    
  88.           //根據參數名稱,做某些處理    
  89.           String requestParam = parameterTypes[i].getSimpleName();   
  90.  
  91.           if (requestParam.equals("HttpServletRequest")){   
  92.               //參數類型已明確,這邊強轉類型    
  93.             paramValues[i]=req;  
  94.               continue;    
  95.           }    
  96.           if (requestParam.equals("HttpServletResponse")){    
  97.             paramValues[i]=resp;  
  98.               continue;    
  99.           }  
  100.           if(requestParam.equals("String")){  
  101.             for (Entry<String, String[]> param : parameterMap.entrySet()) {  
  102.              String value =Arrays.toString(param.getValue()).replaceAll("\[|\]""").replaceAll(",\s"",");  
  103.              paramValues[i]=value; 
  104.            }  
  105.           }  
  106.       }    
  107.   //利用反射機制來調用  
  108.   try {  
  109.     method.invoke(this.controllerMap.get(url), paramValues);//***個參數是method所對應的實例 在ioc容器中  
  110.   } catch (Exception e) {  
  111.     e.printStackTrace(); 
  112.    }  
  113.  
  114. private void  doLoadConfig(String location){  
  115.   //把web.xml中的contextConfigLocation對應value值的文件加載到流里面  
  116.   InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(location);  
  117.   try { 
  118.      //用Properties文件加載文件里的內容  
  119.     properties.load(resourceAsStream);  
  120.   } catch (IOException e) {  
  121.     e.printStackTrace();  
  122.   }finally {  
  123.     //關流  
  124.     if(null!=resourceAsStream){  
  125.       try {  
  126.         resourceAsStream.close();  
  127.       } catch (IOException e) {  
  128.         e.printStackTrace();  
  129.       }  
  130.     }  
  131.   }  
  132.  
  133.  
  134. private void doScanner(String packageName) {  
  135.   //把所有的.替換成/  
  136.   URL url  =this.getClass().getClassLoader().getResource("/"+packageName.replaceAll("\.""/"));  
  137.   File dir = new File(url.getFile());  
  138.   for (File file : dir.listFiles()) {  
  139.     if(file.isDirectory()){  
  140.       //遞歸讀取包  
  141.       doScanner(packageName+"."+file.getName());  
  142.     }else 
  143.       String className =packageName +"." +file.getName().replace(".class""");  
  144.       classNames.add(className); 
  145.     }  
  146.   }  
  147.  
  148. private void doInstance() {  
  149.   if (classNames.isEmpty()) { 
  150.      return 
  151.   }    
  152.   for (String className : classNames) {  
  153.     try {  
  154.       //把類搞出來,反射來實例化(只有加@MyController需要實例化)  
  155.       Class<?> clazz =Class.forName(className);  
  156.        if(clazz.isAnnotationPresent(MyController.class)){  
  157.         ioc.put(toLowerFirstWord(clazz.getSimpleName()),clazz.newInstance());  
  158.       }else 
  159.         continue 
  160.       }  
  161.  
  162.     } catch (Exception e) {  
  163.       e.printStackTrace();  
  164.       continue 
  165.     }  
  166.   } 
  167.  
  168. private void initHandlerMapping(){  
  169.   if(ioc.isEmpty()){  
  170.     return 
  171.   }  
  172.   try {  
  173.     for (Entry<String, Object> entry: ioc.entrySet()) {  
  174.       Class<? extends Object> clazz = entry.getValue().getClass();  
  175.       if(!clazz.isAnnotationPresent(MyController.class)){  
  176.         continue 
  177.       }  
  178.  
  179.       //拼url時,是controller頭的url拼上方法上的url  
  180.       String baseUrl ="" 
  181.       if(clazz.isAnnotationPresent(MyRequestMapping.class)){  
  182.         MyRequestMapping annotation = clazz.getAnnotation(MyRequestMapping.class);  
  183.         baseUrl=annotation.value(); 
  184.       }  
  185.       Method[] methods = clazz.getMethods();  
  186.       for (Method method : methods) {  
  187.         if(!method.isAnnotationPresent(MyRequestMapping.class)){  
  188.           continue 
  189.         }  
  190.         MyRequestMapping annotation = method.getAnnotation(MyRequestMapping.class);  
  191.         String url = annotation.value();
  192.  
  193.         url =(baseUrl+"/"+url).replaceAll("/+""/");  
  194.         handlerMapping.put(url,method);  
  195.         controllerMap.put(url,clazz.newInstance());  
  196.         System.out.println(url+","+method);  
  197.       } 
  198.  
  199.     } 
  200.  
  201.   } catch (Exception e) {  
  202.     e.printStackTrace();  
  203.   }  
  204.  
  205.  
  206. /**  
  207.  * 把字符串的首字母小寫  
  208.  * @param name  
  209.  * @return  
  210.  */  
  211. private String toLowerFirstWord(String name){  
  212.   char[] charArray = name.toCharArray();  
  213.   charArray[0] += 32;  
  214.   return String.valueOf(charArray);  

這里我們就開發完了自己的SpringMVC,現在我們測試一下: 

  1. package com.liugh.core.controller;  
  2. import java.io.IOException;  
  3. import javax.servlet.http.HttpServletRequest;  
  4. import javax.servlet.http.HttpServletResponse; 
  5. import com.liugh.annotation.MyController;  
  6. import com.liugh.annotation.MyRequestMapping;  
  7. import com.liugh.annotation.MyRequestParam;  
  8.  
  9. @MyController  
  10. @MyRequestMapping("/test" 
  11. public class TestController { 
  12.   @MyRequestMapping("/doTest" 
  13.    public void test1(HttpServletRequest request, HttpServletResponse response,  
  14.        @MyRequestParam("param") String param){  
  15.     System.out.println(param);  
  16.      try {  
  17.            response.getWriter().write( "doTest method success! param:"+param);  
  18.        } catch (IOException e) {  
  19.            e.printStackTrace();  
  20.        }  
  21.    }  
  22.  
  23.   @MyRequestMapping("/doTest2" 
  24.    public void test2(HttpServletRequest request, HttpServletResponse response){  
  25.        try {  
  26.            response.getWriter().println("doTest2 method success!");  
  27.        } catch (IOException e) {  
  28.            e.printStackTrace();  
  29.        }  
  30.    } 
  31.  

訪問

http://localhost:8080/liughMVC/test/doTest?param=liugh如下:

訪問一個不存在的試試:

 

到這里我們就大功告成了!水平有限,文章難免有錯誤,歡迎犧牲自己寶貴時間的讀者,就本文內容直抒己見,我的目的僅僅是希望對讀者有所幫助。 

責任編輯:龐桂玉 來源: Java技術棧
相關推薦

2019-05-13 15:05:34

TomcatWeb Server協議

2020-01-09 11:11:35

RPC框架調用遠程

2017-05-08 14:27:49

PHP框架函數框架

2023-10-16 22:03:36

日志包多線程日志包

2020-11-02 08:19:18

RPC框架Java

2020-04-07 15:12:07

微服務架構數據

2012-06-04 18:02:56

社區

2020-12-23 09:48:37

數據工具技術

2022-07-06 19:00:00

微服務框架鏈路

2020-09-27 14:13:50

Spring BootJava框架

2022-10-08 08:34:34

JVM加載機制代碼

2024-08-02 09:49:35

Spring流程Tomcat

2025-07-28 04:22:00

2021-02-20 09:45:02

RPC框架Java

2013-12-18 13:30:19

Linux運維Linux學習Linux入門

2021-12-27 08:27:17

SpringMVC面試

2010-08-03 09:15:05

ScalaSpring

2019-08-21 17:41:29

操作系統軟件設計

2015-08-24 11:03:14

android建項目

2015-07-28 11:02:15

androidapp開發
點贊
收藏

51CTO技術棧公眾號

黄色网址在线免费看| 日本久久久久亚洲中字幕| 欧美日韩一区二区区| 欧美黑人xx片| 91在线国产福利| 日韩av成人在线| 欧美性生给视频| 色播一区二区| 色综合久久中文字幕| 五月天亚洲综合小说网| 99久久亚洲精品日本无码| 激情久久一区| 中文字幕日本欧美| 永久免费看片在线观看| 欧美xxxx做受欧美护士| 一区二区三区免费| 日韩av免费电影| xxxx国产精品| 美女免费视频一区| 97福利一区二区| 小嫩苞一区二区三区| 国产精品久久久久久久久久白浆| 欧美午夜精品一区二区三区| 免费在线看黄色片| 亚洲s色大片| av资源网一区| 97久久精品午夜一区二区| 波多野结衣视频网站| 午夜精品久久99蜜桃的功能介绍| 精品偷拍一区二区三区在线看| 久久久精品视频国产| 欧美日韩国产v| 五月激情六月综合| 激情六月天婷婷| 麻豆tv免费在线观看| 99国产欧美久久久精品| 亚洲一区二区三区乱码aⅴ| www.色国产| 天天综合网91| 亚洲欧美成人一区二区在线电影| 992tv人人草| 日本免费久久| 亚洲图片欧美综合| 夜夜春亚洲嫩草影视日日摸夜夜添夜 | 无码人妻丰满熟妇区bbbbxxxx| 欧美丰满老妇| 亚洲欧美在线一区二区| 蜜臀av粉嫩av懂色av| 伊人久久大香伊蕉在人线观看热v 伊人久久大香线蕉综合影院首页 伊人久久大香 | 欧美激情视频一区二区三区| 99久久久国产精品无码免费| 日本不卡一二三区黄网| 午夜精品久久久久久久男人的天堂| 人成免费在线视频| 国产剧情一区| 国产视频精品va久久久久久| 国产在线观看免费播放| 日本免费在线一区| 色悠久久久久综合欧美99| 成年在线观看视频| 欧美精品hd| 国产精品乱码久久久久久| 欧美裸体网站| 欧美女子与性| 91香蕉视频污| 精品国产第一页| 免费看黄网站在线观看| 国产精品白丝jk黑袜喷水| 国产欧美中文字幕| 一区二区小视频| 另类小说欧美激情| 日本一区二区不卡| 在线视频精品免费| 日本不卡视频在线观看| 国产精品盗摄久久久| 男女视频免费看| 一本一道久久综合狠狠老精东影业| 欧美黄色免费网站| 黄色一级视频在线观看| 狠久久av成人天堂| 欧美高清视频一区二区| 国产在线免费视频| 亚洲麻豆视频| 91爱视频在线| 日韩一级在线视频| 日韩激情中文字幕| 国产精品日韩欧美| 97国产成人无码精品久久久| 国产一区二区不卡老阿姨| 成人激情av在线| 精品黑人一区二区三区在线观看| 大桥未久av一区二区三区中文| 国产伊人精品在线| 波多野结衣在线观看视频| 亚洲永久字幕| 国产精品久久久久久久久久新婚| 亚洲最新av网站| 国产精品亚洲视频| 精品欧美一区二区在线观看视频 | 91精品久久久久久久91蜜桃| 超碰中文字幕在线观看| 粉嫩av一区二区| 亚洲精品一区av在线播放| 久久日免费视频| 91精品秘密在线观看| 久久久久久久久久av| 久久久无码一区二区三区| 亚洲综合精品| 成人黄色大片在线免费观看| 亚洲va久久久噜噜噜无码久久| 97超碰欧美中文字幕| 四虎永久国产精品| 色呦呦网站在线观看| 日韩欧美亚洲国产一区| 免费精品99久久国产综合精品应用| 久久久久亚洲精品中文字幕| 日韩精品一二三四区| 美国精品一区二区| 国内久久视频| 国产精品一区av| 蜜臀av在线观看| 国产精品久久久久久久第一福利| 国产精品久久国产| 中文.日本.精品| 亚洲精品在线网站| 国产精品揄拍100视频| 日韩欧美一区免费| 国产91精品青草社区| 国产欧美久久久| 久久丝袜美腿综合| 91国在线高清视频| 色资源二区在线视频| 欧美精品v国产精品v日韩精品| 黄色短视频在线观看| 91亚洲自偷观看高清| 18性欧美xxxⅹ性满足| 国产模特av私拍大尺度| 国产网站一区二区| av一区二区三区免费观看| 成人国产一区| 亚洲精品日韩在线| 久草免费在线观看视频| 麻豆久久久久久| 蜜桃视频日韩| 成av人片在线观看www| 91精品国产91久久久久久一区二区 | 精品在线不卡| 国产一二区在线| 欧美色综合久久| a级大片在线观看| 亚洲精品日韩久久| 成人免费视频网站入口| 免费网站黄在线观看| 色天天综合久久久久综合片| 色婷婷免费视频| 欧美一区二区三区另类| 国产热re99久久6国产精品| 国产最新视频在线观看| 精品国产999| 国产精品久久久久久亚洲色 | 3atv一区二区三区| 大胸美女被爆操| 青青草国产精品97视觉盛宴| 欧美在线一区二区三区四区| 亚洲最大网站| 亚洲美女免费精品视频在线观看| 日本少妇久久久| 国产成人亚洲精品青草天美| 欧美一级视频免费看| 国产精品丝袜在线播放| 国模精品系列视频| 亚洲AV无码国产精品午夜字幕 | 欧美高清视频一区| 忘忧草在线影院两性视频| 亚洲成人国产精品| 久久精品久久国产| 成人国产精品免费观看视频| av在线播放天堂| 久久香蕉精品香蕉| 欧亚精品中文字幕| 亚洲欧洲国产综合| 亚洲电影在线免费观看| 右手影院亚洲欧美| 玖玖在线精品| 亚洲一卡二卡区| 韩国三级成人在线| 欧美大片免费看| 神马午夜一区二区| 偷拍一区二区三区四区| 蜜桃传媒一区二区亚洲av| 裸体一区二区| 亚洲欧美日韩精品久久久 | 91久久伊人青青碰碰婷婷| aa在线视频| 亚洲大胆人体在线| 亚洲综合图片网| ...中文天堂在线一区| 免费黄频在线观看| 99国产精品自拍| 欧美一级爽aaaaa大片| 韩国精品视频在线观看| 欧美成在线视频| 色吊丝在线永久观看最新版本| 欧美制服丝袜第一页| 国产成人综合在线视频| 91视频免费观看| 亚洲欧洲日本精品| 亚洲一级特黄| 亚洲成人一区二区三区| 亚洲精品a区| 欧美综合第一页| 久久久久久久久免费视频| 亚洲第一av网| 在线观看国产小视频| 亚洲男同性恋视频| 日本成人午夜影院| 丁香啪啪综合成人亚洲小说| 黄色免费网址大全| 国内激情久久| 一区二区三区四区五区视频| 精品中文字幕一区二区三区| 91大神福利视频在线| www免费在线观看| 亚洲男人天堂2023| 午夜久久久久久久久久| 在线一区二区三区四区五区| 免费无码毛片一区二区app| 国产色91在线| 最新版天堂资源在线| 看电视剧不卡顿的网站| 亚洲欧洲日产国码无码久久99| 亚洲性视频大全| 亚洲在线观看视频| 不卡亚洲精品| 国产91精品不卡视频| 日韩激情美女| 久久中文字幕在线视频| 国产在线你懂得| 亚洲国产欧美一区二区丝袜黑人 | 亚洲成人国产| 日本精品一区| 久久久亚洲欧洲日产| 91免费看网站| 农村妇女一区二区| 91av在线免费观看| 日韩经典av| 久久久精品国产亚洲| 粉嫩一区二区三区国产精品| 日韩激情视频在线| 韩国中文字幕hd久久精品| 欧美美女一区二区在线观看| 成年人视频免费| 激情成人中文字幕| 国产亚洲精品久久777777| 自拍偷自拍亚洲精品播放| 久操视频在线观看免费| 久久看人人爽人人| 日本aaa视频| 99久精品国产| 久久久久久无码精品人妻一区二区| 精品一区二区综合| 中文字幕22页| 精品一区二区精品| 亚洲a级黄色片| 激情欧美日韩一区二区| 午夜啪啪小视频| 狠狠色丁香久久婷婷综合_中| 手机版av在线| 紧缚奴在线一区二区三区| 欧美国产日韩另类| 国产在线麻豆精品观看| 亚洲第一成肉网| 国产麻豆精品在线观看| 亚洲天堂2018av| 国产伦精品一区二区三区在线观看| 91精品999| 狠狠网亚洲精品| 制服下的诱惑暮生| 国产不卡视频在线观看| 伊人久久一区二区三区| 99国产精品久久久久久久久久| 亚洲精品视频大全| 国产日本欧洲亚洲| 在线观看天堂av| 中文字幕欧美国产| 欧美丰满熟妇bbbbbb| 亚洲一卡二卡在线观看| 亚洲欧美另类图片小说| 欧美国产在线看| 亚洲成人动漫一区| 三级黄色在线视频| 欧亚洲嫩模精品一区三区| 国产精品一级视频| 亚洲精品一区在线观看| 欧美xxx.com| 中文字幕亚洲欧美在线| 三区四区电影在线观看| 欧美激情一区二区三区成人| 美女av在线免费看| 国产日韩欧美中文在线播放| 午夜视频在线观看精品中文| 国产九色91| 国产一区二区欧美| 自拍偷拍视频在线| 亚洲精品偷拍| 午夜两性免费视频| 国产成人av影院| av电影在线不卡| 中文字幕在线一区| 羞羞影院体验区| 欧美疯狂性受xxxxx喷水图片| 国内爆初菊对白视频| 国产小视频国产精品| 三级福利片在线观看| 青青青国产精品一区二区| 不卡精品视频| 久久久久久99| 一本一道久久a久久精品蜜桃| 国产精品网站免费| 久久精品国产一区二区三区免费看| 国产精品一级无码| www.在线欧美| 麻豆明星ai换脸视频| 色综合婷婷久久| 性色av蜜臀av| 俺去了亚洲欧美日韩| 免费观看亚洲| 久久国产精品免费一区| 亚洲国产一区二区在线观看 | 五十路在线观看| 久久久精品在线观看| 天堂√8在线中文| 成人动漫视频在线观看完整版| 日韩激情图片| 国产精品99久久免费黑人人妻| 国产福利一区二区三区在线视频| 欧美熟妇激情一区二区三区| 亚洲夂夂婷婷色拍ww47| 亚洲熟妇无码久久精品| 精品视频中文字幕| 欧美寡妇性猛交xxx免费| 成人信息集中地欧美| 青青草原综合久久大伊人精品 | 亚洲精品国产精华液| 4438国产精品一区二区| 亚洲精品97久久| 美足av综合网| 91视频免费网站| 欧美va久久久噜噜噜久久| 国产精品少妇在线视频| 99久久免费国产| 日本熟妇毛耸耸xxxxxx| 欧美一区二区三区视频在线| 免费在线观看av片| 日产精品99久久久久久| 怕怕欧美视频免费大全| 国产男女无遮挡| 99国产精品国产精品久久| 久久精品美女视频| 亚洲高清在线观看| 久草在线新免费首页资源站| 亚洲最大成人免费视频| 仙踪林久久久久久久999| 日韩一区二区三区久久| 中文在线资源观看网站视频免费不卡| 91香蕉在线视频| 精品国内二区三区| 欧美freesex黑人又粗又大| 国产欧美日韩综合一区在线观看| 国内一区二区三区| 国产精品成人99一区无码 | 日韩一卡二卡三卡| 超碰在线网址| 岛国视频一区免费观看| 亚洲视频一区| 亚洲黄色免费在线观看| 黑人巨大精品欧美一区二区一视频| 午夜在线视频观看| 91极品女神在线| 一区二区三区视频免费观看| 国产一级不卡毛片| 国产精品伦理在线| 国产精品国产三级国产aⅴ | 熟妇高潮一区二区| 欧美日韩午夜视频在线观看| 韩国中文免费在线视频| 国产欧美日韩最新| 亚洲深深色噜噜狠狠爱网站| 在线中文字日产幕| 精品久久久久久国产| 福利小视频在线观看| 成人美女免费网站视频| 国内视频精品| 精品无码人妻一区| 欧美午夜电影在线播放| 久草免费在线观看| 国产精品播放| 日韩成人免费看| 波多野结衣爱爱视频| 亚洲男女自偷自拍图片另类|