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

SringMVC從入門到源碼,這一篇就夠

開發 后端
Java行業的誰人不知SSM框架呢?除非你告訴我剛學Java,我就相信你不知道SpringMVC。

[[341461]]

SpringMVC簡介

Java行業的誰人不知SSM框架呢?除非你告訴我剛學Java,我就相信你不知道SpringMVC。

關于SringMVC的由來和干嘛用的基本都不用介紹了,基本都知道了。但是有一點可以肯定的是:有很多人只停留在SpringMVC使用層面,對于SpringMVC的底層原理和源碼卻沒有深入了解過。

這一期我們就來了解「SpringMVC的底層原理和源碼」,在以前的JSP時代,代碼中前端和后端都混在一起,可能比較老的程序員就寫過下面的代碼,這就是大名鼎鼎的JSP和Servlet時代。

在一些老的項目中可能就會出現這樣的代碼,這樣的代碼是不是看起來非常的帶勁,要是讓你維護這樣的代碼,想死的心都有。

 

這樣的代碼前端和后端混在一起,相互依賴JSP與Java Bean之間嚴重耦合,java代碼和Html代碼混在一起,這要求開發人員既要會前端也要會后端,給測試帶來了很多不方便,代碼也不能復用。

諸如此類的問題,為了解決這樣的問題,首先就是將這些代碼進行嚴格的劃分,前端與后端的代碼分開,逐漸出現代碼的分層架構,各層職責分明。

 

但是,這樣的模型層也還會有問題,首先每個模塊就需要一個Servlet控制器,模塊多的,控制器就會變得很多,這樣會導致控制器復雜。

并且更換視圖技術麻煩,嚴重依賴Servlet API。Java Bean結構包含持久化層以及業務的處理,數據的封裝,這樣就會導致Java Bean結構臃腫。

按照我們現在代碼的分層,可以把Java Bean又分為「持久層(dao)和服務層(Service)」 以及我們的 「應用控制層(Controller)」。

 

SpringMVC原理

為了簡化控制層(Servlet),在SpringMVC框架中使用「DispatcherServlet(前端控制器)」 調度我們自己的「應用控制層(Controller)」。

就這樣逐漸的演變,出現了我們現在真正意義上的Web MVC三層架構,具體的結構圖如下所示:

 

首先來說明一下SpringMVC幾個核心的組件:

  1. DispatcherServlet:前端前端控制器主要負責調度工作,進行全局的流程控制。比如:調度HandlerMapping然后返回執行鏈。
  2. HandlerMapping:處理器映射器會返回一個執行鏈,通俗來講也就是執行的邏輯順序,執行鏈中包含多個「Interceptor(攔截器)」 和一個「Handler(處理器)」。
  3. HandlerAdapter:處理器適配器里面包含了處理器的調用,使用適配器的設計原則,通過反射調用我們自己的Controller。
  4. Handler:處理器也就是我們的Controller,用戶對應的請求URL請求過來,通過請求與我們Controller的映射規則(HandlerMapping)相對應起來,這個就是處理器。
  5. ModelAndView:模型和視圖,模式(Model)也就是我們的數據,通過上面反射調用Handler(Controller)生成的數據,以及邏輯視圖(View)。邏輯視圖并不是真正的視圖名,它只是一個邏輯視圖名,比如:index。
  6. View:視圖,這時候才會通過上面生成的邏輯視圖名生成對應的物理視圖,返回前端呈現用戶。

Hello World上面說了那么多,其實還是要在項目進行實踐中才會有深刻的體會,下面我們通過實際一個案例進行上面的深刻的理解。

這里我使用idea搭建SSM項目,還用Eclipse的同學,建議你該換工具了,首先New - Project

然后左邊選擇Maven,右邊勾選Create from archetype,并且選擇webapp模塊:

 

下面就是填寫一些GroupId以及ArtifactId,這些比較簡單就直接跳過了,不然會被大佬diss死了,創建完項目后的基本目錄結構如下:

 

并且在resource目錄下分別創建下面四個配置文件「applicationContext.xml、jdbc.properties、log4j.properties、spring-mvc.xml」。

applicationContext.xml是Spring的核心配置文件,內容如下:

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" 
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans 
  6.                         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
  7.                         http://www.springframework.org/schema/tx 
  8.                         http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 
  9.  
  10.     <!-- 加載properties文件 --> 
  11.     <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
  12.         <property name="location" value="classpath:jdbc.properties"/> 
  13.     </bean> 
  14.  
  15.     <!-- 配置數據源 --> 
  16.     <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
  17.         <property name="driverClassName" value="${driver}"/> 
  18.         <property name="url" value="${url}"/> 
  19.         <property name="username" value="${username}"/> 
  20.         <property name="password" value="${password}"/> 
  21.     </bean> 
  22.  
  23.     <!-- mybatis和spring完美整合,不需要mybatis的配置映射文件 --> 
  24.     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
  25.         <property name="dataSource" ref="dataSource"/> 
  26.         <!-- 掃描model包 --> 
  27.         <property name="typeAliasesPackage" value="com.ldc.model"/> 
  28.         <!-- 掃描sql配置文件:mapper需要的xml文件 --> 
  29.         <property name="mapperLocations" value="classpath:mapper/*.xml"/> 
  30.     </bean> 
  31.  
  32.     <!-- Mapper動態代理開發,掃描dao接口包--> 
  33.     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
  34.         <!-- 注入sqlSessionFactory --> 
  35.         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> 
  36.         <!-- 給出需要掃描Dao接口包 --> 
  37.         <property name="basePackage" value="com.ldc.dao"/> 
  38.     </bean> 
  39.  
  40.     <!-- 事務 --> 
  41.     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
  42.         <property name="dataSource" ref="dataSource"/> 
  43.     </bean> 
  44.  
  45. </beans> 

這個文件主要配置了數據源、數據庫的來連接的配置信息,數據的詳細信息就放在jdbc.properties中:

  1. driver=com.mysql.cj.jdbc.Driver 
  2. url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai 
  3. username=root 
  4. password=user 
  5. initialSize=0 
  6. maxActive=20 
  7. maxIdle=20 
  8. minIdle=1 
  9. maxWait=60000 

這里的數據庫信息,你們只要修改數據庫的用戶名了密碼就行了,其它的作為測試信息基本就不用修改了。

接下來就是日志的配置信息log4j.properties,這里只做簡單的日志配置:

  1. #日志輸出級別 
  2. log4j.rootLogger=debug,stdout,D,E 
  3.  
  4. #設置stdout的日志輸出控制臺 
  5. log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
  6. #輸出日志到控制臺的方式,默認為System.out 
  7. log4j.appender.stdout.Target = System.out 
  8. #設置使用靈活布局 
  9. log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
  10. #靈活定義輸出格式 
  11. log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} -[%p]  method:[%c (%rms)] - %m%n 

配置完日志信息后,接著配置spring-mvc.xml,這個的SpringMVC框架內的信息配置文件:

這和配置信息也很簡單,主要包括「開啟注解驅動、包掃描、視圖解析器的配置」。

配置完SpringMVC后,最后就是配置web.xml,web.xml是前端請求的入口文件:

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xmlns:context="http://www.springframework.org/schema/context" 
  5.        xmlns:mvc="http://www.springframework.org/schema/mvc" 
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans 
  7.        http://www.springframework.org/schema/beans/spring-beans.xsd 
  8.        http://www.springframework.org/schema/context 
  9.        http://www.springframework.org/schema/context/spring-context.xsd 
  10.        http://www.springframework.org/schema/mvc 
  11.        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> 
  12.  
  13.     <!-- 掃描注解,這樣com.xjt包下的文件都能被掃描 --> 
  14.     <context:component-scan base-package="com.ldc"/> 
  15.  
  16.     <!-- 開啟SpringMVC注解模式 --> 
  17.     <mvc:annotation-driven/> 
  18.  
  19.     <!-- 靜態資源默認servlet配置 --> 
  20.     <mvc:default-servlet-handler/> 
  21.   
  22.  <!-- 配置返回視圖的路徑,以及識別后綴是jsp文件 --> 
  23.     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
  24.         <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> 
  25.         <property name="prefix" value="/WEB-INF/jsp/"/> 
  26.         <property name="suffix" value=".jsp"/> 
  27.     </bean> 
  28. </beans> 

在web.xml中主要包含:「默認歡迎頁面的配置、字符編碼過濾器的配置、前端控制器、以及指定spring核心配置文件和SpringMVC的配置文件」。

以上就是最基本的配置,其它的配置信息一般是按需配置,這樣配置完后,我們搭建一個簡單的SSM的項目基本已經完成了。

最后的Maven的坐標依賴,如下:

  1. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
  2.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  3.          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 
  4.          version="3.1"
  5.  
  6.   <display-name>mvcDemo</display-name
  7.   <!--項目的歡迎頁,項目運行起來后訪問的頁面--> 
  8.   <welcome-file-list> 
  9.     <welcome-file>index.jsp</welcome-file> 
  10.   </welcome-file-list> 
  11.  
  12.   <!-- 注冊ServletContext監聽器,創建容器對象,并且將ApplicationContext對象放到Application域中 --> 
  13.   <listener> 
  14.     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
  15.   </listener> 
  16.  
  17.   <!-- 指定spring核心配置文件 --> 
  18.   <context-param> 
  19.     <param-name>contextConfigLocation</param-name
  20.     <param-value>classpath:applicationContext.xml</param-value> 
  21.   </context-param> 
  22.  
  23.   <!-- 解決亂碼的過濾器 --> 
  24.   <filter> 
  25.     <filter-name>CharacterEncodingFilter</filter-name
  26.     <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
  27.     <init-param> 
  28.       <param-name>encoding</param-name
  29.       <param-value>utf-8</param-value> 
  30.     </init-param> 
  31.     <init-param> 
  32.       <param-name>forceEncoding</param-name
  33.       <param-value>true</param-value> 
  34.     </init-param> 
  35.   </filter> 
  36.   <filter-mapping> 
  37.     <filter-name>CharacterEncodingFilter</filter-name
  38.     <url-pattern>/*</url-pattern> 
  39.   </filter-mapping> 
  40.   <!-- 配置前端控制器 --> 
  41.   <servlet> 
  42.     <servlet-name>springmvc</servlet-name
  43.     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
  44.     <!-- 指定配置文件位置和名稱 如果不設置,默認找/WEB-INF/<servlet-name>-servlet.xml --> 
  45.     <init-param> 
  46.       <param-name>contextConfigLocation</param-name
  47.       <param-value>classpath:spring-mvc.xml</param-value> 
  48.     </init-param> 
  49.     <load-on-startup>1</load-on-startup> 
  50.     <async-supported>true</async-supported> 
  51.   </servlet> 
  52.   <servlet-mapping> 
  53.     <servlet-name>springmvc</servlet-name
  54.     <url-pattern>/</url-pattern> 
  55.   </servlet-mapping> 
  56. </web-app> 

maven做表中主要開發包含的依賴數據庫驅動、日志、mybaties、spring坐標、web mvc的坐標、以及繼承JSP的坐標。

這里前端技術可以繼承你們自己想要的:Freemarker或者Thymeleaf,只需要引入相關的Maven坐標,因為JSP已經基本被淘汰了,這里只是為了作測試,并不關心前端用什么技術。

我們在controller包下創建我們自己的測試類:UserController:

  1. @Controller 
  2. @RequestMapping("/user"
  3. public class UserController { 
  4.  
  5.     @Autowired 
  6.     private IUserService userService; 
  7.  
  8.     @RequestMapping("/getUserById"
  9.     public ModelAndView selectUser(@PathVariable("id") Long id) throws Exception { 
  10.         ModelAndView mv = new ModelAndView(); 
  11.         User user = userService.selectUser(id); 
  12.         mv.addObject("user"user); 
  13.         mv.setViewName("user"); 
  14.         return mv; 
  15.     } 

這里簡單解釋一下:

  1. @Controller:標名它是一個控制器,被Spring容器所管理,這個注解是在@Component后面出的,為了表示代碼的分層,于是就有了@Controller、@Service、@Mapper這三個注解,他們的作用是一樣的。
  2. @RequestMapping:表示接受的請求,還是GetMapping、PostMapping等注解表示請求方法的不同。
  3. @Autowired:表示自動注入,前提就是被注入的對象被Spring容器所管理。
  4. ModelAndView:這個前面說過,它裝的就是數據和邏輯視圖名。

這些還是比較簡單的,通過下面配置Tomcat信息進行部署,就可以啟動項目進行測試了:

 

DispatcherServlet源碼解析

這個還是比較簡單的,還不會可以自行百度,啟動項目后我們來測試一下前面,出現下面的界面說明,你搭建SSM項目的基本環境已經成功了:

 

那么我們的前端請求是怎么一步一步的從「前臺->后臺->前臺」的呢?其實前面我們已經說了SpringMVC的基本原理,在這個基本原理的基礎上,從源碼的角度,進行詳細的解析:

上面說到SpringMVC的核心調度器就是DispatcherServlet,負責主流程的調度工作,在DispatcherServlet里面最主要的方法就是doDispatch:

  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {   
  2.         HttpServletRequest processedRequest = request;   
  3.         HandlerExecutionChain mappedHandler = null;   
  4.         int interceptorIndex = -1;   
  5.    
  6.         try {   
  7.             ModelAndView mv;   
  8.             boolean errorView = false;   
  9.    
  10.             try {   
  11.                    //檢查是否是請求是否是multipart(如文件上傳),如果是將通過MultipartResolver解析   
  12.                 processedRequest = checkMultipart(request);   
  13.                    //步驟2、請求到處理器(頁面控制器)的映射,通過HandlerMapping進行映射   
  14.                 mappedHandler = getHandler(processedRequest, false);   
  15.                 if (mappedHandler == null || mappedHandler.getHandler() == null) {   
  16.                     noHandlerFound(processedRequest, response);   
  17.                     return;   
  18.                 }   
  19.                    //步驟3、處理器適配,即將我們的處理器包裝成相應的適配器(從而支持多種類型的處理器)   
  20.                 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());   
  21.    
  22.                   // 304 Not Modified緩存支持   
  23.                 //此處省略具體代碼   
  24.    
  25.                 // 執行處理器相關的攔截器的預處理(HandlerInterceptor.preHandle)   
  26.                 //此處省略具體代碼   
  27.    
  28.                 // 步驟4、由適配器執行處理器(調用處理器相應功能處理方法)   
  29.                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());   
  30.    
  31.                 // Do we need view name translation?   
  32.                 if (mv != null && !mv.hasView()) {   
  33.                     mv.setViewName(getDefaultViewName(request));   
  34.                 }   
  35.    
  36.                 // 執行處理器相關的攔截器的后處理(HandlerInterceptor.postHandle)   
  37.                 //此處省略具體代碼   
  38.             }   
  39.             catch (ModelAndViewDefiningException ex) {   
  40.                 logger.debug("ModelAndViewDefiningException encountered", ex);   
  41.                 mv = ex.getModelAndView();   
  42.             }   
  43.             catch (Exception ex) {   
  44.                 Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);   
  45.                 mv = processHandlerException(processedRequest, response, handler, ex);   
  46.                 errorView = (mv != null);   
  47.             }   
  48.    
  49.             //步驟5 步驟6、解析視圖并進行視圖的渲染   
  50. //步驟5 由ViewResolver解析View(viewResolver.resolveViewName(viewName, locale))   
  51. //步驟6 視圖在渲染時會把Model傳入(view.render(mv.getModelInternal(), request, response);)   
  52.             if (mv != null && !mv.wasCleared()) {   
  53.                 render(mv, processedRequest, response);   
  54.                 if (errorView) {   
  55.                     WebUtils.clearErrorRequestAttributes(request);   
  56.                 }   
  57.             }   
  58.             else {   
  59.                 if (logger.isDebugEnabled()) {   
  60.                     logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +   
  61.                             "': assuming HandlerAdapter completed request handling");   
  62.                 }   
  63.             }   
  64.    
  65.             // 執行處理器相關的攔截器的完成后處理(HandlerInterceptor.afterCompletion)   
  66.             //此處省略具體代碼   
  67.    
  68.         catch (Exception ex) {   
  69.             // Trigger after-completion for thrown exception.   
  70.             triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);   
  71.             throw ex;   
  72.         }   
  73.         catch (Error err) {   
  74.             ServletException ex = new NestedServletException("Handler processing failed", err);   
  75.             // Trigger after-completion for thrown exception.   
  76.             triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);   
  77.             throw ex;   
  78.         }   
  79.    
  80.         finally {   
  81.             // Clean up any resources used by a multipart request.   
  82.             if (processedRequest != request) {   
  83.                 cleanupMultipart(processedRequest);   
  84.             }   
  85.         }   
  86.     }   

這個方法不長,基本就是負責其它方法的調用,從我們上面分析到前端請求第一步到達SpringMVC后調用HandlerMapping(處理器映射器)返回執行鏈HandlerExecutionChain:

 

我們debug啟動項目,打個斷點看看,這個HandlerExecutionChain到底是個什么東西。

 

我們可以看到,當斷點執行到HandlerExecutionChain后,查看HandlerExecutionChain中的handler其實就是我們自己的請求訪問的Controller,比如上面的我們請求登陸操作,handler里面的信息就是我們自己的LoginController。

同時包含LoginController的BeanType,前端要請求的方法,以及參數這個元數據信息,簡單的概括就是:「HandlerExecutionChain里面handler就是我們要請求的Controller以及和一些interceptors信息」。

那么在獲取到這個HandlerExecutionChain之前肯定是有初始化所有的Spring容器中的Bean以及所有的url與Bean對應的HandlerMapping對象。

這個都是在Spring中去完成的,這個我們后面在做了解,我們再進一步的了解HandlerMapping對象存儲的內容,再getHandler方法里面進行打斷點:

 

handlerMapping是一個List對象,里面主要是這七個成員信息,我們比較熟悉的就是BeanNameUrlMapping和SimpleUrlHandlerMapping對象,這些里面可以看出「handlerMapping主要存儲的各種映射規則」,通過beanName或者url映射到對應的Bean對象。

 

繼續往里面看,可以看到這里有個applicationContext對象,這個也就我們的上下文,里面還有beanFactory,也就是Spring管理的Bean對象都在這個工廠里面,包括Spring自己的和我們自己定義Bean信息。

 

這個就是HandlerMapping對象,主要「包含著的Bean映射規則、Bean詳細信息。」

從HandlerMapping->HandlerExecutionChain的過程,用一句通俗易懂的話概括就是:「從茫茫的人海中找到了你(從beanFactory找到了請求對應的Controller以及方法)」。

當獲取完我們的執行鏈后,接著就是獲取我們的「處理器適配器」(HandlerAdapter),

 

從getHandlerAdapter的方法中可以看到,根據返回的handlerMapping對象中的handler對象來獲取對應的HandlerAdapter對象,直接返回。

 

返回HandlerAdapter對象后,通過執行HandlerAdapter的handle方法獲取ModelAndView對象,從這個方法的上面的注釋來看:Actually invoke the handler.。

實際就是通過「反射」的方式動態的執行我們自己的Controller中的方法,也就是前端請求的Controller,因為mappedHandler.getHandler()返回的「handler對象包含著請求Controller的詳細信息,包括全類名」。

 

獲取到ModelAndView之后,接著就執行我們的攔截器的后置處理方法postHandle。

 

從他的源碼可以看出,它是獲取到所有的攔截器,然后一個一個遍歷,執行。

 

執行完所有攔截器的后置處理方法,就是最后䣌視圖的渲染,這里執行的是processDispatchResult方法,并把ModelAndView對象作為參數傳遞進去。

 

在processDispatchResult方法里面最重要的就是render方法了,執行視圖的渲染,最后將渲染的結果呈現給用戶。

 

到這里DispatcherServlet主要執行邏輯就講完了,其實主要講的還是SpringMVC的從前端請求->后臺->前端這樣的一個過程,限于篇幅,從源碼的角度大概講解這個的過程是怎么跑起來的。

 

一篇文章要把SpringMVC的都講清楚是不可能的,SpringMVC所有講下來,都能寫一本書了,后續的源碼我們繼續精進,這篇作為一個大體脈絡的了解。

本文轉載自微信公眾號「非科班的科班」,可以通過以下二維碼關注。轉載本文請聯系非科班的科班公眾號。

 

責任編輯:武曉燕 來源: 非科班的科班
相關推薦

2021-11-24 22:42:15

WorkManagerAPI

2020-10-17 08:48:12

搞懂“智能聯接”

2025-07-04 02:12:00

2022-07-19 19:39:05

RTK技術定位技術

2020-03-09 17:28:51

NoSQLMongoDB數據庫

2023-09-11 08:13:03

分布式跟蹤工具

2025-07-10 02:11:00

毫米波雷達4G

2021-01-14 07:15:19

NginxWeb服務器

2021-05-14 23:31:50

大數據計算機開發

2021-09-29 09:00:19

Linux虛擬機CentOS

2021-03-12 13:46:49

鴻蒙HarmonyOS應用

2019-06-18 08:13:47

內網公網NAT

2020-10-18 07:32:06

SD-WAN網絡傳統廣域網

2025-10-17 07:05:00

Python數據可視化數據科學

2020-08-03 10:00:11

前端登錄服務器

2023-04-24 08:00:00

ES集群容器

2021-04-14 15:54:20

Kubernetes程序工具

2018-01-17 09:32:45

人工智能卷積神經網絡CNN

2018-11-14 11:57:28

2023-10-30 07:12:04

點贊
收藏

51CTO技術棧公眾號

午夜美女福利视频| 欧美激情图片小说| 日本成人在线网站| 亚洲综合色丁香婷婷六月图片| 波多野结衣成人在线| 久久久精品视频网站| 五月开心六月丁香综合色啪| 精品国产不卡一区二区三区| 国产日韩成人内射视频 | 国产亚洲精品美女久久久| 亚欧激情乱码久久久久久久久| 国产高清在线a视频大全| 91小视频在线| 亚洲一区二区三区毛片| 成人免费毛片视频| 亚洲视频观看| 久久精彩免费视频| 最近中文字幕免费视频| 中文字幕区一区二区三| 精品视频1区2区| www.中文字幕在线| 日韩电影免费观看| 一区二区中文字幕在线| 欧美三级网色| 污污网站免费在线观看| 国产精品99久久久久久似苏梦涵| 国产成人亚洲综合91| 国产无码精品一区二区| 性xxxx欧美老肥妇牲乱| 在线观看国产精品淫| 国产黄色三级网站| 1313精品午夜理伦电影| 欧美高清一级片在线| 一本色道久久88综合亚洲精品ⅰ | 久久91亚洲精品中文字幕奶水| 亚洲乱码国产乱码精品精大量| 国产精品久久久久久久久久辛辛 | 久久国产乱子伦免费精品| 亚洲91av| 有坂深雪av一区二区精品| 五月天丁香综合久久国产| 天天操天天干天天爽| 国产精品99久久久| 91在线免费观看网站| 中文字幕福利视频| 裸体素人女欧美日韩| 97国产在线观看| 精品在线视频免费| 欧美日本一区| 欧美激情欧美激情在线五月| 裸体武打性艳史| 国产亚洲一卡2卡3卡4卡新区 | 91手机在线观看| 国产免费高清av| 国产在线精品一区二区| 成人免费激情视频| 一级爱爱免费视频| 久久国产生活片100| 国产情人节一区| 一级全黄少妇性色生活片| 理论电影国产精品| 成人av色在线观看| 国产www免费观看| 国产激情视频一区二区在线观看| 97伦理在线四区| 国产后入清纯学生妹| 东方欧美亚洲色图在线| 好看的日韩精品视频在线| 亚洲色图另类小说| 国产日产精品1区| 亚洲一区二区精品在线观看| 日本在线天堂| 亚洲黄色免费电影| 奇米精品一区二区三区| 日本在线中文字幕一区二区三区| 欧美日韩精品一区二区三区蜜桃| 911福利视频| 亚洲三级av| 日韩精品在线看| 九九九视频在线观看| 天堂美国久久| 久久久久久中文字幕| 免费观看成人毛片| 美女网站一区二区| 99在线免费观看视频| 色婷婷av一区二区三区之e本道| 91丝袜美腿高跟国产极品老师| 欧美一区二区三区四区在线观看地址| jizz日韩| 亚洲国产精品久久久久婷婷884 | 日本视频一区二区在线观看| 秋霞影院午夜丰满少妇在线视频| 亚洲综合在线视频| 人妻无码视频一区二区三区 | 国产主播一区二区三区四区| 国产黄色片在线观看| 夜夜亚洲天天久久| 蜜桃免费在线视频| 国产精品视频3p| 社区色欧美激情 | 精品成人久久久| 老色鬼精品视频在线观看播放| 国产精品亚洲一区| 日韩免费啪啪| 欧美日韩一区二区在线播放| 亚洲一级片av| 九九久久精品| 欧美极品少妇xxxxⅹ裸体艺术| 久久国产乱子伦精品| 国产成人免费视频精品含羞草妖精| 欧美一区2区三区4区公司二百| 91网在线看| 欧美性色欧美a在线播放| 日本50路肥熟bbw| 99久久婷婷| 国产97在线观看| 欧美特黄一级视频| 亚洲欧美区自拍先锋| 黄色av免费在线播放| 国产精品流白浆在线观看| 日韩中文字幕亚洲| www.久久视频| 91麻豆国产自产在线观看| 欧美日韩亚洲国产成人| 91tv亚洲精品香蕉国产一区| 日韩精品极品视频免费观看| 久久国产精品二区| 国产一区二区三区四区五区入口 | 久久精品日韩欧美| 国产麻豆一区二区三区在线观看| 国内外激情在线| 精品视频色一区| 女女互磨互喷水高潮les呻吟 | 午夜精品久久久久久久99黑人| 国产精品久久久久久久久毛片 | 亚洲黄色成人网| 欧美精品色哟哟| 国产一区二区91| 国产精品夜夜夜爽张柏芝| aaaa欧美| 在线看片第一页欧美| 亚洲不卡在线视频| 久久亚洲二区三区| 成人免费在线小视频| 久久九九热re6这里有精品| 欧美激情精品久久久久久免费印度 | 欧美日韩卡一卡二| 在线视频这里只有精品| 美女视频黄久久| 杨幂一区欧美专区| 自拍偷拍亚洲图片| 欧美成人亚洲成人| 亚洲第一页综合| 亚洲成av人在线观看| 亚洲图片综合网| 99精品福利视频| 久久亚洲国产精品日日av夜夜| 欧亚在线中文字幕免费| 亚洲欧美日韩一区二区在线| 最新在线中文字幕| 国产精品福利在线播放| 精品亚洲视频在线| 欧美有码视频| 国产伦精品一区二区三区视频黑人| av中文字幕在线观看第一页| 国产丝袜精品第一页| 99成人精品视频| 综合电影一区二区三区| 韩国三级丰满少妇高潮| 99国产精品| 亚洲v国产v| 久久综合给合| 78色国产精品| av电影在线网| 欧美本精品男人aⅴ天堂| 青青草av在线播放| 国产精品素人一区二区| 日本r级电影在线观看| 夜夜精品视频| 中文字幕综合在线观看| xxxx日韩| 国产日韩欧美在线看| 欧美草逼视频| 亚洲人成欧美中文字幕| 国产精品怡红院| 欧美日韩国产在线| 三级黄色在线观看| 不卡高清视频专区| 8x8x最新地址| 极品av少妇一区二区| 三区精品视频| 国产日韩三级| 国产日韩精品在线观看| 国产h片在线观看| 日韩在线观看免费| 青春草在线观看 | 国产精品亚洲激情| 黄色羞羞视频在线观看| 一区二区三区视频观看| 手机看片一区二区| 91精品黄色片免费大全| 黄色av一级片| 亚洲曰韩产成在线| 91传媒免费观看| 久久久综合九色合综国产精品| 黄色a级三级三级三级| 日韩1区2区3区| 波多野结衣综合网| 欧美fxxxxxx另类| 伊人久久大香线蕉综合75| 亚洲精品无吗| 激情小说综合区| 国模大尺度视频一区二区| 国产精品91在线观看| а√天堂8资源中文在线| 久久综合伊人77777尤物| 国产视频精选在线| 亚洲欧美另类自拍| 天堂在线视频免费观看| 欧美成人一区二区三区片免费 | 免费一级片在线观看| 国产精品沙发午睡系列990531| 五月婷婷综合在线观看| av福利精品导航| 亚洲av午夜精品一区二区三区| 美洲天堂一区二卡三卡四卡视频| 成人在线观看黄| 国产日本精品| 人妻夜夜添夜夜无码av| 欧美片第1页综合| 色哺乳xxxxhd奶水米仓惠香| 久久在线视频| 一区二区三区四区欧美日韩| 国产欧美一区二区三区精品观看| 久久精品二区| 欧美爱爱网站| 九九九九久久久久| 天天躁日日躁狠狠躁欧美巨大小说| 国产日韩二区| 欧美交a欧美精品喷水| 韩国一区二区三区美女美女秀 | 91蝌蚪精品视频| 高清免费日韩| 国产精品1luya在线播放| 99热最新在线| 嗯用力啊快一点好舒服小柔久久| 岛国视频一区免费观看| 国产精品18hdxxxⅹ在线| 国产亚洲精品久久飘花| 亚洲国产最新| 青青草国产精品| 日韩中文首页| 天天干天天操天天干天天操| 中文字幕免费一区二区| 国产911在线观看| 亚洲麻豆一区| 久久久免费高清电视剧观看| 亚洲wwwww| 性欧美办公室18xxxxhd| 97成人资源| 国产原创欧美精品| 91精品国产自产在线丝袜啪| 国内精品视频在线播放| 精品久久网站| 中文字幕日韩精品久久| 欧美色图首页| 狠狠爱免费视频| 麻豆中文一区二区| 亚洲欧美日韩网站| 99热这里都是精品| 青青草华人在线视频| 亚洲综合一二三区| 国产91精品看黄网站在线观看| 欧美日韩一区不卡| 亚洲精品字幕在线| 亚洲欧美www| 黄色网址免费在线观看| 午夜精品久久久久久久白皮肤| 国产私拍福利精品视频二区| 91视频99| 人人狠狠综合久久亚洲婷| 一二三在线视频| 久久三级福利| 18深夜在线观看免费视频| 91亚洲国产成人精品一区二区三| 香蕉成人在线视频| 亚洲大型综合色站| 91精品国产色综合久久不8| 精品日韩99亚洲| 97电影在线观看| 午夜精品久久17c| 亚洲人成777| 蜜桃av噜噜一区二区三| 香蕉av一区二区| 国产成人无码av在线播放dvd| 国精品**一区二区三区在线蜜桃| 日韩 中文字幕| 亚洲精品中文字幕在线观看| 99re国产在线| 亚洲国产精品久久久| 国产视频在线播放| 国产成人精品亚洲精品| 51vv免费精品视频一区二区 | 97视频在线观看网站| 午夜精品美女自拍福到在线| 国产精品va视频| 亚洲欧美日韩国产成人综合一二三区| 亚洲精品麻豆| 性生活一级大片| 国产精品污www在线观看| 男女视频免费看| 精品人在线二区三区| 欧美天天影院| 国产欧美日韩精品在线观看 | 视频一区二区视频| 日韩精品91亚洲二区在线观看| 亚洲中文字幕无码一区| 亚洲免费色视频| 一区二区 亚洲| 一个人www欧美| 欧美xxxxxx| 蜜桃欧美视频| 国产精品普通话对白| 扒开伸进免费视频| 亚洲综合自拍偷拍| 精品国产av 无码一区二区三区 | 九一国产在线观看| 欧美精品一区二| 色操视频在线| 痴汉一区二区三区| 国色天香一区二区| 国产69视频在线观看| 亚洲伊人色欲综合网| 精品人妻伦一二三区久久| 美女福利视频一区| 高清久久精品| 国产免费xxx| 国产高清不卡一区二区| 青娱乐国产在线视频| 欧美一级高清片在线观看| 二区三区四区高清视频在线观看| 成人精品一区二区三区| 国产精品videosex性欧美| 一级淫片在线观看| 亚洲人午夜精品天堂一二香蕉| 国产女人高潮时对白| 另类视频在线观看| 亚洲精品福利| 成人毛片一区二区| 91视频国产资源| 黄色网址中文字幕| 日韩中文在线中文网在线观看 | 欧美成人精品高清在线播放| 日本伦理一区二区| 精选一区二区三区四区五区| 鲁大师影院一区二区三区| 久久久久久久毛片| 欧美日韩国产123区| 中文字幕资源网在线观看| 国产精品10p综合二区| 国产欧美另类| 精品一区二区三区蜜桃在线| 欧美日韩极品在线观看一区| 在线观看三级视频| 激情欧美一区二区三区中文字幕| 先锋a资源在线看亚洲| 中国特黄一级片| 日韩一区二区三区精品视频| 高潮在线视频| 亚洲 国产 欧美一区| 福利电影一区二区| 狠狠人妻久久久久久| www.亚洲人.com| 久久精品亚洲成在人线av网址| 999在线免费视频| 亚洲精品国产精品乱码不99| 天堂中文在线资| 国产一区香蕉久久| 亚洲高清资源| 久久久精品成人| 精品国产一区久久| 日韩成人影音| 日韩精品一区二区在线视频| 久久亚洲一级片| 99视频国产精品免费观看a| 57pao成人永久免费视频| 日韩中字在线| 欧美黑人欧美精品刺激| 91精品黄色片免费大全| 欧美香蕉视频| 少妇久久久久久被弄到高潮| 国产亚洲va综合人人澡精品| 精品国自产拍在线观看| 国产成人精品久久二区二区91| 香蕉久久网站| 在线免费观看麻豆| 精品久久久久久最新网址| 成人国产精选| 国产91在线免费| 亚洲乱码精品一二三四区日韩在线|