3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java笔记+踩坑】SpringBoot——基础

發布時間:2024/3/26 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java笔记+踩坑】SpringBoot——基础 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??導航:

【黑馬Java筆記+踩坑匯總】JavaSE+JavaWeb+SSM+SpringBoot+瑞吉外賣+SpringCloud/SpringCloudAlibaba+黑馬旅游+谷粒商城

目錄

1,SpringBoot簡介

1.0 SpringMvc回顧?

1.1 SpringBoot快速入門

1.1.1 開發步驟

1.1.2 SpringBoot 對比Spring

1.1.3 官網構建工程

1.1.4 SpringBoot工程打包啟動

1.2 SpringBoot概述

1.2.1 起步依賴

1.2.2 程序啟動

1.2.3 切換web服務器,由Tomcat切換成Jetty

2,配置文件

2.1 配置文件格式

2.1.1 環境準備

2.1.2 不同配置文件配置端口

2.1.3 三種配置文件的優先級

2.2 yaml配置文件介紹

2.2.1 概述

2.2.2 語法規則

2.2.3 常用配置、清理控制臺

2.3 yaml配置文件數據讀取

2.3.1 環境準備

2.3.2 三種讀取yaml配置數據的方式

2.4 多環境配置

2.4.1 yaml文件

2.4.2 properties文件

2.4.3 命令行啟動參數設置,修改端口、環境

2.4.4 maven和springboot多環境開發兼容

2.5 配置文件分類

2.5.1 概述

2.5.1 代碼演示

3,SpringBoot整合junit

3.0 回顧 Spring 整合 junit

3.1 環境準備

3.2 編寫測試類,@SpringBootTest

4,SpringBoot整合mybatis

4.1 回顧Spring整合Mybatis

4.2 SpringBoot整合mybatis

4.3 案例,整合ssm的書籍增刪改查項目

4.3.1 創建工程

4.3.2 代碼拷貝,@Mapper

4.3.3 配置文件

4.3.4 靜態資源

4.4 SpringBoot整合MyBatis-Plus回顧

5、SSMP整合綜合案例,Book增刪改查分頁

0.模塊創建

1.實體類開發,lombok

2.數據層開發——基礎CRUD

3.數據層開發——分頁功能制作

4.數據層開發——條件查詢功能制作

5.業務層開發

業務層快速開發(慎用)

6.表現層開發

7.表現層消息一致性處理

8.前后端聯通性測試

9.頁面基礎功能開發

F-1.列表功能(非分頁版)

F-2.添加功能

F-3.刪除功能

F-4.修改功能

10.業務消息一致性處理

11.頁面功能開發

F-5.分頁功能

F-6.刪除功能維護

F-7.條件查詢功能


1,SpringBoot簡介

1.0 SpringMvc回顧?

SpringBoot 是由 Pivotal 團隊提供的全新框架,其設計目的是用來簡化 Spring 應用的初始搭建以及開發過程。

使用了 Spring 框架后已經簡化了我們的開發。而 SpringBoot 又是對 Spring 開發進行簡化的,可想而知 SpringBoot 使用的簡單及廣泛性。

回顧 SpringMVC :

  • 1.創建工程,并在 pom.xml 配置文件中配置所依賴的坐標,還可以導入jackson,JSON類型轉換

  • 2.編寫 web3.0 的配置類

    作為 web 程序,web3.0 的配置類不能缺少,而這個配置類還是比較麻煩的,代碼如下

  • 3.編寫 SpringMVC 的配置類

做到這只是將工程的架子搭起來。要想被外界訪問,最起碼還需要提供一個 Controller 類,在該類中提供一個方法。

  • 4.編寫 Controller 類

從上面的 SpringMVC 程序開發可以看到,前三步都是在搭建環境,而且這三步基本都是固定的。SpringBoot 就是對這三步進行簡化了。接下來我們通過一個入門案例來體現 SpingBoot 簡化 Spring 開發。

1.1 SpringBoot快速入門

1.1.1 開發步驟

SpringBoot 開發起來特別簡單,分為如下幾步:

  • 創建新模塊,選擇Spring初始化,并配置模塊相關基礎信息
  • 選擇當前模塊需要使用的技術集
  • 開發控制器類
  • 運行自動生成的Application類
  • 知道了 SpringBoot 的開發步驟后,接下來我們進行具體的操作

    創建新模塊

    • 點擊 + 選擇 New Module 創建新模塊

    • 選擇 Spring Initializr ,用來創建 SpringBoot 工程

      以前我們選擇的是 Maven ,今天選擇 Spring Initializr 來快速構建 SpringBoot 工程。而在 Module SDK 這一項選擇我們安裝的 JDK 版本。

    • 對 SpringBoot 工程進行相關的設置

      我們使用這種方式構建的 SpringBoot 工程其實也是 Maven 工程,而該方式只是一種快速構建的方式而已。注意選擇的包是jar,不是war。java版本和jdk版本一致,包名跟組名寫一樣方便閱讀。

      注意:打包方式這里需要設置為 Jar

    • 選中 Web,然后勾選 Spring Web

      由于我們需要開發一個 web 程序,使用到了 SpringMVC 技術,所以按照下圖紅框進行勾選

    • 下圖界面不需要任何修改,直接點擊 Finish 完成 SpringBoot 工程的構建

    經過以上步驟后就創建了如下結構的模塊,它會幫我們自動生成一個 Application 類,而該類一會再啟動服務器時會用到。

    • 刪除選中的文件、目錄:

    報錯解決:

    如果maven模塊的pom圖標顯示不正常,就右鍵pom.xml,添加成Maven項目:

    找不到插件 'org.springframework.boot:spring-boot-maven-plugin:':

    手動導入版本,版本號與springboot一致:

    <plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.7.3</version></plugin>

    注意:

  • 在創建好的工程中不需要創建SpringConfig和SpringMvcConfig配置類

  • 創建好的項目會自動生成其他的一些文件,而這些文件目前對我們來說沒有任何作用,所以可以將這些文件刪除

    可以刪除的目錄和文件如下:

    • .mvn
    • .gitignore
    • HELP.md
    • mvnw
    • mvnw.cmd
  • 所有文件介紹:

    • \1. .gitignore:分布式版本控制系統git的配置文件,意思為忽略提交
    • 在 .gitingore 文件中,遵循相應的語法,即在每一行指定一個忽略規則。 如:.log、/target/、.idea
    • \2. mvnw:全名是maven wrapper的文件
    • 它的作用是在maven-wrapper.properties文件中記錄你要使用的maven版本,當用戶執行mvnw clean 命令時,發現當前用戶的maven版本和期望的版本不一致,那么就下載期望的版本,然后用期望的版本來執行mvn命令,比如mvn clean命令。
    • \3. mvn文件夾:存放mvnw相關文件
    • 存放著maven-wrapper.properties和相關jar包以及名為MavenWrapperDownloader的java文件
    • \4. mvn.cmd:執行mvnw命令的cmd入口
    • 注:mvnw文件適用于Linux(bash),mv斜體樣式*nw.cmd適用于Windows 環境。
    • \5. .iml文件:intellij idea的工程配置文件
    • 里面包含當前project的一些配置信息,如模塊開發的相關信息,比如java組件,maven組件,插件組件等,還可能會存儲一些模塊路徑信息,依賴信息以及一些別的信息。
    • \6. .idea文件夾:存放項目的配置信息
    • 包括數據源,類庫,項目字符編碼,歷史記錄,版本控制信息等。
    • \7. pom.xml:項目對象模型(核心重要)
    • pom.xml主要描述了項目的maven坐標,依賴關系,開發者需要遵循的規則,缺陷管理系統,組織和licenses,以及其他所有的項目相關因素,是項目級別的配置文件。

    創建 Controller

    在 com.itheima.controller 包下創建 BookController ,代碼如下:

    @RestController @RequestMapping("/books") public class BookController {@GetMapping("/{id}")public String getById(@PathVariable Integer id){System.out.println("id ==> "+id);return "hello , spring boot!";} }

    啟動服務器

    運行 SpringBoot 工程不需要使用本地的 Tomcat 和 插件,只需要右鍵運行項目 com.itheima 包下的 Application 類,我們就可以在控制臺看出如下信息

    啟動后修改配置:

    如果報錯:找不到插件org.springframework.boot spring-boot-*maven*-plugin

    進入C:\Users\用戶名.m2\repository

    然后在這個文件夾下搜索spring-boot-maven-plugin,打開這個文件夾,里面都是版本號

    選擇加入pom.xml即可:

    進行測試

    使用 Postman 工具來測試我們的程序

    SpringBoot 是如何讓開發變簡單的呢?

    我們代碼之所以能簡化,就是因為指定的父工程和 Spring Web 依賴實現的

    要研究這個問題,我們需要看看 Application 類和 pom.xml 都書寫了什么。先看看 Applicaion 類,該類內容如下:

    @SpringBootApplication public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);} }

    這個類中的東西很簡單,就在類上添加了一個 @SpringBootApplication 注解,而在主方法中就一行代碼。我們在啟動服務器時就是執行的該類中的主方法

    再看看 pom.xml 配置文件中的內容,可以發現除了打包插件之外,引入的父工程、兩個依賴前綴都是spring-boot-starter

    <?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!--指定了一個父工程,父工程中的東西在該工程中可以繼承過來使用--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.0</version></parent><groupId>com.itheima</groupId><artifactId>springboot_01_quickstart</artifactId><version>0.0.1-SNAPSHOT</version><!--JDK 的版本--><properties><java.version>8</java.version></properties><dependencies><!--該依賴就是我們在創建 SpringBoot 工程勾選的那個 Spring Web 產生的--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--這個是單元測試的依賴,我們現在沒有進行單元測試,所以這個依賴現在可以沒有--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><!--這個插件是在打包時需要的,而這里暫時還沒有用到--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build> </project>

    1.1.2 SpringBoot 對比Spring

    做完 SpringBoot 的入門案例后,接下來對比一下 Spring 程序和 SpringBoot 程序。如下圖

    • 坐標

      Spring 程序中的坐標需要自己編寫,而且坐標非常多

      SpringBoot 程序中的坐標是我們在創建工程時進行勾選自動生成的

    • web3.0配置類

      Spring 程序需要自己編寫這個配置類。這個配置類大家之前編寫過,肯定感覺很復雜

      SpringBoot 程序不需要我們自己書寫

    • 配置類

      Spring/SpringMVC 程序的配置類需要自己書寫。而 SpringBoot 程序則不需要書寫。

    注意:基于Idea的 Spring Initializr 快速構建 SpringBoot 工程時需要聯網。

    1.1.3 官網構建工程

    在入門案例中之所以能快速構建 SpringBoot 工程,是因為 Idea 使用了官網提供了快速構建 SpringBoot 工程的組件實現的。那如何在官網進行工程構建呢?通過如下步驟構建

    進入SpringBoot官網

    官網地址如下:

    https://spring.io/projects/spring-boot

    進入到 SpringBoot 官網后拖到最下方就可以看到如下內容

    然后點擊 Spring Initializr 超鏈接就會跳轉到如下頁面

    這個頁面內容是不是感覺很眼熟的,這和我們使用 Idea 快速構建 SpringBoot 工程的界面基本相同。在上面頁面輸入對應的信息

    選擇依賴

    選擇 Spring Web 可以點擊上圖右上角的 ADD DEPENDENCIES... CTRL + B 按鈕,就會出現如下界面

    生成工程

    以上步驟完成后就可以生成 SpringBoot 工程了。在頁面的最下方點擊 GENERATE CTRL + 回車 按鈕生成工程并下載到本地,如下圖所示

    打開下載好的壓縮包可以看到工程結構和使用 Idea 生成的一模一樣,如下圖

    而打開 pom.xml 文件,里面也包含了父工程和 Spring Web 的依賴。

    通過上面官網的操作,我們知道 Idea 中快速構建 SpringBoot 工程其實就是使用的官網的快速構建組件,那以后即使沒有 Idea 也可以使用官網的方式構建 SpringBoot 工程。

    1.1.4 SpringBoot工程打包啟動

    問題導入

    以后我們和前端開發人員協同開發,而前端開發人員需要測試前端程序就需要后端開啟服務器,這就受制于后端開發人員。為了擺脫這個受制,前端開發人員嘗試著在自己電腦上安裝 Tomcat 和 Idea ,在自己電腦上啟動后端程序,這顯然不現實。

    我們后端可以將 SpringBoot 工程打成 jar 包,該 jar 包運行不依賴于 Tomcat 和 Idea 這些工具也可以正常運行,只是這個 jar 包在運行過程中連接和我們自己程序相同的 Mysql 數據庫即可。這樣就可以解決這個問題,如下圖

    打包

    打包package前先clean是好習慣。

    先終止當前運行的項目。由于我們在構建 SpringBoot 工程時已經在 pom.xml 中配置了spring-boot-maven-plugin插件

    //spring-boot-maven-plugin插件打包時需要的 <plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId> </plugin>

    所以我們只需要使用 Maven 的 package 指令打包就會在 target 目錄生成對應的 Jar 包

    注意:該插件必須配置,不然打好的 jar 包也是有問題的。

    啟動

    進入 jar 包所在位置,地址欄輸入cmd回車,在 命令提示符 中輸入如下命令(將jar包名字改為自己的):

    java -jar springboot_01_quickstart-0.0.1-SNAPSHOT.jar

    啟動jar包并覆蓋設置端口、 切換環境:

    java –jar springboot.jar –-server.port=88 –-spring.profiles.active=test

    執行上述命令就可以看到 SpringBoot 運行的日志信息

    然后postman發請求,可以看到命令行里輸出后端信息,postman展示響應信息。

    非springboot的maven是不能用java -jar命令的。

    1.2 SpringBoot概述

    SpringBoot 是由Pivotal團隊提供的全新框架,其設計目的是用來簡化Spring應用的初始搭建以及開發過程

    大家已經感受了 SpringBoot 程序,回過頭看看 SpringBoot 主要作用是什么,就是簡化 Spring 的搭建過程和開發過程。

    原始 Spring 環境搭建和開發存在以下問題:

    • 配置繁瑣
    • 依賴設置繁瑣

    SpringBoot 程序優點恰巧就是針對 Spring 的缺點

    • 自動配置。這個是用來解決 Spring 程序配置繁瑣的問題
    • 起步依賴(簡化以來配置)。這個是用來解決 Spring 程序依賴設置繁瑣的問題
    • 輔助功能(內置服務器,...)。我們在啟動 SpringBoot 程序時既沒有使用本地的 tomcat 也沒有使用 tomcat 插件,而是使用 SpringBoot 內置的服務器

    接下來我們來說一下 SpringBoot 的起步依賴

    1.2.1 起步依賴

    我們使用 Spring Initializr 方式創建的 Maven 工程的的 pom.xml 配置文件中自動生成了很多包含 starter 的依賴,如下圖

    這些依賴就是啟動依賴,接下來我們探究一下他是如何實現的。

    1.2.1.1 探索父工程

    爺工程spring-boot-dependencies.pom里配置了各依賴插件的特定版本,因此我們只需要使用對應版本的springboot,在pom.xml里配置不含版本的插件或依賴,就可以繼承對應插件或依賴。

    爺工程pom.xml查看:

    從上面的文件中可以看到指定了一個父工程,我們ctrl+b進入到父工程,發現父工程中又指定了一個父工程,如下圖所示

    再進入到該父工程中,在該工程中我們可以看到配置內容結構如下圖所示

    上圖中的 properties 標簽定義了各個技術軟件依賴的版本,避免了我們在使用不同軟件技術時考慮版本的兼容問題。

    在 properties 中我們找 servlet 和 mysql 的版本如下圖

    爺工程pom.xml里依賴管理標簽:

    dependencyManagement 標簽是進行依賴版本鎖定,但是并沒有導入對應的依賴

    如果我們工程需要哪個依賴只需要引入依賴的 groupid 和 artifactId 不需要定義 version。

    爺工程pom.xml里插件管理:

    而 build 標簽中也對插件的版本進行了鎖定,如下圖

    看完了父工程中 pom.xml 的配置后不難理解我們工程的的依賴不配置 version的原因

    1.2.1.2 探索依賴

    在我們創建的工程中的 pom.xml 中配置了spring-boot-starter-web如下依賴

    進入到該依賴,查看 pom.xml 的依賴會發現它引入了如下的依賴

    里面引入了 spring-web 和 spring-webmvc 的依賴,這就是為什么我們的工程中沒有依賴這兩個包還能正常使用 springMVC 中的注解的原因。

    依賴 spring-boot-starter-tomcat ,從名字基本能確認內部依賴了 tomcat所以我們的工程才能正常啟動。

    結論:以后需要使用技術,只需要引入該技術對應的起步依賴即可

    同樣方法,spring-boot-starter-test依賴里有spring-test等依賴。

    小結:

    starter

    • 只要依賴名字中有starter,就一定是起步以來。starter是SpringBoot 中常見項目名稱,定義了當前項目使用的所有項目坐標,以達到減少依賴配置的目的。

    parent

    • 所有 SpringBoot 項目要繼承的項目,定義了若干個坐標版本號(依賴管理,而非依賴),以達到減少依賴沖突的目的
    • spring-boot-starter-parent(2.5.0)與 spring-boot-starter-parent(2.4.6)共計57處坐標版本不同。springboot版本也不是越新越好,實際開發中要看公司項目的spring-boot-starter-parent版本,然后使用對應的springboot版本。

    實際開發

    • 使用任意坐標時,僅書寫GAV中的G和A,V由SpringBoot提供

      G:groupid

      A:artifactId

      V:version

    • 如發生坐標錯誤,再指定version(要小心版本沖突)

    1.2.2 程序啟動

    創建的每一個 SpringBoot 程序時都包含一個類似于下面的類,我們將這個類稱作引導類、主啟動類

    @SpringBootApplication public class Springboot01QuickstartApplication {public static void main(String[] args) {SpringApplication.run(Springboot01QuickstartApplication.class, args);} }

    注意:

    • SpringBoot 在創建項目時,采用jar的打包方式

    • SpringBoot 的引導類是項目的入口運行 main 方法就可以啟動項目

      因為我們在 pom.xml 中配置了 spring-boot-starter-web 依賴,而該依賴通過前面的學習知道它依賴 tomcat ,所以運行 main 方法就可以使用 tomcat 啟動咱們的工程。

    1.2.3 切換web服務器,由Tomcat切換成Jetty

    使用spring-boot-starter-web 依賴實現內置Tomcat服務器,是springboot帶來的輔助功能。

    現在我們啟動工程使用的是 tomcat 服務器,那能不能不使用 tomcat 而使用 jetty 服務器

    jetty 在我們 maven 高級時講 maven 私服使用的服務器,比Tomcat更輕量級,可擴展性強,谷歌應用引擎已全面切換為Jetty,但目前大型應用一般用的還是Tomcat。

    而要切換 web 服務器就需要使用 exclusion 標簽將默認的 tomcat 服務器給排除掉。

    排除Tomcat依賴

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><artifactId>spring-boot-starter-tomcat</artifactId><groupId>org.springframework.boot</groupId></exclusion></exclusions> </dependency>

    引入 jetty 的起步依賴:

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jetty</artifactId> </dependency>

    接下來再次運行引導類,在日志信息中就可以看到使用的是 jetty 服務器

    小結:

    通過切換服務器,我們不難發現在使用 SpringBoot 換技術時只需要導入該技術的起步依賴即可。

    2,配置文件

    2.1 配置文件格式

    我們現在啟動服務器默認的端口號是 8080,訪問路徑可以書寫為

    http://localhost:8080/books/1

    在線上環境我們還是希望將端口號改為 80,這樣在訪問的時候就可以不寫端口號了,如下

    http://localhost/books/1

    SpringBoot 提供了多種屬性配置方式

    • application.properties,常用,在resources包下

      server.port=80
    • application.yml(以后用這種)

      server:port: 81
    • application.yaml

      server:port: 82

    注意:SpringBoot 程序的配置文件名必須是 application ,只是后綴名不同而已。

    2.1.1 環境準備

    創建一個新工程 springboot_02_base_config 用來演示不同的配置文件,工程環境和入門案例一模一樣,結構如下:

    在該工程中的 com.itheima.controller 包下創建一個名為 BookController 的控制器。內容如下:

    @RestController @RequestMapping("/books") public class BookController {@GetMapping("/{id}")public String getById(@PathVariable Integer id){System.out.println("id ==> "+id);return "hello , spring boot!";} }

    2.1.2 不同配置文件配置端口

    • 方法一(默認,不建議):application.properties配置文件

    現在需要進行配置,配合文件必須放在 resources 目錄下,而該目錄下有一個名為 application.properties 的配置文件,我們就可以在該配置文件中修改端口號,在該配置文件中書寫 port ,Idea 就會提示,如下

    application.properties 配置文件內容如下:

    #端口號 server.port = 8888 #項目名,如果不設定,默認是 / server.servlet.context-path : /demo

    啟動服務,會在控制臺打印出日志信息,從日志信息中可以看到綁定的端口號已經修改了

    • 方法二(以后使用):application.yml配置文件

    刪除 application.properties 配置文件中的內容。在 resources 下創建一個名為 application.yml 的配置文件,在該文件中書寫端口號的配置項,格式如下:

    server:#端口號port: 8888#項目名,如果不設定,默認是 /servlet:context-path: /demo

    注意: 在:后,數據前一定要加空格。

    而在 yml 配置文件中也是有提示功能的,我們也可以在該文件中書寫 port ,然后 idea 就會提示并書寫成上面的格式

    啟動服務,可以在控制臺看到綁定的端口號是 81

    • 方法三(不建議):application.yaml配置文件

    刪除 application.yml 配置文件和 application.properties 配置文件內容,然后在 resources 下創建名為 application.yaml 的配置文件,配置內容和后綴名為 yml 的配置文件中的內容相同,只是使用了不同的后綴名而已

    application.yaml 配置文件內容如下:

    server:port: 83

    啟動服務,在控制臺可以看到綁定的端口號

    注意:在配置文件中輸入port,如果沒有提示,可以使用以下方式解決

    • 點擊 File 選中 Project Structure

    • 彈出如下窗口,按圖中標記紅框進行選擇

    • 通過上述操作,會彈出如下窗口

    • 點擊上圖的 + 號,彈出選擇該模塊的配置文件

    • 通過上述幾步后,就可以看到如下界面。properties 類型的配合文件有一個,ymal 類型的配置文件有兩個

    2.1.3 三種配置文件的優先級

    結論:優先級properties>yml>yaml

    在三種配合文件中分別配置不同的端口號,啟動服務查看綁定的端口號。用這種方式就可以看到哪個配置文件的優先級更高一些

    application.properties 文件內容如下:

    server.port=80

    application.yml 文件內容如下:

    server:port: 81

    application.yaml 文件內容如下:

    server:port: 82

    啟動服務,在控制臺可以看到使用的端口號是 80。說明 application.properties 的優先級最高

    注釋掉 application.properties 配置文件內容。再次啟動服務,在控制臺可以看到使用的端口號是 81,說明 application.yml 配置文件為第二優先級。

    從上述的驗證結果可以確定三種配置文件的優先級是:

    application.properties > application.yml > application.yaml

    注意:

    • SpringBoot 核心配置文件名為 application

    • SpringBoot 內置屬性過多,且所有屬性集中在一起修改,在使用時,通過提示鍵+關鍵字修改屬性

      例如要設置日志的級別時,可以在配置文件中書寫 logging,就會提示出來。配置內容如下

      logging:level:root: info

    2.2 yaml配置文件介紹

    2.2.1 概述

    properties 類型的配合文件之前我們學習過,接下來我們重點學習 yaml 類型的配置文件。

    yaml格式擴展名:.yml(主流)或.yaml。

    YAML(YAML Ain't Markup Language),一種數據序列化格式。這種格式的配置文件在近些年已經占有主導地位,那么這種配置文件和前期使用的配置文件是有一些優勢的,我們先看之前使用的配置文件。

    最開始我們使用的是 xml ,格式如下:

    <enterprise><name>itcast</name><age>16</age><tel>4006184000</tel> </enterprise>

    而 properties 類型的配置文件如下

    enterprise.name=itcast enterprise.age=16 enterprise.tel=4006184000

    yaml 類型的配置文件內容如下

    enterprise:name: itcastage: 16tel: 4006184000

    優點:

    • 容易閱讀

      yaml 類型的配置文件比 xml 類型的配置文件更容易閱讀,結構更加清晰

    • 容易與腳本語言交互

    • 以數據為核心,重數據輕格式,如下圖數據清爽

      yaml 更注重數據,而 xml 更注重格式

    YAML 文件擴展名:

    • .yml (主流)
    • .yaml

    上面兩種后綴名都可以,以后使用更多的還是 yml 的。

    2.2.2 語法規則

    • 大小寫敏感

    • 屬性層級關系使用多行描述,每行結尾使用冒號結束(這里冒號說的是標簽名后的冒號

    • 使用縮進表示層級關系同層級左側對齊只允許使用空格(不允許使用Tab鍵)

      空格的個數并不重要,只要保證同層級的左側對齊即可。

    • 屬性值前面添加空格(屬性名與屬性值之間使用冒號加空格作為分隔)

    • #表示注釋

    核心規則:數據前面要加空格與冒號隔開

    數組數據在數據書寫位置的下方使用減號作為數據開始符號,每行書寫一個數據,減號與數據間空格分隔,例如

    enterprise:name: itcastage: 16tel: 4006184000subject:- Java- 前端- 大數據

    連接符---作用:單文件中可以通過---實現多文件的效果。

    #開發 spring:profiles: dev #給開發環境起的名字 server:port: 80 --- #生產 spring:profiles: pro #給生產環境起的名字 server:port: 81 --- #測試 spring:profiles: test #給測試環境起的名字 server:port: 82 ---

    2.2.3 常用配置、清理控制臺

    properties下新建logback.xml:

    <?xml version="1.0" encoding="UTF-8"?> <configuration> </configuration>

    server:port: 80 spring:datasource:type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://localhost/ssm_db?serverTimezone=UTCusername: rootpassword: 填密碼driver-class-name: com.mysql.cj.jdbc.Drivermain:banner-mode: off mybatis-plus:global-config:db-config:table-prefix: tbl_ #關閉圖標banner: false #打開日志configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

    2.3 yaml配置文件數據讀取

    2.3.1 環境準備

    新創建一個名為 springboot_03_read_data 的 SpringBoot 工程,目錄結構如下

    在 com.itheima.controller 包寫創建名為 BookController 的控制器,內容如下

    @RestController @RequestMapping("/books") public class BookController {@GetMapping("/{id}")public String getById(@PathVariable Integer id){System.out.println("id ==> "+id);return "hello , spring boot!";} }

    在 com.itheima.domain 包下創建一個名為 Enterprise 的實體類等會用來封裝數據,內容如下

    public class Enterprise {private String name;private int age;private String tel;private String[] subject;//自己加上setter and getter,別忘了,別忘了,別忘了//toString }

    在 resources 下創建一個名為 application.yml 的配置文件,里面配置了不同的數據,內容如下

    lesson: SpringBootserver:port: 80enterprise:name: itcastage: 16tel: 4006184000subject:- Java- 前端- 大數據

    2.3.2 三種讀取yaml配置數據的方式

    2.3.2.1 使用 @Value注解讀取yaml(適合少量數據)

    使用 @Value("表達式") 注解可以從配合文件中讀取數據,注解中用于讀取屬性名引用方式跟Spring里一樣,是:${一級屬性名.二級屬性名……}

    這種方法和Spring讀取配置文件很像,不同點是Spring要讀取配置文件,要先在SpringConfig配置類掃描配置文件,例如@PropertySource("classpath:jdbc.properties")

    我們可以在 BookController 中使用 @Value 注解讀取配合文件數據,如下

    @RestController @RequestMapping("/books") public class BookController {@Value("${lesson}")private String lesson;@Value("${server.port}")private Integer port;@Value("${enterprise.subject[0]}")private String subject_00;@GetMapping("/{id}")public String getById(@PathVariable Integer id){System.out.println(lesson);System.out.println(port);System.out.println(subject_00);return "hello , spring boot!";} }

    2.3.2.2 自動注入Environment對象讀取yaml(少用,了解)

    上面方式讀取到的數據特別零散,SpringBoot 還可以使用 @Autowired 注解注入 Environment 對象的方式讀取數據。這種方式 SpringBoot 會將配置文件中所有的數據封裝到 Environment 對象中,如果需要使用哪個數據只需要通過調用 Environment 對象的 getProperty(String name) 方法獲取。具體代碼如下:

    @RestController @RequestMapping("/books") public class BookController {@Autowiredprivate Environment env;@GetMapping("/{id}")public String getById(@PathVariable Integer id){System.out.println(env.getProperty("lesson"));System.out.println(env.getProperty("enterprise.name"));System.out.println(env.getProperty("enterprise.subject[0]"));return "hello , spring boot!";} }

    注意:這種方式,框架內容大量數據,而在開發中我們很少使用。

    2.3.2.3 自定義實體類bean讀取yaml(最常用),@ConfigurationProperties

    SpringBoot 還提供了將配置文件中的數據封裝到我們自定義的實體類對象中的方式。具體操作如下:

    • 實體類 bean 的創建交給 Spring 管理

      在類上添加 @Component 注解

    • 使用 @ConfigurationProperties 注解表示加載配置文件

      在該注解中也可以使用 prefix 屬性指定只加載指定前綴的數據

    • 在 BookController 中進行注入

    為什么這種方法最常用:

    例如配置Mybatis時候,會定義一個實體類bean,加載yaml中的數據庫信息。

    具體代碼如下:

    Enterprise 實體類內容如下:實體類要有getter,setter,toString好習慣,防止報錯。

    @Component //ConfigurationProperties譯為配置屬性,prefix前綴必須設為"enterprise",不加冒號,不能少字母。配置prefix后可以讀取到yaml中前綴為enterprise標簽的所有屬性。 //雖然prefix叫前綴,但它的意思是通過標簽名看成前綴。 @ConfigurationProperties(prefix = "enterprise") public class Enterprise {private String name;private int age;private String tel;private String[] subject;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getTel() {return tel;}public void setTel(String tel) {this.tel = tel;}public String[] getSubject() {return subject;}public void setSubject(String[] subject) {this.subject = subject;}@Overridepublic String toString() {return "Enterprise{" +"name='" + name + '\'' +", age=" + age +", tel='" + tel + '\'' +", subject=" + Arrays.toString(subject) +'}';} }

    BookController 內容如下:

    @RestController @RequestMapping("/books") public class BookController {@Autowiredprivate Enterprise enterprise;@GetMapping("/{id}")public String getById(@PathVariable Integer id){System.out.println(enterprise.getName());System.out.println(enterprise.getAge());System.out.println(enterprise.getSubject());System.out.println(enterprise.getTel());System.out.println(enterprise.getSubject()[0]);return "hello , spring boot!";} }

    注意:

    警告:使用第三種方式,在實體類上有如下警告提示

    解決:這個警告提示解決是在 pom.xml 中添加如下依賴即可

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional> </dependency>

    為了加強管理第三方配置類,這種方式還可以優化:

    ?步驟①在引導類上開啟@EnableConfigurationProperties注解,并標注要使用@ConfigurationProperties注解綁定屬性的類

    @SpringBootApplication @EnableConfigurationProperties(ServerConfig.class) public class Springboot13ConfigurationApplication { }

    步驟②:在對應的類上直接使用@ConfigurationProperties進行屬性綁定

    @Data @ConfigurationProperties(prefix = "servers") //這里不用加@component了 public class ServerConfig {private String ipAddress;private int port;private long timeout; }

    注意:

    • 開啟了@EnableConfigurationProperties注解后綁定屬性的ServerConfig類就不能聲明@Component注解,否則會被spring檢測到兩個bean

    當使用@EnableConfigurationProperties注解時,spring會默認將其標注的類定義為bean,因此不能再次聲明@Component注解了。

    2.4 多環境配置

    以后在工作中,對于開發環境、測試環境、生產環境的配置肯定都不相同,比如我們開發階段會在自己的電腦上安裝 mysql ,連接自己電腦上的 mysql 即可,但是項目開發完畢后要上線就需要該配置,將環境的配置改為線上環境的。

    來回的修改配置會很麻煩,而 SpringBoot 給開發者提供了多環境的快捷配置,需要切換環境時只需要改一個配置即可。不同類型的配置文件多環境開發的配置都不相同,接下來對不同類型的配置文件進行說明

    2.4.1 yaml文件

    在 application.yml 中使用 --- 來分割不同的配置,內容如下

    連接符---作用:單文件中可以通過---實現多文件的效果。

    配置多個環境并設置啟動環境:

    #設置啟用的環境 spring:profiles:active: dev #表示使用的是開發環境的配置--- #開發 spring:profiles: dev server:port: 80 --- #生產 spring:profiles: pro server:port: 81 --- #測試 spring:profiles: test server:port: 82 ---

    上面配置中 spring.profiles 是用來給不同的配置起名字的。

    注意:

    在上面配置中給不同配置起名字的 spring.profiles 配置項已經過時。最新用來起名字的配置項是

    #開發 spring:config:activate:on-profile: dev

    2.4.2 properties文件

    properties 類型的配置文件配置多環境需要另外定義不同的配置文件

    • application-dev.properties 是開發環境的配置文件。我們在該文件中配置端口號為 80

      server.port=80
    • application-test.properties 是測試環境的配置文件。我們在該文件中配置端口號為 81

      server.port=81
    • application-pro.properties 是生產環境的配置文件。我們在該文件中配置端口號為 82

      server.port=82

    SpringBoot 只會默認加載名為 application.properties 的配置文件,所以需要在 application.properties 配置文件中設置啟用哪個配置文件,配置如下:

    spring.profiles.active=pro

    2.4.3 命令行啟動參數設置,修改端口、環境

    使用 SpringBoot 開發的程序以后都是打成 jar 包,通過 java -jar xxx.jar 的方式啟動服務的。

    命令行jar包切換環境:

    注意: 命令行啟動參數都是臨時更改,不影響源代碼。

    我們知道 jar 包其實就是一個壓縮包,可以解壓縮,然后修改配置,最后再打成jar包就可以了。這種方式顯然有點麻煩。

    而 SpringBoot 提供了在運行 jar 時設置開啟指定的環境的方式,如下

    java –jar xxx.jar –-spring.profiles.active=test

    命令行jar包修改端口:

    那么這種方式能不能臨時修改端口號呢?也是可以的,可以通過如下方式

    java –jar xxx.jar –-server.port=88

    命令行jar包同時修改環境和端口:

    當然也可以同時設置多個配置,比如即指定啟用哪個環境配置,又臨時指定端口,如下

    java –jar springboot.jar –-server.port=88 –-spring.profiles.active=test

    大家進行測試后就會發現命令行設置的端口號優先級高(也就是使用的是命令行設置的端口號),配置的優先級其實 SpringBoot 官網已經進行了說明 :

    https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config

    進入上面網站后會看到如下頁面

    如果使用了多種方式配合同一個配置項,優先級高的生效。

    2.4.4 maven和springboot多環境開發兼容

    Maven和springboot都有profile環境配置,在實際開發中,應該maven為主,springboot為輔。springboot讀取maven多環境配置。

    pom.xml

    解析resources資源的插件maven-resources-plugin

    配置多環境

    application.yml

    2.5 配置文件分類

    2.5.1 概述

    有這樣的場景,我們開發完畢后需要測試人員進行測試。

    由于測試環境和開發環境的很多配置都不相同,所以測試人員在運行我們的工程時需要臨時修改很多配置,如下

    java –jar springboot.jar –-spring.profiles.active=test --server.port=85 --server.servlet.context-path=/heima --server.tomcat.connection-timeout=-1 …… …… …… …… ……

    針對這種情況,SpringBoot 定義了配置文件不同的放置的位置;而放在不同位置的優先級時不同的。

    SpringBoot 中4級配置文件放置位置:

    • 1級:classpath:application.yml
    • 2級:classpath:config/application.yml
    • 3級:file :application.yml
    • 4級:file :config/application.yml

    說明:

    • 級別越高優先級越高,file:config優先級最高
    • 一二級classpath是為開發用的,三四級file是為打包后設置通用屬性用的。
    • resources下config目錄里放配置文件
    • classpath:是類路徑,在resources下,優先級高。
    • file:是在包目錄下,這個目錄下創建config文件夾里放配置文件優先級最高。

    2.5.1 代碼演示

    在這里我們只演示不同級別配置文件放置位置的優先級。

    2.5.1.1 環境準備

    創建一個名為 springboot_06_config_file 的 SpringBoot 工程,目錄結構如下

    在 resources 下創建一個名為 config 的目錄,在該目錄中創建 application.yml 配置文件,而在該配置文件中將端口號設置為 81,內容如下

    server:port: 81

    而在 resources 下創建的 application.yml 配置文件中并將端口號設置為 80,內容如下

    server:port: 80

    2.5.1.2 驗證1級和2級的優先級

    運行啟動引導類,可以在控制臺看到如下日志信息

    通過這個結果可以得出類路徑下的 config 下的配置文件優先于類路徑下的配置文件。

    2.5.1.3 驗證2級和4級的優先級

    結論:file: config 下的配置文件優先于類路徑下的配置文件。

    要驗證4級,按照以下步驟完成

    • 將工程打成 jar 包

      點擊工程的 package 來打 jar 包

    • 在硬盤上找到 jar 包所在位置

    • 在 jar 包所在位置創建 config 文件夾,在該文件夾下創建 application.yml 配置文件,而在該配合文件中將端口號設置為 82

    • 在命令行使用以下命令運行程序

      java -jar springboot_06_config_file-0.0.1-SNAPSHOT.jar

      運行后日志信息如下

      通過這個結果可以得出file: config 下的配置文件優先于類路徑下的配置文件。

    注意:

    SpringBoot 2.5.0版本存在一個bug,我們在使用這個版本時,需要在 jar 所在位置的 config 目錄下創建一個任意名稱的文件夾

    3,SpringBoot整合junit

    3.0 回顧 Spring 整合 junit

    回顧 Spring 整合 junit

    @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SpringConfig.class) public class UserServiceTest {@Autowiredprivate BookService bookService;@Testpublic void testSave(){bookService.save();} }

    使用 @RunWith 注解指定運行器,使用 @ContextConfiguration 注解來指定配置類或者配置文件。

    SpringBoot 整合 junit 特別簡單,分為以下三步完成

    • 測試類上添加 SpringBootTest 注解
    • 使用 @Autowired 注入要測試的資源
    • 定義測試方法進行測試

    在springboot中,@RunWith不用特別寫,springboot內部自己加上了。@ContextConfiguration加載SpringConfig也不用特別寫了,因為springboot的引導類起到了配置類的作用,這個類會把同位置下所有包掃描一遍,所以@Component的類才能加載成bean,測試類也就不用寫@ContextConfiguration加載SpringConfig了。

    3.1 環境準備

    創建一個名為 springboot_07_test 的 SpringBoot 工程,工程目錄結構如下

    在 com.itheima.service 下創建 BookService 接口,內容如下

    public interface BookService {public void save(); }

    在 com.itheima.service.impl 包寫創建一個 BookServiceImpl 類,使其實現 BookService 接口,內容如下

    @Service public class BookServiceImpl implements BookService {@Overridepublic void save() {System.out.println("book service is running ...");} }

    3.2 編寫測試類,@SpringBootTest

    實際上,整合很簡單,只有一步,包都不用再導, 直接給引導類同包下的測試類注解@SpringBootTest

    test/java 下創建 com.itheima 包,在該包下創建測試類,將 BookService 注入到該測試類中

    @SpringBootTest class Springboot07TestApplicationTests {@Autowiredprivate BookService bookService;@Testpublic void save() {bookService.save();} }

    注意:這里的引導類所在包必須是測試類所在包及其子包。

    例如:

    • 引導類所在包是 com.itheima
    • 測試類所在包是 com.itheima

    如果不滿足這個要求的話,就需要在使用 @SpringBootTest 注解時,使用 classes 屬性指定引導類的字節碼對象。如 @SpringBootTest(classes = Springboot07TestApplication.class)

    4,SpringBoot整合mybatis

    4.1 回顧Spring整合Mybatis

    Spring 整合 Mybatis 需要定義很多配置類

    • SpringConfig 配置類

      • 導入 JdbcConfig 配置類

      • 導入 MybatisConfig 配置類

        @Configuration @ComponentScan("com.itheima") @PropertySource("classpath:jdbc.properties") @Import({JdbcConfig.class,MyBatisConfig.class}) public class SpringConfig { }
    • JdbcConfig 配置類

      • 定義數據源(加載properties配置項:driver、url、username、password)

        public class JdbcConfig {@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String userName;@Value("${jdbc.password}")private String password;@Beanpublic DataSource getDataSource(){DruidDataSource ds = new DruidDataSource();ds.setDriverClassName(driver);ds.setUrl(url);ds.setUsername(userName);ds.setPassword(password);return ds;} }
    • MybatisConfig 配置類

      • 定義 SqlSessionFactoryBean

      • 定義映射配置

        public class MybatisConfig {@Beanpublic SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);factoryBean.setTypeAliasesPackage("package1.pojo");return factoryBean;}@Beanpublic MapperScannerConfigurer mapperScannerConfigurer(){MapperScannerConfigurer msc=new MapperScannerConfigurer();msc.setBasePackage("package1.dao");return msc;} }

    4.2 SpringBoot整合mybatis

    兩個關鍵步驟:@Mapper和yml配置數據源

    • 在dao接口@Mapper或引導類@MapperScan,類同于ssm中MybatisConfig的mapper掃描包。
    • 導入druid依賴、在application.yml中配置數據源dataSource

    4.2.1 創建模塊

    • 創建新模塊,選擇 Spring Initializr,并配置模塊相關基礎信息

    • 選擇當前模塊需要使用的技術集(MyBatis、MySQL)。如果需要寫controller層則再添加Web里的Spring Web,或者在pom.xml導入依賴spring-boot-starter-web

    4.2.2 定義實體類

    在 com.itheima.domain 包下定義實體類 Book,內容如下

    public class Book {private Integer id;private String name;private String type;private String description;//自己生成setter and getter,別忘了,別忘了,別忘了,別忘了,別忘了,別忘了,//toString }

    4.2.3 定義dao接口

    在 com.itheima.dao 包下定義 BookDao 接口,內容如下

    或者可以在引導類掃描@MapperScan

    //@Repository //BookDao是接口無實現類,不定義成bean也能在Service自動注入 @Mapper public interface BookDao {@Select("select * from tbl_book where id = #{id}")public Book getById(Integer id); }

    4.2.4 定義測試類

    在 test/java 下定義包 com.itheima ,在該包下測試類,內容如下

    @SpringBootTest class Springboot08MybatisApplicationTests {@Autowiredprivate BookDao bookDao;@Testvoid testGetById() {Book book = bookDao.getById(1);System.out.println(book);} }

    4.2.5 編寫配置

    我們代碼中并沒有指定連接哪兒個數據庫,用戶名是什么,密碼是什么。所以這部分需要在 SpringBoot 的配置文件中進行配合。

    ?application.yml?

    spring:datasource:#mysql6以后必須driver-class-name中間加cj,url設置時區,否則會報錯driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTCusername: rootpassword: root

    com.mysql.jdbc.Driver與com.mysql.cj.jdbc.Driver的區別:

    • JDBC連接Mysql5需用com.mysql.jdbc.Driver
    • JDBC連接Mysql6需用com.mysql.cj.jdbc.Driver,同時url需要指定時區serverTimezone。
    • 設定時區時,serverTimezone=UTC比中國時間早8個小時,若在中國,可設置serverTimezone=Asia/Shanghai

    4.2.6 測試

    運行測試方法,我們會看到如下錯誤信息

    錯誤信息顯示在 Spring 容器中沒有 BookDao 類型的 bean。為什么會出現這種情況呢?

    原因是 Mybatis 會掃描接口并創建接口的代碼對象交給 Spring 管理,但是現在并沒有告訴 Mybatis 哪個是 dao 接口。而我們要解決這個問題需要在BookDao 接口上使用 @Mapper

    BookDao 接口加上@Mapper注解或者引導類加@MapperScan:

    @Mapper //替代MybatisConfig里的MapperScannerConfigurer方法,也就是Mybatis核心配置文件的<mappers>標簽里的掃描mapper包 public interface BookDao {@Select("select * from tbl_book where id = #{id}")public Book getById(Integer id); }

    注意:

    SpringBoot 版本低于2.4.3(不含),Mysql驅動版本大于8.0時,需要在url連接串中配置時區 jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC,或在MySQL數據庫端配置時區解決此問題

    4.2.6.5 配置內置數據源、運行引導類

    application.yml

    spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/ssm_dbusername: rootpassword: root

    此時運行引導類,項目就已經能跑起來了,不過實際開發中更多的是使用druid數據源。

    4.2.7 使用Druid數據源

    現在我們并沒有指定數據源,SpringBoot 有默認的數據源,我們也可以指定使用 Druid 數據源,按照以下步驟實現

    • 導入 Druid 依賴

      <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version> </dependency>
    • 在 application.yml 配置文件配置

      可以通過 spring.datasource.type 來配置使用什么數據源。配置文件內容可以改進為

      spring:datasource: #druid建議driver設成com.mysql.cj.jdbc.Driverdriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/ssm_dbusername: rootpassword: roottype: com.alibaba.druid.pool.DruidDataSource

    如果spring-boot-starter-parent版本是2.4.3 以前,在url后面加上?serverTimezone=UTC,否則會報錯:

    spring:datasource: #druid建議driver設成com.mysql.cj.jdbc.Driverdriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTCusername: rootpassword: roottype: com.alibaba.druid.pool.DruidDataSource

    4.3 案例,整合ssm的書籍增刪改查項目

    SpringBoot 到這就已經學習完畢,接下來我們將學習 SSM 時做的三大框架整合的案例用 SpringBoot 來實現一下。我們完成這個案例基本是將之前做的拷貝過來,修改成 SpringBoot 的即可,主要從以下幾部分完成

  • pom.xml

    配置起步依賴,必要的資源坐標(druid)

  • application.yml

    設置數據源、端口等

  • 配置類

    全部刪除

  • dao

    設置@Mapper

  • 測試類

  • 頁面

    放置在resources目錄下的static目錄中

  • 4.3.1 創建工程

    創建 SpringBoot 工程,在創建工程時需要勾選 web、mysql、mybatis,工程目錄結構如下

    由于我們工程中使用到了 Druid ,所以需要導入 Druid 的坐標

    <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version> </dependency>

    4.3.2 代碼拷貝,@Mapper

    將上一節整合ssm的項目, springmvc_11_page 工程中的 java 代碼及測試代碼連同包拷貝到 springboot_09_ssm 工程,按照下圖進行拷貝

    需要修改的內容如下:

    • Springmvc_11_page 中 config 包下的是配置類,而 SpringBoot 工程不需要這些配置類,所以這些可以直接刪除

    • dao 包下的接口上在拷貝到 springboot_09-ssm 工程中需要在接口中添加 @Mapper 注解

    • BookServiceTest 測試類需要加@SpringBootTest注解,改成 SpringBoot 整合 junit 的

      @SpringBootTest public class BookServiceTest {@Autowiredprivate BookService bookService;@Testpublic void testGetById(){Book book = bookService.getById(2);System.out.println(book);}@Testpublic void testGetAll(){List<Book> all = bookService.getAll();System.out.println(all);} }

    另外還需要修改配置文件。

    controller包下攔截器interceptor失效,因為以前需要SpringMvcConfig實現WebMvcConfigurer 接口;

    因為沒有了ServletConfig,springmvc也就不會攔截資源,也就不用放行靜態資源了

    SpringMvcConfig回顧:

    @Configuration //package1.config主要為了掃描項目攔截器類、ServletContainersInitConfig類 @ComponentScan({"package1.controller","package1.config"}) @EnableWebMvc public class SpringMvcConfig implements WebMvcConfigurer {@Autowiredprivate ProjectInterception projectInterception;//添加攔截器,配置本地資源映射路徑,在訪問A(虛擬的)的時候,需要到B(實際的)的位置去訪問。@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(projectInterception).addPathPatterns("/books","/books/*");//如果只攔截/books,發送http://localhost/books/100后會發現攔截器沒有被執行//registry.addInterceptor(projectInterceptor).addPathPatterns("/books");}//添加資源處理器@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");registry.addResourceHandler("/js/**").addResourceLocations("/js/");registry.addResourceHandler("/css/**").addResourceLocations("/css/");registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");} }

    4.3.3 配置文件

    在 application.yml 配置文件中需要配置如下內容

    • 服務的端口號
    • 連接數據庫的信息
    • 數據源
    server:port: 80spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/ssm_db?servierTimezone=UTCusername: rootpassword: root

    4.3.4 靜態資源

    在 SpringBoot 程序中是沒有 webapp 目錄的,那么在 SpringBoot 程序中靜態資源需要放在什么位置呢?

    靜態資源需要放在 resources 下的 static 下,如下圖所示

    另外配置一個index.html,實現直接http://localhost/即可訪問books列表:

    然后運行引導類,先輸入http://localhost/books測試后端,再用postman測試所有功能,完成。

    4.4 SpringBoot整合MyBatis-Plus回顧

    具體整合看下面文章的入門案例:

    MyBatisPlus基礎_vincewm的博客-CSDN博客

    步驟①:導入對應的starter

    <!--mybatis和mysql依賴勾選自動生成--> <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version> </dependency> <dependencies><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.6</version></dependency> </dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>

    關于這個坐標,此處要說明一點,之前我們看的starter都是spring-boot-starter-???,也就是說都是下面的格式

    Spring-boot-start-***

    而MyBatis與MyBatisPlus這兩個坐標的名字書寫比較特殊,是第三方技術名稱在前,boot和starter在后。

    springboot依賴命名規范:

    starter所屬命名規則示例
    官方提供spring-boot-starter-技術名稱spring-boot-starter-web spring-boot-starter-test
    第三方提供第三方技術名稱-spring-boot-startermybatis-spring-boot-starter druid-spring-boot-starter
    第三方提供第三方技術名稱-boot-starter(第三方技術名稱過長,簡化命名)mybatis-plus-boot-starter

    溫馨提示

    創建項目時勾選里是沒有mybatisplus的,因為SpringBoot官網還未收錄此坐標。

    步驟②配置數據源相關信息

    #2.配置相關信息 spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/ssm_dbusername: rootpassword: root

    步驟3:映射接口(Dao)

    @Mapper public interface BookDao extends BaseMapper<Book> { }

    核心在于Dao接口繼承了一個BaseMapper的接口,這個接口中幫助開發者預定了若干個常用的API接口,簡化了通用API接口的開發工作。

    下面就可以寫一個測試類進行測試了,此處省略。

    溫馨提示

    目前數據庫的表名定義規則是tbl_模塊名稱,為了能和實體類相對應,需要實體類注解@TableName("表名"),或者配置application.yml文件,添加如下配置即可,設置所有表名的通用前綴名。

    //注解了lombok的@Data會自動生成getter,setter,toString方法 @Data //一般數據庫表名tbl_user,這里注解@TableName("tbl_user"),就可以對應上表名,畢竟mp的語句里沒有指定表名,都是在數據庫中搜索和首字母小的的實體類名對應的表的。 @TableName("user") public class User {//設置主鍵自增策略為auto,mp默認自增策略是ASSIGN_ID,分布式、雪花算法。自增策略也可以在yml中全局配置。@TableId(type = IdType.AUTO)private Long id;private String name;//value屬性起別名,select設置該字段是否參與查詢,針對于一些密碼等隱私數據不希望被查出來@TableField(value = "password",select = false)private String password;private Integer age;private String tel;//exist屬性設置是否在數據庫中存在該字段@TableField(exist = false)private String online;//樂觀鎖注解版本,需要搭配樂觀攔截器@Versionprivate Integer version;//邏輯刪除,本質是更新,數據庫內該字段默認是0,通過標記為1來判定刪除。@TableLogicprivate Integer delete; }

    或者配置yml

    mybatis-plus:global-config:db-config:table-prefix: tbl_ #設置所有表的通用前綴名稱為tbl_

    5、SSMP整合綜合案例,Book增刪改查分頁

    主頁面

    添加

    刪除

    修改

    分頁

    條件查詢

    整體案例中需要采用的技術如下:

  • 實體類開發————使用Lombok快速制作實體類

  • Dao開發————整合MyBatisPlus,制作數據層測試

  • Service開發————基于MyBatisPlus進行增量開發,制作業務層測試類

  • Controller開發————基于Restful開發,前后端開發協議制作,使用PostMan測試接口功能

  • 頁面開發————基于VUE+ElementUI制作,前后端聯調,頁面數據處理,頁面消息處理

    • 列表
    • 新增
    • 修改
    • 刪除
    • 分頁
    • 查詢
  • 項目異常處理————異常攔截器、業務和系統異常類

  • 按條件查詢————頁面功能調整、Controller修正功能、Service修正功能

  • 0.模塊創建

    對于這個案例如果按照企業開發的形式進行應該制作后臺微服務,前后端分離的開發。

    這個對初學的小伙伴要求太高了,咱們簡化一下。后臺做單體服務器,前端不使用前后端分離的制作了。

    一個服務器即充當后臺服務調用,又負責前端頁面展示,降低學習的門檻。

    模塊構建步驟:

    pom.xml

    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency> </dependencies>

    application.yml

    server:port: 80

    1.實體類開發,lombok

    本案例對應的模塊表結構如下:

    -- ---------------------------- -- Table structure for tbl_book -- ---------------------------- DROP TABLE IF EXISTS `tbl_book`; CREATE TABLE `tbl_book` (`id` int(11) NOT NULL AUTO_INCREMENT,`type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 51 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ---------------------------- -- Records of tbl_book -- ---------------------------- INSERT INTO `tbl_book` VALUES (1, '計算機理論', 'Spring實戰 第5版', 'Spring入門經典教程,深入理解Spring原理技術內幕'); INSERT INTO `tbl_book` VALUES (2, '計算機理論', 'Spring 5核心原理與30個類手寫實戰', '十年沉淀之作,手寫Spring精華思想'); INSERT INTO `tbl_book` VALUES (3, '計算機理論', 'Spring 5 設計模式', '深入Spring源碼剖析Spring源碼中蘊含的10大設計模式'); INSERT INTO `tbl_book` VALUES (4, '計算機理論', 'Spring MVC+MyBatis開發從入門到項目實戰', '全方位解析面向Web應用的輕量級框架,帶你成為Spring MVC開發高手'); INSERT INTO `tbl_book` VALUES (5, '計算機理論', '輕量級Java Web企業應用實戰', '源碼級剖析Spring框架,適合已掌握Java基礎的讀者'); INSERT INTO `tbl_book` VALUES (6, '計算機理論', 'Java核心技術 卷I 基礎知識(原書第11版)', 'Core Java 第11版,Jolt大獎獲獎作品,針對Java SE9、10、11全面更新'); INSERT INTO `tbl_book` VALUES (7, '計算機理論', '深入理解Java虛擬機', '5個維度全面剖析JVM,大廠面試知識點全覆蓋'); INSERT INTO `tbl_book` VALUES (8, '計算機理論', 'Java編程思想(第4版)', 'Java學習必讀經典,殿堂級著作!贏得了全球程序員的廣泛贊譽'); INSERT INTO `tbl_book` VALUES (9, '計算機理論', '零基礎學Java(全彩版)', '零基礎自學編程的入門圖書,由淺入深,詳解Java語言的編程思想和核心技術'); INSERT INTO `tbl_book` VALUES (10, '市場營銷', '直播就該這么做:主播高效溝通實戰指南', '成長為網紅的秘密都在書中'); INSERT INTO `tbl_book` VALUES (11, '市場營銷', '直播銷講實戰一本通', '和秋葉一起學系列網絡營銷書籍'); INSERT INTO `tbl_book` VALUES (12, '市場營銷', '直播帶貨:淘寶、天貓直播從新手到高手', '一本教你如何玩轉直播的書,10堂課輕松實現帶貨月入3W+');

    根據上述表結構,制作對應的實體類

    實體類

    public class Book {private Integer id;private String type;private String name;private String description; }

    實體類的開發可以自動通過工具手工生成get/set方法,然后覆蓋toString()方法,方便調試,等等。不過這一套操作書寫很繁瑣,有對應的工具可以幫助我們簡化開發,介紹一個小工具,lombok。

    Lombok,一個Java類庫,提供了一組注解,簡化POJO實體類開發,SpringBoot目前默認集成了lombok技術,并提供了對應的版本控制,所以只需要提供對應的坐標即可,在pom.xml中添加lombok的坐標。

    <dependencies><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency> </dependencies>

    使用lombok可以通過一個注解@Data完成一個實體類對應的getter,setter,toString,equals,hashCode等操作的快速添加

    import lombok.Data; @Data public class Book {private Integer id;private String type;private String name;private String description; }

    到這里實體類就做好了,是不是比不使用lombok簡化好多,這種工具在Java開發中還有N多,后面遇到了能用的實用開發技術時,在不增加各位小伙伴大量的學習時間的情況下,盡量多給大家介紹一些。

    總結

  • 實體類制作

  • 使用lombok簡化開發

    • 導入lombok無需指定版本,由SpringBoot提供版本
    • @Data注解
  • 2.數據層開發——基礎CRUD

    數據層開發本次使用MyBatisPlus技術,數據源使用前面學習的Druid,學都學了都用上。

    步驟①:導入MyBatisPlus與Druid對應的starter,當然mysql的驅動不能少

    <dependencies><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.6</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency> </dependencies>

    ?spring-boot-starter-web和spring-boot-starter-test在創建springboot項目時已經勾選創建了:

    步驟②:配置druid數據庫連接相關的數據源配置

    server:port: 80spring:datasource:druid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTCusername: rootpassword: root

    步驟③:使用MyBatisPlus的標準通用接口BaseMapper加速開發,別忘了@Mapper和泛型的指定

    @Mapper public interface BookDao extends BaseMapper<Book> { }

    步驟④:制作測試類測試結果,這個測試類制作是個好習慣,不過在企業開發中往往都為加速開發跳過此步,且行且珍惜吧

    package com.itheima.dao;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.itheima.domain.Book; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest public class BookDaoTestCase {@Autowiredprivate BookDao bookDao;@Testvoid testGetById(){System.out.println(bookDao.selectById(1));}@Testvoid testSave(){Book book = new Book();book.setType("測試數據123");book.setName("測試數據123");book.setDescription("測試數據123");bookDao.insert(book);}@Testvoid testUpdate(){Book book = new Book();book.setId(17);book.setType("測試數據abcdefg");book.setName("測試數據123");book.setDescription("測試數據123");bookDao.updateById(book);}@Testvoid testDelete(){bookDao.deleteById(16);}@Testvoid testGetAll(){bookDao.selectList(null);} }

    配置id生成策略

    MyBatisPlus技術默認的主鍵生成策略為雪花算法,生成的主鍵ID長度較大,和目前的數據庫設定規則不相符,需要配置一下使MyBatisPlus使用數據庫的主鍵生成策略。在application.yml中添加對應配置即可,具體如下

    server:port: 80spring:datasource:druid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTCusername: rootpassword: rootmybatis-plus:global-config:db-config:table-prefix: tbl_ #設置表名通用前綴id-type: auto #設置主鍵id字段的生成策略為參照數據庫設定的策略,當前數據庫設置id生成策略為自增

    清理控制臺沒用日志

    yml

    mybatis-plus:global-config:banner: false spring:main:banner-mode: off

    resources下創建logback.xml

    <?xml version="1.0" encoding="UTF-8"?> <configuration> </configuration>

    查看MyBatisPlus運行日志

    在進行數據層測試的時候,因為基礎的CRUD操作均由MyBatisPlus給我們提供了,所以就出現了一個局面,開發者不需要書寫SQL語句了,這樣程序運行的時候總有一種感覺,一切的一切都是黑盒的,作為開發者我們啥也不知道就完了。如果程序正常運行還好,如果報錯了,這個時候就很崩潰,你甚至都不知道從何下手,因為傳遞參數、封裝SQL語句這些操作完全不是你開發出來的,所以查看執行期運行的SQL語句就成為當務之急。

    SpringBoot整合MyBatisPlus的時候充分考慮到了這點,通過配置的形式就可以查閱執行期SQL語句,配置如下

    mybatis-plus:global-config:db-config:table-prefix: tbl_id-type: autoconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

    再來看運行結果,此時就顯示了運行期執行SQL的情況。

    Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2c9a6717] was not registered for synchronization because synchronization is not active JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@6ca30b8a] will not be managed by Spring ==> Preparing: SELECT id,type,name,description FROM tbl_book ==> Parameters: <== Columns: id, type, name, description <== Row: 1, 計算機理論, Spring實戰 第5版, Spring入門經典教程,深入理解Spring原理技術內幕 <== Row: 2, 計算機理論, Spring 5核心原理與30個類手寫實戰, 十年沉淀之作,手寫Spring精華思想 <== Row: 3, 計算機理論, Spring 5 設計模式, 深入Spring源碼剖析Spring源碼中蘊含的10大設計模式 <== Row: 4, 計算機理論, Spring MVC+MyBatis開發從入門到項目實戰, 全方位解析面向Web應用的輕量級框架,帶你成為Spring MVC開發高手 <== Row: 5, 計算機理論, 輕量級Java Web企業應用實戰, 源碼級剖析Spring框架,適合已掌握Java基礎的讀者 <== Row: 6, 計算機理論, Java核心技術 卷I 基礎知識(原書第11版), Core Java 第11版,Jolt大獎獲獎作品,針對Java SE9、10、11全面更新 <== Row: 7, 計算機理論, 深入理解Java虛擬機, 5個維度全面剖析JVM,大廠面試知識點全覆蓋 <== Row: 8, 計算機理論, Java編程思想(第4版), Java學習必讀經典,殿堂級著作!贏得了全球程序員的廣泛贊譽 <== Row: 9, 計算機理論, 零基礎學Java(全彩版), 零基礎自學編程的入門圖書,由淺入深,詳解Java語言的編程思想和核心技術 <== Row: 10, 市場營銷, 直播就該這么做:主播高效溝通實戰指南, 成長為網紅的秘密都在書中 <== Row: 11, 市場營銷, 直播銷講實戰一本通, 和秋葉一起學系列網絡營銷書籍 <== Row: 12, 市場營銷, 直播帶貨:淘寶、天貓直播從新手到高手, 一本教你如何玩轉直播的書,10堂課輕松實現帶貨月入3W+ <== Row: 13, 測試類型, 測試數據, 測試描述數據 <== Row: 14, 測試數據update, 測試數據update, 測試數據update <== Row: 15, -----------------, 測試數據123, 測試數據123 <== Total: 15

    其中清晰的標注了當前執行的SQL語句是什么,攜帶了什么參數,對應的執行結果是什么,所有信息應有盡有。

    此處設置的是日志的顯示形式,當前配置的是控制臺輸出,當然還可以由更多的選擇,根據需求切換即可

    總結

  • 手工導入starter坐標(2個),mysql驅動(1個)

  • 配置數據源與MyBatisPlus對應的配置

  • 開發Dao接口(繼承BaseMapper)

  • 制作測試類測試Dao功能是否有效

  • 使用配置方式開啟日志,設置日志輸出方式為標準輸出即可查閱SQL執行日志

  • 3.數據層開發——分頁功能制作

    前面僅僅是使用了MyBatisPlus提供的基礎CRUD功能,實際上MyBatisPlus給我們提供了幾乎所有的基礎操作,這一節說一下如何實現數據庫端的分頁操作。

    MyBatisPlus提供的分頁操作API如下:

    @Test void testGetPage(){IPage page = new Page(2,5);bookDao.selectPage(page, null);System.out.println(page.getCurrent());System.out.println(page.getSize());System.out.println(page.getTotal());System.out.println(page.getPages());System.out.println(page.getRecords()); }

    其中selectPage方法需要傳入一個封裝分頁數據的對象,可以通過new的形式創建這個對象,當然這個對象也是MyBatisPlus提供的,別選錯包了。創建此對象時需要指定兩個分頁的基本數據

    • 當前顯示第幾頁
    • 每頁顯示幾條數據

    可以通過創建Page對象時利用構造方法初始化這兩個數據。

    IPage page = new Page(2,5);

    將該對象傳入到查詢方法selectPage后,可以得到查詢結果,但是我們會發現當前操作查詢結果返回值仍然是一個IPage對象,這又是怎么回事?

    IPage page = bookDao.selectPage(page, null);

    原來這個IPage對象中封裝了若干個數據,而查詢的結果作為IPage對象封裝的一個數據存在的,可以理解為查詢結果得到后,又塞到了這個IPage對象中,其實還是為了高度的封裝,一個IPage描述了分頁所有的信息。下面5個操作就是IPage對象中封裝的所有信息了。

    @Test void testGetPage(){IPage page = new Page(2,5);bookDao.selectPage(page, null);System.out.println(page.getCurrent()); //當前頁碼值System.out.println(page.getSize()); //每頁顯示數System.out.println(page.getTotal()); //數據總量System.out.println(page.getPages()); //總頁數System.out.println(page.getRecords()); //詳細數據 }

    到這里就知道這些數據如何獲取了,但是當你去執行這個操作時,你會發現并不像我們分析的這樣,實際上這個分頁功能當前是無效的。為什么這樣呢?這個要源于MyBatisPlus的內部機制。

    對于MySQL的分頁操作使用limit關鍵字進行,而并不是所有的數據庫都使用limit關鍵字實現的,這個時候MyBatisPlus為了制作的兼容性強,將分頁操作設置為基礎查詢操作的升級版,你可以理解為IPhone6與IPhone6S-PLUS的關系。

    基礎操作中有查詢全部的功能,而在這個基礎上只需要升級一下(PLUS)就可以得到分頁操作。所以MyBatisPlus將分頁操作做成了一個開關,你用分頁功能就把開關開啟,不用就不需要開啟這個開關。而我們現在沒有開啟這個開關,所以分頁操作是沒有的。這個開關是通過MyBatisPlus的攔截器的形式存在的,其中的原理這里不分析了,有興趣的小伙伴可以學習MyBatisPlus這門課程進行詳細解讀。具體設置方式如下:

    定義MyBatisPlus攔截器并將其設置為Spring管控的bean

    @Configuration public class MPConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor());return interceptor;} }

    上述代碼第一行是創建MyBatisPlus的攔截器棧,這個時候攔截器棧中沒有具體的攔截器,第二行是初始化了分頁攔截器,并添加到攔截器棧中。如果后期開發其他功能,需要添加全新的攔截器,按照第二行的格式繼續add進去新的攔截器就可以了。

    總結

  • 使用IPage封裝分頁數據
  • 分頁操作依賴MyBatisPlus分頁攔截器實現功能
  • 借助MyBatisPlus日志查閱執行SQL語句
  • 4.數據層開發——條件查詢功能制作

    除了分頁功能,MyBatisPlus還提供有強大的條件查詢功能。以往我們寫條件查詢要自己動態拼寫復雜的SQL語句,現在簡單了,MyBatisPlus將這些操作都制作成API接口,調用一個又一個的方法就可以實現各種條件的拼裝。這里給大家普及一下基本格式,詳細的操作還是到MyBatisPlus的課程中查閱吧。

    下面的操作就是執行一個模糊匹配對應的操作,由like條件書寫變為了like方法的調用。

    @Test void testGetBy(){QueryWrapper<Book> qw = new QueryWrapper<>();qw.like("name","Spring");bookDao.selectList(qw); }

    其中第一句QueryWrapper對象是一個用于封裝查詢條件的對象,該對象可以動態使用API調用的方法添加條件,最終轉化成對應的SQL語句。第二句就是一個條件了,需要什么條件,使用QueryWapper對象直接調用對應操作即可。比如做大于小于關系,就可以使用lt或gt方法,等于使用eq方法,等等,此處不做更多的解釋了。

    這組API使用還是比較簡單的,但是關于屬性字段名的書寫存在著安全隱患,比如查詢字段name,當前是以字符串的形態書寫的,萬一寫錯,編譯器還沒有辦法發現,只能將問題拋到運行器通過異常堆棧告訴開發者,不太友好。

    MyBatisPlus針對字段檢查進行了功能升級,全面支持Lambda表達式,就有了下面這組API。由QueryWrapper對象升級為LambdaQueryWrapper對象,這下就避免了上述問題的出現。

    @Test void testGetBy2(){String name = "1";LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();lqw.like(Book::getName,name);bookDao.selectList(lqw); }

    為了便于開發者動態拼寫SQL,防止將null數據作為條件使用,MyBatisPlus還提供了動態拼裝SQL的快捷書寫方式。

    @Test void testGetBy2(){String name = "1";LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();//if(name != null) lqw.like(Book::getName,name); //方式一:JAVA代碼控制lqw.like(name != null,Book::getName,name); //方式二:API接口提供控制開關bookDao.selectList(lqw); }

    其實就是個格式,沒有區別。關于MyBatisPlus的基礎操作就說到這里吧,如果這一塊知識不太熟悉的小伙伴建議還是完整的學習一下MyBatisPlus的知識吧,這里只是蜻蜓點水的用了幾個操作而已。

    MyBatisPlus基礎_vincewm的博客-CSDN博客

    總結

  • 使用QueryWrapper對象封裝查詢條件

  • 推薦使用LambdaQueryWrapper對象

  • 所有查詢操作封裝成方法調用

  • 查詢條件支持動態條件拼裝

  • 5.業務層開發

    業務層是組織業務邏輯功能,并根據業務需求,對數據持久層發起調用。目標是為了組織出符合需求的業務邏輯功能,至于調不調用數據層還真不好說,有需求就調用,沒有需求就不調用。

    區分數據層和業務層:

    業務層的方法名定義一定要與業務有關,例如登錄操作

    login(String username,String password);

    而數據層的方法名定義一定與業務無關,是一定,不是可能,也不是有可能,例如根據用戶名密碼查詢

    selectByUserNameAndPassword(String username,String password);

    我們在開發的時候是可以根據完成的工作不同劃分成不同職能的開發團隊的。比如一個哥們制作數據層,他就可以不知道業務是什么樣子,拿到的需求文檔要求可能是這樣的

    接口:傳入用戶名與密碼字段,查詢出對應結果,結果是單條數據 接口:傳入ID字段,查詢出對應結果,結果是單條數據 接口:傳入離職字段,查詢出對應結果,結果是多條數據

    但是進行業務功能開發的哥們,拿到的需求文檔要求差別就很大

    接口:傳入用戶名與密碼字段,對用戶名字段做長度校驗,4-15位,對密碼字段做長度校驗,8到24位,對密碼字段做特殊字符校驗,不允許存在空格,查詢結果為對象。如果為null,返回BusinessException,封裝消息碼INFO_LOGON_USERNAME_PASSWORD_ERROR

    你比較一下,能是一回事嗎?差別太大了,所以說業務層方法定義與數據層方法定義差異化很大,只不過有些入門級的開發者手懶或者沒有使用過公司相關的ISO標準化文檔而已。

    代碼實現:

    業務層接口:

    public interface BookService {Boolean save(Book book);Boolean update(Book book);Boolean delete(Integer id);Book getById(Integer id);List<Book> getAll();IPage<Book> getPage(int currentPage,int pageSize); }

    業務層實現類如下,轉調數據層即可:

    @Service public class BookServiceImpl implements BookService {@Autowiredprivate BookDao bookDao;@Overridepublic Boolean save(Book book) {return bookDao.insert(book) > 0;}@Overridepublic Boolean update(Book book) {return bookDao.updateById(book) > 0;}@Overridepublic Boolean delete(Integer id) {return bookDao.deleteById(id) > 0;}@Overridepublic Book getById(Integer id) {return bookDao.selectById(id);}@Overridepublic List<Book> getAll() {return bookDao.selectList(null);}@Overridepublic IPage<Book> getPage(int currentPage, int pageSize) {IPage page = new Page(currentPage,pageSize);bookDao.selectPage(page,null);return page;} }

    別忘了對業務層接口進行測試,測試類如下:

    @SpringBootTest public class BookServiceTest {@Autowiredprivate IBookService bookService;@Testvoid testGetById(){System.out.println(bookService.getById(4));}@Testvoid testSave(){Book book = new Book();book.setType("測試數據123");book.setName("測試數據123");book.setDescription("測試數據123");bookService.save(book);}@Testvoid testUpdate(){Book book = new Book();book.setId(17);book.setType("-----------------");book.setName("測試數據123");book.setDescription("測試數據123");bookService.updateById(book);}@Testvoid testDelete(){bookService.removeById(18);}@Testvoid testGetAll(){bookService.list();}@Testvoid testGetPage(){IPage<Book> page = new Page<Book>(2,5);bookService.page(page);System.out.println(page.getCurrent());System.out.println(page.getSize());System.out.println(page.getTotal());System.out.println(page.getPages());System.out.println(page.getRecords());}}

    總結

  • Service接口名稱定義成業務名稱,并與Dao接口名稱進行區分
  • 制作測試類測試Service功能是否有效
  • 業務層快速開發(慎用)

    其實MyBatisPlus技術不僅提供了數據層快速開發方案,業務層MyBatisPlus也給了一個通用接口,個人觀點不推薦使用,湊合能用吧,其實就是一個封裝+繼承的思想,代碼給出,實際開發慎用。

    業務層接口快速開發

    public interface IBookService extends IService<Book> {//添加非通用操作API接口 }

    業務層接口實現類快速開發,關注繼承的類需要傳入兩個泛型,一個是數據層接口,另一個是實體類。

    @Service public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {@Autowiredprivate BookDao bookDao;//添加非通用操作API }

    如果感覺MyBatisPlus提供的功能不足以支撐你的使用需要(其實是一定不能支撐的,因為需求不可能是通用的),在原始接口基礎上接著定義新的API接口就行了,此處不再說太多了,就是自定義自己的操作了,但是不要和已有的API接口名沖突即可。

    總結

  • 使用通用接口(ISerivce)快速開發Service
  • 使用通用實現類(ServiceImpl<M,T>)快速開發ServiceImpl
  • 可以在通用接口基礎上做功能重載或功能追加
  • 注意重載時不要覆蓋原始操作,避免原始提供的功能丟失
  • 6.表現層開發

    終于做到表現層了,做了這么多都是基礎工作。其實你現在回頭看看,哪里還有什么SpringBoot的影子?前面1,2步就搞完了。繼續完成表現層制作吧,咱們表現層的開發使用基于Restful的表現層接口開發,功能測試通過Postman工具進行。

    表現層接口如下:

    @RestController @RequestMapping("/books") public class BookController2 {@Autowiredprivate IBookService bookService;@GetMappingpublic List<Book> getAll(){return bookService.list();}@PostMappingpublic Boolean save(@RequestBody Book book){return bookService.save(book);}@PutMappingpublic Boolean update(@RequestBody Book book){return bookService.modify(book);}@DeleteMapping("{id}")public Boolean delete(@PathVariable Integer id){return bookService.delete(id);}@GetMapping("{id}")public Book getById(@PathVariable Integer id){return bookService.getById(id);}//當前頁碼和每頁數量由前端傳@GetMapping("{currentPage}/{pageSize}")public IPage<Book> getPage(@PathVariable int currentPage,@PathVariable int pageSize){return bookService.getPage(currentPage,pageSize);} }

    在使用Postman測試時關注提交類型,對應上即可,不然就會報405的錯誤碼了。

    普通GET請求

    PUT請求傳遞json數據,后臺實用@RequestBody接收數據

    GET請求傳遞路徑變量,后臺實用@PathVariable接收數據

    總結

  • 基于Restful制作表現層接口

    • 新增:POST
    • 刪除:DELETE
    • 修改:PUT
    • 查詢:GET
  • 接收參數

    • 實體數據:@RequestBody
    • 路徑變量:@PathVariable
  • 7.表現層消息一致性處理

    目前我們通過Postman測試后業務層接口功能是通的,但是這樣的結果給到前端開發者會出現一個小問題。不同的操作結果所展示的數據格式差異化嚴重。

    增刪改操作結果

    true

    查詢單個數據操作結果

    {"id": 1,"type": "計算機理論","name": "Spring實戰 第5版","description": "Spring入門經典教程" }

    查詢全部數據操作結果

    [{"id": 1,"type": "計算機理論","name": "Spring實戰 第5版","description": "Spring入門經典教程"},{"id": 2,"type": "計算機理論","name": "Spring 5核心原理與30個類手寫實戰","description": "十年沉淀之作"} ]

    每種不同操作返回的數據格式都不一樣,而且還不知道以后還會有什么格式,這樣的結果讓前端人員看了是很容易讓人崩潰的,必須將所有操作的操作結果數據格式統一起來,需要設計表現層返回結果的模型類,用于后端與前端進行數據格式統一,也稱為前后端數據協議

    @Data public class R {//完整形態應該把flag改integer型code,加上String的錯誤信息msg,再創建一個code類定義所有成功失敗的碼,private Boolean flag;private Object data; }

    其中flag用于標識操作是否成功,data用于封裝操作數據,現在的數據格式就變了

    {"flag": true,"data":{"id": 1,"type": "計算機理論","name": "Spring實戰 第5版","description": "Spring入門經典教程"} }

    表現層開發格式也需要轉換一下

    結果這么一折騰,全格式統一,現在后端發送給前端的數據格式就統一了,免去了不少前端解析數據的煩惱。

    總結

  • 設計統一的返回值結果類型便于前端開發讀取數據

  • 返回值結果類型可以根據需求自行設定,沒有固定格式

  • 返回值結果模型類用于后端與前端進行數據格式統一,也稱為前后端數據協議

  • 8.前后端聯通性測試

    后端的表現層接口開發完畢,就可以進行前端的開發了。

    將前端人員開發的頁面保存到lresources目錄下的static目錄中,建議執行maven的clean生命周期,避免緩存的問題出現。

    在進行具體的功能開發之前,先做聯通性的測試,通過頁面發送異步提交(axios),這一步調試通過后再進行進一步的功能開發。

    //列表 getAll() {axios.get("/books").then((res)=>{console.log(res.data);}); },

    只要后臺代碼能夠正常工作,前端能夠在日志中接收到數據,就證明前后端是通的,也就可以進行下一步的功能開發了。

    總結

  • 單體項目中頁面放置在resources/static目錄下
  • created鉤子函數用于初始化頁面時發起調用
  • 頁面使用axios發送異步請求獲取數據后確認前后端是否聯通
  • 9.頁面基礎功能開發

    F-1.列表功能(非分頁版)

    列表功能主要操作就是加載完數據,將數據展示到頁面上,此處要利用VUE的數據模型綁定,發送請求得到數據,然后頁面上讀取指定數據即可。

    頁面數據模型定義

    data:{dataList: [], //當前頁要展示的列表數據... },

    異步請求獲取數據

    //列表 getAll() {axios.get("/books").then((res)=>{this.dataList = res.data.data;}); },

    這樣在頁面加載時就可以獲取到數據,并且由VUE將數據展示到頁面上了。

    總結:

  • 將查詢數據返回到頁面,利用前端數據綁定進行數據展示
  • F-2.添加功能

    添加功能用于收集數據的表單是通過一個彈窗展示的,因此在添加操作前首先要進行彈窗的展示,添加后隱藏彈窗即可。因為這個彈窗一直存在,因此當頁面加載時首先設置這個彈窗為不可顯示狀態,需要展示,切換狀態即可。

    默認狀態

    data:{dialogFormVisible: false, //添加表單是否可見... },

    切換為顯示狀態

    //彈出添加窗口 handleCreate() {this.dialogFormVisible = true; },

    由于每次添加數據都是使用同一個彈窗錄入數據,所以每次操作的痕跡將在下一次操作時展示出來,需要在每次操作之前清理掉上次操作的痕跡。

    定義清理數據操作

    //重置表單 resetForm() {this.formData = {}; },

    切換彈窗狀態時清理數據

    //彈出添加窗口 handleCreate() {this.dialogFormVisible = true;this.resetForm(); },

    至此準備工作完成,下面就要調用后臺完成添加操作了。

    添加操作

    //添加 handleAdd () {//發送異步請求axios.post("/books",this.formData).then((res)=>{//如果操作成功,關閉彈層,顯示數據if(res.data.flag){this.dialogFormVisible = false;this.$message.success("添加成功");}else {this.$message.error("添加失敗");}}).finally(()=>{this.getAll();}); },
  • 將要保存的數據傳遞到后臺,通過post請求的第二個參數傳遞json數據到后臺

  • 根據返回的操作結果決定下一步操作

    • 如何是true就關閉添加窗口,顯示添加成功的消息
    • 如果是false保留添加窗口,顯示添加失敗的消息
  • 無論添加是否成功,頁面均進行刷新,動態加載數據(對getAll操作發起調用)

  • 取消添加操作

    //取消 cancel(){this.dialogFormVisible = false;this.$message.info("操作取消"); },

    總結

  • 請求方式使用POST調用后臺對應操作
  • 添加操作結束后動態刷新頁面加載數據
  • 根據操作結果不同,顯示對應的提示信息
  • 彈出添加Div時清除表單數據
  • F-3.刪除功能

    模仿添加操作制作刪除功能,差別之處在于刪除操作僅傳遞一個待刪除的數據id到后臺即可。

    刪除操作

    // 刪除 handleDelete(row) {axios.delete("/books/"+row.id).then((res)=>{if(res.data.flag){this.$message.success("刪除成功");}else{this.$message.error("刪除失敗");}}).finally(()=>{this.getAll();}); },

    刪除操作提示信息

    // 刪除 handleDelete(row) {//1.彈出提示框this.$confirm("此操作永久刪除當前數據,是否繼續?","提示",{type:'info'}).then(()=>{//2.做刪除業務axios.delete("/books/"+row.id).then((res)=>{if(res.data.flag){this.$message.success("刪除成功");}else{this.$message.error("刪除失敗");}}).finally(()=>{this.getAll();});}).catch(()=>{//3.取消刪除this.$message.info("取消刪除操作");}); },

    總結

  • 請求方式使用Delete調用后臺對應操作
  • 刪除操作需要傳遞當前行數據對應的id值到后臺
  • 刪除操作結束后動態刷新頁面加載數據
  • 根據操作結果不同,顯示對應的提示信息
  • 刪除操作前彈出提示框避免誤操作
  • F-4.修改功能

    修改功能可以說是列表功能、刪除功能與添加功能的合體。幾個相似點如下:

  • 頁面也需要有一個彈窗用來加載修改的數據,這一點與添加相同,都是要彈窗

  • 彈出窗口中要加載待修改的數據,而數據需要通過查詢得到,這一點與查詢全部相同,都是要查數據

  • 查詢操作需要將要修改的數據id發送到后臺,這一點與刪除相同,都是傳遞id到后臺

  • 查詢得到數據后需要展示到彈窗中,這一點與查詢全部相同,都是要通過數據模型綁定展示數據

  • 修改數據時需要將被修改的數據傳遞到后臺,這一點與添加相同,都是要傳遞數據

    所以整體上來看,修改功能就是前面幾個功能的大合體

    查詢并展示數據

  • //彈出編輯窗口 handleUpdate(row) {axios.get("/books/"+row.id).then((res)=>{if(res.data.flag){//展示彈層,加載數據this.formData = res.data.data;this.dialogFormVisible4Edit = true;}else{this.$message.error("數據同步失敗,自動刷新");}}); },

    修改操作

    //修改 handleEdit() {axios.put("/books",this.formData).then((res)=>{//如果操作成功,關閉彈層并刷新頁面if(res.data.flag){this.dialogFormVisible4Edit = false;this.$message.success("修改成功");}else {this.$message.error("修改失敗,請重試");}}).finally(()=>{this.getAll();}); },

    總結

  • 加載要修改數據通過傳遞當前行數據對應的id值到后臺查詢數據(同刪除與查詢全部)
  • 利用前端雙向數據綁定將查詢到的數據進行回顯(同查詢全部)
  • 請求方式使用PUT調用后臺對應操作(同新增傳遞數據)
  • 修改操作結束后動態刷新頁面加載數據(同新增)
  • 根據操作結果不同,顯示對應的提示信息(同新增)
  • 10.業務消息一致性處理

    目前的功能制作基本上達成了正常使用的情況,什么叫正常使用呢?也就是這個程序不出BUG,如果我們搞一個BUG出來,你會發現程序馬上崩潰掉。比如后臺手工拋出一個異常,看看前端接收到的數據什么樣子。

    {"timestamp": "2021-09-15T03:27:31.038+00:00","status": 500,"error": "Internal Server Error","path": "/books" }

    面對這種情況,前端的同學又不會了,這又是什么格式?怎么和之前的格式不一樣?

    {"flag": true,"data":{"id": 1,"type": "計算機理論","name": "Spring實戰 第5版","description": "Spring入門經典教程"} }

    看來不僅要對正確的操作數據格式做處理,還要對錯誤的操作數據格式做同樣的格式處理。

    首先在當前的數據結果中添加消息字段,用來兼容后臺出現的操作消息。

    @Data public class R{//完整形態是flag換Integer型的狀態碼codeprivate Boolean flag;private Object data;private String msg; //用于封裝消息 }

    后臺代碼也要根據情況做處理,當前是模擬的錯誤。

    @PostMapping public R save(@RequestBody Book book) throws IOException {Boolean flag = bookService.insert(book);return new R(flag , flag ? "添加成功^_^" : "添加失敗-_-!"); }

    然后在表現層做統一的異常處理,使用SpringMVC提供的異常處理器做統一的異常處理。

    @RestControllerAdvice public class ProjectExceptionAdvice {@ExceptionHandler(Exception.class)public R doOtherException(Exception ex){//記錄日志//發送消息給運維//發送郵件給開發人員,ex對象發送給開發人員ex.printStackTrace();return new R(false,null,"系統錯誤,請稍后再試!");} }

    頁面上得到數據后,先判定是否有后臺傳遞過來的消息,標志就是當前操作是否成功,如果返回操作結果false,就讀取后臺傳遞的消息。

    //添加 handleAdd () {//發送ajax請求axios.post("/books",this.formData).then((res)=>{//如果操作成功,關閉彈層,顯示數據if(res.data.flag){this.dialogFormVisible = false;this.$message.success("添加成功");}else {this.$message.error(res.data.msg); //消息來自于后臺傳遞過來,而非固定內容}}).finally(()=>{this.getAll();}); },

    總結

  • 使用注解@RestControllerAdvice定義SpringMVC異常處理器用來處理異常的
  • 異常處理器必須被掃描加載,否則無法生效
  • 表現層返回結果的模型類中添加消息屬性用來傳遞消息到頁面
  • 11.頁面功能開發

    F-5.分頁功能

    分頁功能的制作用于替換前面的查詢全部,其中要使用到elementUI提供的分頁組件。

    <!--分頁組件--> <div class="pagination-container"><el-paginationclass="pagiantion"@current-change="handleCurrentChange":current-page="pagination.currentPage":page-size="pagination.pageSize"layout="total, prev, pager, next, jumper":total="pagination.total"></el-pagination> </div>

    為了配合分頁組件,封裝分頁對應的數據模型。

    data:{pagination: { //分頁相關模型數據currentPage: 1, //當前頁碼pageSize:10, //每頁顯示的記錄數total:0, //總記錄數} },

    修改查詢全部功能為分頁查詢,通過路徑變量傳遞頁碼信息參數。

    getAll() {axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res) => {}); },

    后臺提供對應的分頁功能。

    @GetMapping("/{currentPage}/{pageSize}") public R getAll(@PathVariable Integer currentPage,@PathVariable Integer pageSize){IPage<Book> pageBook = bookService.getPage(currentPage, pageSize);return new R(null != pageBook ,pageBook); }

    頁面根據分頁操作結果讀取對應數據,并進行數據模型綁定。

    getAll() {axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res) => {this.pagination.total = res.data.data.total;this.pagination.currentPage = res.data.data.current;this.pagination.pagesize = res.data.data.size;this.dataList = res.data.data.records;}); },

    對切換頁碼操作設置調用當前分頁操作。

    //切換頁碼 handleCurrentChange(currentPage) {this.pagination.currentPage = currentPage;this.getAll(); },

    總結

  • 使用el分頁組件
  • 定義分頁組件綁定的數據模型
  • 異步調用獲取分頁數據
  • 分頁數據頁面回顯
  • F-6.刪除功能維護

    由于使用了分頁功能,當最后一頁只有一條數據時,刪除操作就會出現BUG,最后一頁無數據但是獨立展示,對分頁查詢功能進行后臺功能維護,如果當前頁碼值大于最大頁碼值,重新執行查詢。其實這個問題解決方案很多,這里給出比較簡單的一種處理方案。

    @GetMapping("{currentPage}/{pageSize}") public R getPage(@PathVariable int currentPage,@PathVariable int pageSize){IPage<Book> page = bookService.getPage(currentPage, pageSize);//如果當前頁碼值大于了總頁碼值,那么重新執行查詢操作,使用最大頁碼值作為當前頁碼值if( currentPage > page.getPages()){page = bookService.getPage((int)page.getPages(), pageSize);}return new R(true, page); }

    F-7.條件查詢功能

    最后一個功能來做條件查詢,其實條件查詢可以理解為分頁查詢的時候除了攜帶分頁數據再多帶幾個數據的查詢。這些多帶的數據就是查詢條件。比較一下不帶條件的分頁查詢與帶條件的分頁查詢差別之處,這個功能就好做了

    • 頁面封裝的數據:帶不帶條件影響的僅僅是一次性傳遞到后臺的數據總量,由傳遞2個分頁相關數據轉換成2個分頁數據加若干個條件

    • 后臺查詢功能:查詢時由不帶條件,轉換成帶條件,反正不帶條件的時候查詢條件對象使用的是null,現在換成具體條件,差別不大

    • 查詢結果:不管帶不帶條件,出來的數據只是有數量上的差別,其他都差別,這個可以忽略

      經過上述分析,看來需要在頁面發送請求的格式方面做一定的修改,后臺的調用數據層操作時發送修改,其他沒有區別。

      頁面發送請求時,兩個分頁數據仍然使用路徑變量,其他條件采用動態拼裝url參數的形式傳遞。

      頁面封裝查詢條件字段

      pagination: { //分頁相關模型數據currentPage: 1, //當前頁碼pageSize:10, //每頁顯示的記錄數total:0, //總記錄數name: "",type: "",description: "" },

      頁面添加查詢條件字段對應的數據模型綁定名稱

      <div class="filter-container"><el-input placeholder="圖書類別" v-model="pagination.type" class="filter-item"/><el-input placeholder="圖書名稱" v-model="pagination.name" class="filter-item"/><el-input placeholder="圖書描述" v-model="pagination.description" class="filter-item"/><el-button @click="getAll()" class="dalfBut">查詢</el-button><el-button type="primary" class="butT" @click="handleCreate()">新建</el-button> </div>

      將查詢條件組織成url參數,添加到請求url地址中,這里可以借助其他類庫快速開發,當前使用手工形式拼接,降低學習要求

      getAll() {//1.獲取查詢條件,拼接查詢條件param = "?name="+this.pagination.name;param += "&type="+this.pagination.type;param += "&description="+this.pagination.description;console.log("-----------------"+ param);axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param).then((res) => {this.dataList = res.data.data.records;}); },

      后臺代碼中定義實體類封查詢條件

      @GetMapping("{currentPage}/{pageSize}") public R getAll(@PathVariable int currentPage,@PathVariable int pageSize,Book book) {System.out.println("參數=====>"+book);IPage<Book> pageBook = bookService.getPage(currentPage,pageSize);return new R(null != pageBook ,pageBook); }

      對應業務層接口與實現類進行修正

      public interface IBookService extends IService<Book> {IPage<Book> getPage(Integer currentPage,Integer pageSize,Book queryBook); } @Service public class BookServiceImpl2 extends ServiceImpl<BookDao,Book> implements IBookService {public IPage<Book> getPage(Integer currentPage,Integer pageSize,Book queryBook){IPage page = new Page(currentPage,pageSize);LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();lqw.like(Strings.isNotEmpty(queryBook.getName()),Book::getName,queryBook.getName());lqw.like(Strings.isNotEmpty(queryBook.getType()),Book::getType,queryBook.getType());lqw.like(Strings.isNotEmpty(queryBook.getDescription()),Book::getDescription,queryBook.getDescription());return bookDao.selectPage(page,lqw);} }

      頁面回顯數據

      getAll() {//1.獲取查詢條件,拼接查詢條件param = "?name="+this.pagination.name;param += "&type="+this.pagination.type;param += "&description="+this.pagination.description;console.log("-----------------"+ param);axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param).then((res) => {this.pagination.total = res.data.data.total;this.pagination.currentPage = res.data.data.current;this.pagination.pagesize = res.data.data.size;this.dataList = res.data.data.records;}); },

    總結

  • 定義查詢條件數據模型(當前封裝到分頁數據模型中)
  • 異步調用分頁功能并通過請求參數傳遞數據到后臺
  • 總結

    以上是生活随笔為你收集整理的【Java笔记+踩坑】SpringBoot——基础的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    国产麻豆精品一区二区三区v视界 | 乱人伦人妻中文字幕无码久久网 | 亚洲成av人综合在线观看 | 国产av一区二区三区最新精品 | √天堂资源地址中文在线 | 在线а√天堂中文官网 | 美女毛片一区二区三区四区 | 亚洲熟妇色xxxxx欧美老妇 | 无遮挡国产高潮视频免费观看 | 国产乱人偷精品人妻a片 | 人妻无码久久精品人妻 | 亚洲成av人综合在线观看 | 最近的中文字幕在线看视频 | 久久久久久亚洲精品a片成人 | 亚洲自偷自偷在线制服 | 熟女俱乐部五十路六十路av | 色综合久久久无码中文字幕 | 婷婷丁香五月天综合东京热 | 九九在线中文字幕无码 | 久久亚洲a片com人成 | 精品国精品国产自在久国产87 | 黑人巨大精品欧美黑寡妇 | 亚洲 激情 小说 另类 欧美 | 在线观看国产一区二区三区 | 亚洲国产成人av在线观看 | 奇米影视7777久久精品 | 久9re热视频这里只有精品 | 亚洲成在人网站无码天堂 | 色一情一乱一伦一视频免费看 | 九九久久精品国产免费看小说 | 偷窥日本少妇撒尿chinese | 欧美性生交xxxxx久久久 | 久久久精品人妻久久影视 | 成人女人看片免费视频放人 | 图片区 小说区 区 亚洲五月 | 国内精品久久久久久中文字幕 | 人人澡人人妻人人爽人人蜜桃 | 国产欧美熟妇另类久久久 | 人妻插b视频一区二区三区 | 久久久久亚洲精品中文字幕 | 国产后入清纯学生妹 | 国产性生交xxxxx无码 | 亚洲狠狠色丁香婷婷综合 | 爽爽影院免费观看 | 亚洲色偷偷偷综合网 | 99久久婷婷国产综合精品青草免费 | 无码吃奶揉捏奶头高潮视频 | 久青草影院在线观看国产 | 色诱久久久久综合网ywww | 日日摸夜夜摸狠狠摸婷婷 | 捆绑白丝粉色jk震动捧喷白浆 | 在线观看国产一区二区三区 | 亚洲 a v无 码免 费 成 人 a v | 荫蒂添的好舒服视频囗交 | 国产国语老龄妇女a片 | 国产激情综合五月久久 | 亚洲中文字幕va福利 | 精品无码一区二区三区的天堂 | 精品久久久中文字幕人妻 | 亚洲国产精品一区二区第一页 | 国产精品手机免费 | 天天摸天天透天天添 | 欧美三级不卡在线观看 | 内射老妇bbwx0c0ck | 亚洲日韩av一区二区三区中文 | 欧洲极品少妇 | 国产亚洲欧美日韩亚洲中文色 | 国产超碰人人爽人人做人人添 | 夜夜躁日日躁狠狠久久av | 一个人免费观看的www视频 | 亚洲色成人中文字幕网站 | 日韩精品无码一区二区中文字幕 | 毛片内射-百度 | 国产成人无码av一区二区 | 香蕉久久久久久av成人 | 在线а√天堂中文官网 | 日本va欧美va欧美va精品 | 99久久婷婷国产综合精品青草免费 | 亚洲男人av香蕉爽爽爽爽 | 蜜桃视频插满18在线观看 | 国产69精品久久久久app下载 | 国产97色在线 | 免 | 性欧美熟妇videofreesex | 欧洲熟妇色 欧美 | 免费男性肉肉影院 | 色噜噜亚洲男人的天堂 | 亚洲精品欧美二区三区中文字幕 | 欧美丰满老熟妇xxxxx性 | 精品无码一区二区三区的天堂 | 无码av免费一区二区三区试看 | 国产明星裸体无码xxxx视频 | 午夜精品久久久内射近拍高清 | 成人欧美一区二区三区黑人 | 一本久道久久综合婷婷五月 | 人人妻人人澡人人爽精品欧美 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 免费无码一区二区三区蜜桃大 | 亚洲色偷偷偷综合网 | 久久综合网欧美色妞网 | 在线播放无码字幕亚洲 | 亚洲国产精华液网站w | 久久人人97超碰a片精品 | 青青久在线视频免费观看 | 娇妻被黑人粗大高潮白浆 | 内射爽无广熟女亚洲 | 国产乡下妇女做爰 | 夫妻免费无码v看片 | 国产综合色产在线精品 | 久久99热只有频精品8 | 蜜桃av抽搐高潮一区二区 | 亚洲国产成人av在线观看 | 精品无码一区二区三区爱欲 | 国产又爽又黄又刺激的视频 | 色婷婷av一区二区三区之红樱桃 | 久久久久成人精品免费播放动漫 | 无码任你躁久久久久久久 | 亚洲理论电影在线观看 | 日日噜噜噜噜夜夜爽亚洲精品 | 亚洲爆乳大丰满无码专区 | 疯狂三人交性欧美 | 性啪啪chinese东北女人 | 伊在人天堂亚洲香蕉精品区 | 无码一区二区三区在线观看 | 亚洲日韩乱码中文无码蜜桃臀网站 | 久久亚洲中文字幕精品一区 | 无套内谢老熟女 | 特黄特色大片免费播放器图片 | 一个人免费观看的www视频 | 鲁鲁鲁爽爽爽在线视频观看 | 国产午夜亚洲精品不卡 | 国产超级va在线观看视频 | 日韩精品乱码av一区二区 | 午夜精品一区二区三区的区别 | 亚洲精品午夜无码电影网 | 国产精品毛片一区二区 | 日日躁夜夜躁狠狠躁 | 亚洲精品国偷拍自产在线观看蜜桃 | av香港经典三级级 在线 | 精品久久8x国产免费观看 | 国产亚洲精品久久久闺蜜 | 亚洲国产av精品一区二区蜜芽 | 一二三四在线观看免费视频 | 国产精品无码永久免费888 | 亚洲色无码一区二区三区 | 国产免费久久精品国产传媒 | 中文字幕人妻丝袜二区 | 国产精品人人爽人人做我的可爱 | 日韩精品一区二区av在线 | 伊人久久大香线蕉av一区二区 | 狠狠躁日日躁夜夜躁2020 | 久久精品女人天堂av免费观看 | 女人和拘做爰正片视频 | 日日躁夜夜躁狠狠躁 | 亚洲熟妇色xxxxx欧美老妇 | 久久久精品人妻久久影视 | 久久久国产一区二区三区 | 久精品国产欧美亚洲色aⅴ大片 | 国产香蕉尹人综合在线观看 | 人妻插b视频一区二区三区 | 大屁股大乳丰满人妻 | 麻花豆传媒剧国产免费mv在线 | 丰满人妻翻云覆雨呻吟视频 | 色综合久久久无码网中文 | 欧美日韩精品 | 日韩欧美中文字幕在线三区 | 精品人人妻人人澡人人爽人人 | 亚洲欧美色中文字幕在线 | 中国大陆精品视频xxxx | 1000部啪啪未满十八勿入下载 | 久久视频在线观看精品 | 久久久久久av无码免费看大片 | 日韩人妻无码中文字幕视频 | 99久久久无码国产精品免费 | 无码任你躁久久久久久久 | 亚洲色欲色欲天天天www | 久久久精品欧美一区二区免费 | 国产精品美女久久久 | 国产肉丝袜在线观看 | 成人片黄网站色大片免费观看 | 亚洲gv猛男gv无码男同 | 亚洲色大成网站www国产 | 成人性做爰aaa片免费看 | 夜夜影院未满十八勿进 | 一本大道久久东京热无码av | 男女下面进入的视频免费午夜 | 欧美亚洲国产一区二区三区 | 国产精品无码一区二区三区不卡 | 亚洲经典千人经典日产 | 欧美老妇交乱视频在线观看 | 欧美日韩色另类综合 | 天下第一社区视频www日本 | 18无码粉嫩小泬无套在线观看 | 无码精品人妻一区二区三区av | av香港经典三级级 在线 | 欧美日韩人成综合在线播放 | 青草视频在线播放 | 无码成人精品区在线观看 | 国产精品无码永久免费888 | 日日噜噜噜噜夜夜爽亚洲精品 | 中文精品久久久久人妻不卡 | 鲁大师影院在线观看 | 伊在人天堂亚洲香蕉精品区 | 日日鲁鲁鲁夜夜爽爽狠狠 | 日本免费一区二区三区最新 | 中文字幕乱妇无码av在线 | 中文字幕无码热在线视频 | 色综合久久久久综合一本到桃花网 | 久久综合久久自在自线精品自 | 日本精品人妻无码免费大全 | 国内综合精品午夜久久资源 | 亚洲中文无码av永久不收费 | 麻豆国产97在线 | 欧洲 | 精品成在人线av无码免费看 | 成人精品视频一区二区 | 亚洲欧洲无卡二区视頻 | 波多野42部无码喷潮在线 | 5858s亚洲色大成网站www | 中文字幕 亚洲精品 第1页 | 久久久久人妻一区精品色欧美 | 成人亚洲精品久久久久 | 国产精品va在线播放 | 国产精品久久久久9999小说 | 人人妻在人人 | 98国产精品综合一区二区三区 | 国产精品无码一区二区三区不卡 | 18禁黄网站男男禁片免费观看 | 欧美野外疯狂做受xxxx高潮 | 国产午夜视频在线观看 | 亚洲s码欧洲m码国产av | 无遮无挡爽爽免费视频 | 亚洲国产精品一区二区第一页 | 亚洲va欧美va天堂v国产综合 | 老头边吃奶边弄进去呻吟 | 久久国产精品萌白酱免费 | 蜜桃臀无码内射一区二区三区 | 久久综合网欧美色妞网 | 婷婷色婷婷开心五月四房播播 | 国产精品igao视频网 | 免费播放一区二区三区 | 亚洲国产欧美日韩精品一区二区三区 | 亚洲春色在线视频 | 人妻体内射精一区二区三四 | 中国女人内谢69xxxxxa片 | 国产午夜精品一区二区三区嫩草 | 色妞www精品免费视频 | 国产av一区二区三区最新精品 | 成年美女黄网站色大免费全看 | 四虎影视成人永久免费观看视频 | 午夜福利不卡在线视频 | 精品午夜福利在线观看 | 奇米影视7777久久精品 | 日日摸天天摸爽爽狠狠97 | 欧美人与禽zoz0性伦交 | 人妻体内射精一区二区三四 | 国产在线aaa片一区二区99 | 99久久精品国产一区二区蜜芽 | 亚洲国产日韩a在线播放 | 全黄性性激高免费视频 | 国产成人久久精品流白浆 | 成熟女人特级毛片www免费 | 最新国产麻豆aⅴ精品无码 | 亚洲狠狠色丁香婷婷综合 | 久在线观看福利视频 | 午夜精品久久久内射近拍高清 | 中文字幕无码人妻少妇免费 | 久久精品国产一区二区三区 | 国产情侣作爱视频免费观看 | 熟妇人妻无乱码中文字幕 | 九一九色国产 | 狂野欧美激情性xxxx | 国产无遮挡吃胸膜奶免费看 | 99久久久无码国产精品免费 | 久久精品国产精品国产精品污 | 99riav国产精品视频 | 鲁一鲁av2019在线 | 欧美日韩视频无码一区二区三 | 亚洲小说图区综合在线 | 东京热无码av男人的天堂 | 无码帝国www无码专区色综合 | 精品无码一区二区三区的天堂 | 国产精品美女久久久网av | 亚洲国产成人a精品不卡在线 | 99视频精品全部免费免费观看 | 午夜熟女插插xx免费视频 | 风流少妇按摩来高潮 | 欧美黑人性暴力猛交喷水 | 中文精品久久久久人妻不卡 | 老熟女重囗味hdxx69 | 午夜免费福利小电影 | 国产精品久久久久影院嫩草 | 国产成人无码av片在线观看不卡 | 人人妻人人藻人人爽欧美一区 | 中文字幕av伊人av无码av | 欧美高清在线精品一区 | 高中生自慰www网站 | 成人亚洲精品久久久久软件 | 久久99精品久久久久久动态图 | 人人爽人人澡人人人妻 | 亚洲综合另类小说色区 | 国产人妻精品午夜福利免费 | 97久久超碰中文字幕 | 性啪啪chinese东北女人 | 精品无人区无码乱码毛片国产 | 欧美丰满熟妇xxxx性ppx人交 | 国产精品亚洲а∨无码播放麻豆 | 国产色xx群视频射精 | 黑森林福利视频导航 | 一本大道久久东京热无码av | 久久久久成人精品免费播放动漫 | 欧美人与物videos另类 | 国产精品理论片在线观看 | 久久aⅴ免费观看 | 亚洲中文无码av永久不收费 | 亚洲色www成人永久网址 | 老司机亚洲精品影院无码 | 丰满人妻翻云覆雨呻吟视频 | 在线观看国产一区二区三区 | 国产深夜福利视频在线 | 国产舌乚八伦偷品w中 | 亚洲 日韩 欧美 成人 在线观看 | 欧美丰满熟妇xxxx性ppx人交 | 国产精品va在线播放 | 香港三级日本三级妇三级 | 日本爽爽爽爽爽爽在线观看免 | 香蕉久久久久久av成人 | 国产成人精品必看 | 中国大陆精品视频xxxx | www国产亚洲精品久久网站 | 亚洲欧美日韩成人高清在线一区 | 伊人久久婷婷五月综合97色 | 亚洲一区二区三区无码久久 | 久在线观看福利视频 | 青草青草久热国产精品 | 久久精品国产日本波多野结衣 | 国产av无码专区亚洲awww | 扒开双腿吃奶呻吟做受视频 | 国产亚洲人成a在线v网站 | 亚洲日本va午夜在线电影 | 国产亚洲人成a在线v网站 | 牲欲强的熟妇农村老妇女视频 | 精品久久久无码人妻字幂 | 亚洲精品一区二区三区四区五区 | 又大又黄又粗又爽的免费视频 | 乱码午夜-极国产极内射 | 日韩欧美中文字幕公布 | 51国偷自产一区二区三区 | 日日天干夜夜狠狠爱 | 任你躁国产自任一区二区三区 | 三级4级全黄60分钟 | 亚洲爆乳无码专区 | 日本丰满护士爆乳xxxx | 亚洲综合久久一区二区 | 久久久久久九九精品久 | 欧洲精品码一区二区三区免费看 | 亚洲精品久久久久avwww潮水 | 无码av最新清无码专区吞精 | 国产va免费精品观看 | 亚洲国产精品无码一区二区三区 | 熟妇人妻无码xxx视频 | 久久精品女人天堂av免费观看 | 国产人妻大战黑人第1集 | 中文字幕人妻无码一区二区三区 | 色情久久久av熟女人妻网站 | 娇妻被黑人粗大高潮白浆 | 国产无遮挡又黄又爽免费视频 | 久久精品一区二区三区四区 | 无码午夜成人1000部免费视频 | 日本熟妇人妻xxxxx人hd | 中文字幕亚洲情99在线 | 国产国产精品人在线视 | 影音先锋中文字幕无码 | 国产黄在线观看免费观看不卡 | 久久久婷婷五月亚洲97号色 | 东京热男人av天堂 | 欧美第一黄网免费网站 | 精品无码一区二区三区的天堂 | 中文字幕人妻丝袜二区 | 亚洲性无码av中文字幕 | 人妻夜夜爽天天爽三区 | 欧美精品一区二区精品久久 | 久久精品女人天堂av免费观看 | 自拍偷自拍亚洲精品10p | 在线观看国产午夜福利片 | 亚洲熟妇色xxxxx欧美老妇y | 久久亚洲精品成人无码 | 久9re热视频这里只有精品 | 精品无码国产自产拍在线观看蜜 | 亚洲精品午夜国产va久久成人 | 人人妻人人藻人人爽欧美一区 | 黑人粗大猛烈进出高潮视频 | 精品国偷自产在线 | 中文字幕日韩精品一区二区三区 | 乱人伦人妻中文字幕无码久久网 | 内射白嫩少妇超碰 | 无码国产乱人伦偷精品视频 | 久久人人爽人人爽人人片ⅴ | 亚洲а∨天堂久久精品2021 | 精品无码国产一区二区三区av | √天堂中文官网8在线 | 正在播放东北夫妻内射 | 女高中生第一次破苞av | 桃花色综合影院 | 欧洲美熟女乱又伦 | 国产精品无码久久av | 性欧美熟妇videofreesex | 人人澡人人妻人人爽人人蜜桃 | 伊人久久婷婷五月综合97色 | 亚洲日韩av一区二区三区四区 | 欧美一区二区三区 | 无码吃奶揉捏奶头高潮视频 | 久久久国产一区二区三区 | 欧美一区二区三区视频在线观看 | 扒开双腿疯狂进出爽爽爽视频 | 国产综合色产在线精品 | 国产精品无码一区二区桃花视频 | 少妇厨房愉情理9仑片视频 | 曰本女人与公拘交酡免费视频 | 欧美高清在线精品一区 | 欧美喷潮久久久xxxxx | 国产又爽又猛又粗的视频a片 | 欧美成人家庭影院 | 欧美亚洲日韩国产人成在线播放 | 久久无码人妻影院 | 久久国产36精品色熟妇 | 一本大道久久东京热无码av | а√天堂www在线天堂小说 | av小次郎收藏 | 无码人妻少妇伦在线电影 | 麻豆蜜桃av蜜臀av色欲av | 无码一区二区三区在线观看 | 亚洲人成网站免费播放 | 欧美熟妇另类久久久久久多毛 | 国产精品久久久久久久9999 | 无码人妻少妇伦在线电影 | 色欲久久久天天天综合网精品 | 大肉大捧一进一出视频出来呀 | 97久久超碰中文字幕 | 亚洲成av人在线观看网址 | 欧美 亚洲 国产 另类 | 亚洲欧洲无卡二区视頻 | 红桃av一区二区三区在线无码av | 日本爽爽爽爽爽爽在线观看免 | 精品乱码久久久久久久 | 性色欲网站人妻丰满中文久久不卡 | 亚洲欧美国产精品专区久久 | 鲁大师影院在线观看 | 日本护士毛茸茸高潮 | 日日摸天天摸爽爽狠狠97 | 97无码免费人妻超级碰碰夜夜 | 乱中年女人伦av三区 | 小sao货水好多真紧h无码视频 | 丁香啪啪综合成人亚洲 | 欧美一区二区三区视频在线观看 | 国产亚洲精品久久久久久久久动漫 | 国产乱人偷精品人妻a片 | 无码人妻丰满熟妇区五十路百度 | 国产精品va在线观看无码 | 最近中文2019字幕第二页 | 国产精品久久久久久久9999 | 国内精品人妻无码久久久影院蜜桃 | 欧美怡红院免费全部视频 | 妺妺窝人体色www在线小说 | 国产午夜视频在线观看 | 中文毛片无遮挡高清免费 | 牲欲强的熟妇农村老妇女视频 | 中国女人内谢69xxxxxa片 | 亚洲gv猛男gv无码男同 | 国产熟妇另类久久久久 | 国产人妻人伦精品 | 久久伊人色av天堂九九小黄鸭 | 国产无遮挡又黄又爽又色 | 亚拍精品一区二区三区探花 | 久久久www成人免费毛片 | 免费无码午夜福利片69 | 中文字幕无码免费久久99 | 久久无码专区国产精品s | 欧美精品免费观看二区 | 国产极品美女高潮无套在线观看 | 精品无码一区二区三区的天堂 | 少妇人妻大乳在线视频 | 久久久国产一区二区三区 | 亚欧洲精品在线视频免费观看 | 人人妻人人澡人人爽欧美一区 | 精品 日韩 国产 欧美 视频 | 牛和人交xxxx欧美 | 麻豆md0077饥渴少妇 | 99er热精品视频 | 人妻少妇被猛烈进入中文字幕 | 中文字幕无码av激情不卡 | 亚洲区小说区激情区图片区 | 亚洲精品无码国产 | 国产另类ts人妖一区二区 | 夜夜夜高潮夜夜爽夜夜爰爰 | 天海翼激烈高潮到腰振不止 | 中文字幕无码av波多野吉衣 | 自拍偷自拍亚洲精品10p | 日本高清一区免费中文视频 | 清纯唯美经典一区二区 | 人妻无码久久精品人妻 | 好男人社区资源 | 久精品国产欧美亚洲色aⅴ大片 | 国产极品美女高潮无套在线观看 | 精品午夜福利在线观看 | 亚洲小说春色综合另类 | 人妻中文无码久热丝袜 | 丝袜 中出 制服 人妻 美腿 | 久久精品国产大片免费观看 | 久久久精品成人免费观看 | 国产内射老熟女aaaa | 99久久99久久免费精品蜜桃 | 国产熟妇另类久久久久 | 成人无码精品一区二区三区 | 欧美兽交xxxx×视频 | 初尝人妻少妇中文字幕 | 国产美女极度色诱视频www | 亚洲狠狠色丁香婷婷综合 | 亚洲色欲色欲欲www在线 | 在线视频网站www色 | 色偷偷人人澡人人爽人人模 | 国产xxx69麻豆国语对白 | 秋霞成人午夜鲁丝一区二区三区 | 99视频精品全部免费免费观看 | 国产亚洲人成在线播放 | 强辱丰满人妻hd中文字幕 | 亚洲 欧美 激情 小说 另类 | 亚洲熟悉妇女xxx妇女av | 久久亚洲中文字幕无码 | 玩弄人妻少妇500系列视频 | 呦交小u女精品视频 | 国产无套粉嫩白浆在线 | 久久精品国产99久久6动漫 | 99国产精品白浆在线观看免费 | 国产精品沙发午睡系列 | 女人被爽到呻吟gif动态图视看 | 大肉大捧一进一出好爽视频 | 午夜无码人妻av大片色欲 | 久久久久久国产精品无码下载 | 老子影院午夜精品无码 | 女人被男人躁得好爽免费视频 | 日本精品人妻无码免费大全 | 男人的天堂av网站 | 久久亚洲a片com人成 | 无码人妻精品一区二区三区不卡 | 午夜理论片yy44880影院 | 无码乱肉视频免费大全合集 | 色欲人妻aaaaaaa无码 | 激情人妻另类人妻伦 | 精品夜夜澡人妻无码av蜜桃 | 日韩在线不卡免费视频一区 | 国产午夜亚洲精品不卡 | 男女作爱免费网站 | 国产精品无码一区二区三区不卡 | 日韩欧美中文字幕在线三区 | 丰满人妻翻云覆雨呻吟视频 | 国产欧美亚洲精品a | 亚洲国产一区二区三区在线观看 | www国产亚洲精品久久久日本 | 亚洲欧美综合区丁香五月小说 | 国产成人综合在线女婷五月99播放 | 久久精品国产一区二区三区 | 理论片87福利理论电影 | 久久精品中文字幕一区 | 高潮毛片无遮挡高清免费视频 | 久久久精品456亚洲影院 | 午夜理论片yy44880影院 | 天堂亚洲2017在线观看 | 午夜无码区在线观看 | 日韩av无码中文无码电影 | 欧美野外疯狂做受xxxx高潮 | 亚洲人成网站色7799 | 欧美人与物videos另类 | 伊人久久婷婷五月综合97色 | 中文字幕无码视频专区 | 在线看片无码永久免费视频 | 大肉大捧一进一出好爽视频 | 精品无码国产一区二区三区av | 久久久精品欧美一区二区免费 | 国産精品久久久久久久 | 精品国精品国产自在久国产87 | 亚洲成a人片在线观看无码3d | 亚洲日韩中文字幕在线播放 | 黑人玩弄人妻中文在线 | 国产欧美亚洲精品a | 国产偷国产偷精品高清尤物 | 性生交大片免费看l | аⅴ资源天堂资源库在线 | 无码国产激情在线观看 | 日韩欧美中文字幕在线三区 | 无码人妻av免费一区二区三区 | 成人亚洲精品久久久久 | 天下第一社区视频www日本 | 亚洲综合色区中文字幕 | 亚洲日韩一区二区 | 99久久亚洲精品无码毛片 | 四虎4hu永久免费 | 日本又色又爽又黄的a片18禁 | 在线观看国产一区二区三区 | 国产午夜无码视频在线观看 | 红桃av一区二区三区在线无码av | 真人与拘做受免费视频一 | 久久综合狠狠综合久久综合88 | 色偷偷人人澡人人爽人人模 | 性欧美疯狂xxxxbbbb | а√资源新版在线天堂 | 亚洲精品成a人在线观看 | 久久精品国产99久久6动漫 | 中文精品久久久久人妻不卡 | 亚洲热妇无码av在线播放 | 亚无码乱人伦一区二区 | 国产成人无码av在线影院 | 亚洲精品国产精品乱码视色 | 奇米影视7777久久精品 | 久久精品人妻少妇一区二区三区 | 国产电影无码午夜在线播放 | 在线欧美精品一区二区三区 | 亚洲国产精品一区二区美利坚 | 精品国产成人一区二区三区 | 中文字幕+乱码+中文字幕一区 | 青青青手机频在线观看 | 欧美老熟妇乱xxxxx | 熟妇人妻无乱码中文字幕 | 少妇邻居内射在线 | 国产亚av手机在线观看 | 国产精品人妻一区二区三区四 | 强辱丰满人妻hd中文字幕 | 国产成人久久精品流白浆 | 无码av免费一区二区三区试看 | 国产精品毛片一区二区 | 亚洲一区二区三区含羞草 | 国产av人人夜夜澡人人爽麻豆 | 2019nv天堂香蕉在线观看 | 亚洲gv猛男gv无码男同 | 2020久久香蕉国产线看观看 | 乱人伦人妻中文字幕无码久久网 | 亚洲区欧美区综合区自拍区 | 曰本女人与公拘交酡免费视频 | 亚洲国产精品久久久久久 | 久久精品人人做人人综合试看 | 国产成人一区二区三区别 | 丰满少妇熟乱xxxxx视频 | 波多野结衣av在线观看 | 久久精品国产99久久6动漫 | 国产高清不卡无码视频 | 少妇无码av无码专区在线观看 | 亚洲第一无码av无码专区 | 成人试看120秒体验区 | 樱花草在线播放免费中文 | 久久综合香蕉国产蜜臀av | 国产精品久久久av久久久 | 国产在线一区二区三区四区五区 | 无码精品人妻一区二区三区av | 欧美丰满熟妇xxxx性ppx人交 | 色综合视频一区二区三区 | 欧美精品免费观看二区 | 日韩av无码一区二区三区 | 色五月丁香五月综合五月 | 麻豆人妻少妇精品无码专区 | 无码播放一区二区三区 | 少妇人妻av毛片在线看 | 国产亚洲精品精品国产亚洲综合 | 亚洲综合无码久久精品综合 | 55夜色66夜色国产精品视频 | 久久精品国产一区二区三区 | 97资源共享在线视频 | 性欧美疯狂xxxxbbbb | 中国女人内谢69xxxx | 麻豆精品国产精华精华液好用吗 | 丝袜 中出 制服 人妻 美腿 | 国产乱人无码伦av在线a | 日日干夜夜干 | 男女作爱免费网站 | 国产97色在线 | 免 | 3d动漫精品啪啪一区二区中 | 六月丁香婷婷色狠狠久久 | 国产人妻精品午夜福利免费 | 午夜精品久久久内射近拍高清 | 性啪啪chinese东北女人 | 欧美成人免费全部网站 | 婷婷五月综合激情中文字幕 | 亚洲精品一区二区三区四区五区 | 成年女人永久免费看片 | 精品国产成人一区二区三区 | 亚洲国产精品久久久久久 | 亚洲欧洲无卡二区视頻 | 全黄性性激高免费视频 | 欧美高清在线精品一区 | 欧美国产日韩亚洲中文 | 玩弄中年熟妇正在播放 | 亚洲精品一区二区三区在线 | 色婷婷香蕉在线一区二区 | 色综合天天综合狠狠爱 | 欧美熟妇另类久久久久久不卡 | 国产亚洲日韩欧美另类第八页 | 国产麻豆精品一区二区三区v视界 | 亚洲色www成人永久网址 | 性啪啪chinese东北女人 | 少妇被粗大的猛进出69影院 | 久久亚洲中文字幕精品一区 | 中文字幕无线码免费人妻 | 俄罗斯老熟妇色xxxx | 国产一区二区三区精品视频 | 对白脏话肉麻粗话av | 亚洲国产精品成人久久蜜臀 | 无码国产乱人伦偷精品视频 | 久久综合给久久狠狠97色 | 国产精品亚洲а∨无码播放麻豆 | 欧美日韩视频无码一区二区三 | 亚洲精品一区二区三区在线观看 | 福利一区二区三区视频在线观看 | 日欧一片内射va在线影院 | 亚洲精品一区二区三区大桥未久 | 人人妻人人藻人人爽欧美一区 | 草草网站影院白丝内射 | 国模大胆一区二区三区 | 精品国精品国产自在久国产87 | 国产小呦泬泬99精品 | 日本一区二区三区免费播放 | 夜夜夜高潮夜夜爽夜夜爰爰 | 日韩av无码一区二区三区不卡 | 国产人妻大战黑人第1集 | 亚洲国产欧美在线成人 | 高中生自慰www网站 | 99久久精品国产一区二区蜜芽 | 啦啦啦www在线观看免费视频 | 国产精品人人妻人人爽 | 欧美自拍另类欧美综合图片区 | 国产免费无码一区二区视频 | 东京一本一道一二三区 | 天天爽夜夜爽夜夜爽 | 中文字幕无码av激情不卡 | 免费网站看v片在线18禁无码 | 国产超碰人人爽人人做人人添 | 99久久精品午夜一区二区 | 亚洲精品鲁一鲁一区二区三区 | 免费网站看v片在线18禁无码 | 天天综合网天天综合色 | 亚洲区小说区激情区图片区 | 澳门永久av免费网站 | 亚洲日韩精品欧美一区二区 | 蜜桃臀无码内射一区二区三区 | 久久久久亚洲精品中文字幕 | 香港三级日本三级妇三级 | 一个人免费观看的www视频 | 夜夜夜高潮夜夜爽夜夜爰爰 | 亚洲精品鲁一鲁一区二区三区 | 性欧美牲交在线视频 | 日日摸夜夜摸狠狠摸婷婷 | 红桃av一区二区三区在线无码av | 国精产品一品二品国精品69xx | 国产艳妇av在线观看果冻传媒 | 午夜精品一区二区三区的区别 | 少妇人妻偷人精品无码视频 | 国产精品美女久久久 | 亚洲成色在线综合网站 | 少妇无套内谢久久久久 | 天天拍夜夜添久久精品 | 中文字幕+乱码+中文字幕一区 | 丁香花在线影院观看在线播放 | 久久 国产 尿 小便 嘘嘘 | 亚洲精品一区三区三区在线观看 | 亚洲熟妇色xxxxx亚洲 | 少妇无码一区二区二三区 | 欧美激情一区二区三区成人 | 午夜福利不卡在线视频 | 日韩精品成人一区二区三区 | 又大又硬又爽免费视频 | 国产色在线 | 国产 | 欧美性生交xxxxx久久久 | 亚洲国产精品一区二区美利坚 | 乱人伦人妻中文字幕无码 | 无码国产激情在线观看 | 娇妻被黑人粗大高潮白浆 | 亚洲 a v无 码免 费 成 人 a v | 日日噜噜噜噜夜夜爽亚洲精品 | 久久久www成人免费毛片 | 亚洲狠狠色丁香婷婷综合 | 亚洲成av人片在线观看无码不卡 | 久久国产精品偷任你爽任你 | 欧美黑人巨大xxxxx | 国产精品福利视频导航 | 国产又爽又猛又粗的视频a片 | 久久久久国色av免费观看性色 | 中文字幕无码日韩专区 | 成人免费视频在线观看 | 99国产精品白浆在线观看免费 | 国产精品欧美成人 | 日欧一片内射va在线影院 | 黑人玩弄人妻中文在线 | 欧美怡红院免费全部视频 | 天海翼激烈高潮到腰振不止 | 亚洲人成网站色7799 | 日日鲁鲁鲁夜夜爽爽狠狠 | 国产人妻精品午夜福利免费 | 亚洲大尺度无码无码专区 | 久久综合给久久狠狠97色 | 对白脏话肉麻粗话av | 奇米影视7777久久精品 | 天天拍夜夜添久久精品大 | 丰满岳乱妇在线观看中字无码 | 亚洲综合久久一区二区 | 亚洲精品国产精品乱码视色 | 精品久久久久久亚洲精品 | 黑人巨大精品欧美黑寡妇 | 精品国产麻豆免费人成网站 | 任你躁在线精品免费 | 97精品人妻一区二区三区香蕉 | 国产另类ts人妖一区二区 | 成人欧美一区二区三区黑人免费 | 大肉大捧一进一出好爽视频 | aⅴ亚洲 日韩 色 图网站 播放 | 国产精品久久久久影院嫩草 | 亚洲国产精华液网站w | 亚洲色欲久久久综合网东京热 | 久久久国产精品无码免费专区 | 亚洲国产av精品一区二区蜜芽 | 小鲜肉自慰网站xnxx | 天天燥日日燥 | 中文字幕无码热在线视频 | 性生交大片免费看女人按摩摩 | 夜先锋av资源网站 | 5858s亚洲色大成网站www | 国産精品久久久久久久 | 日韩少妇白浆无码系列 | 国产亚洲日韩欧美另类第八页 | 欧美熟妇另类久久久久久多毛 | 99久久精品日本一区二区免费 | 国产欧美熟妇另类久久久 | 色婷婷久久一区二区三区麻豆 | 午夜精品久久久久久久久 | 美女扒开屁股让男人桶 | 亚洲色大成网站www国产 | 国产乱子伦视频在线播放 | 东京无码熟妇人妻av在线网址 | 亚洲日韩一区二区 | 97久久精品无码一区二区 | 黑人巨大精品欧美一区二区 | 精品久久8x国产免费观看 | 51国偷自产一区二区三区 | 国产精华av午夜在线观看 | 亚洲中文字幕在线无码一区二区 | 中文字幕无码乱人伦 | 香蕉久久久久久av成人 | 在线亚洲高清揄拍自拍一品区 | 久久人人爽人人爽人人片av高清 | 国产精品久久久久久无码 | 久久久久se色偷偷亚洲精品av | 又色又爽又黄的美女裸体网站 | aⅴ在线视频男人的天堂 | 小sao货水好多真紧h无码视频 | 国产精品久久久久久亚洲影视内衣 | 少妇性荡欲午夜性开放视频剧场 | 强开小婷嫩苞又嫩又紧视频 | 熟妇激情内射com | 综合网日日天干夜夜久久 | www一区二区www免费 | 免费观看的无遮挡av | 国产美女极度色诱视频www | 日韩欧美中文字幕公布 | 中文无码成人免费视频在线观看 | 九月婷婷人人澡人人添人人爽 | 四虎国产精品免费久久 | 亚洲最大成人网站 | 久久www免费人成人片 | 亚洲va中文字幕无码久久不卡 | 中文无码精品a∨在线观看不卡 | 国产精品久久久久无码av色戒 | 欧美性色19p | 国产精品久久福利网站 | 99久久精品午夜一区二区 | 2020久久超碰国产精品最新 | 亚洲天堂2017无码中文 | 伊人久久婷婷五月综合97色 | 国产欧美熟妇另类久久久 | 亚洲天堂2017无码 | 人妻互换免费中文字幕 | 中文久久乱码一区二区 | 丰满肥臀大屁股熟妇激情视频 | av香港经典三级级 在线 | 自拍偷自拍亚洲精品10p | 国产精品久免费的黄网站 | 正在播放东北夫妻内射 | 精品一区二区不卡无码av | 粗大的内捧猛烈进出视频 | 欧洲极品少妇 | 十八禁真人啪啪免费网站 | 亚洲人成影院在线无码按摩店 | 精品国产乱码久久久久乱码 | 天堂久久天堂av色综合 | 国产精品亚洲综合色区韩国 | 久9re热视频这里只有精品 | 蜜桃臀无码内射一区二区三区 | 国产香蕉尹人视频在线 | 撕开奶罩揉吮奶头视频 | 国产精品久久久久久亚洲影视内衣 | 四虎永久在线精品免费网址 | av在线亚洲欧洲日产一区二区 | 国产乱人伦偷精品视频 | ass日本丰满熟妇pics | 亚洲娇小与黑人巨大交 | 熟女俱乐部五十路六十路av | 日韩av激情在线观看 | 亚洲国产精品毛片av不卡在线 | 97久久国产亚洲精品超碰热 | 色综合天天综合狠狠爱 | 色综合久久88色综合天天 | a片免费视频在线观看 | 99久久久国产精品无码免费 | 一区二区传媒有限公司 | 色婷婷综合中文久久一本 | 男人的天堂2018无码 | 精品成人av一区二区三区 | 久久精品国产一区二区三区 | 99在线 | 亚洲 | 久久久精品国产sm最大网站 | 亚洲日韩乱码中文无码蜜桃臀网站 | 一区二区三区乱码在线 | 欧洲 | 国产艳妇av在线观看果冻传媒 | 日韩少妇白浆无码系列 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 国产亚洲精品久久久久久大师 | 国产av一区二区三区最新精品 | 免费男性肉肉影院 | 亚洲码国产精品高潮在线 | 狠狠cao日日穞夜夜穞av | 午夜理论片yy44880影院 | a片免费视频在线观看 | 无人区乱码一区二区三区 | 亚洲中文字幕在线观看 | 国产情侣作爱视频免费观看 | 在线精品亚洲一区二区 | 久久久婷婷五月亚洲97号色 | 天堂亚洲2017在线观看 | 麻豆精品国产精华精华液好用吗 | 欧美激情综合亚洲一二区 | 久久精品国产一区二区三区 | 欧美性黑人极品hd | 精品无人区无码乱码毛片国产 | 亚洲最大成人网站 | 亚洲一区二区三区 | 亚洲色偷偷男人的天堂 | 色综合久久中文娱乐网 | 狠狠色色综合网站 | 久久精品国产一区二区三区肥胖 | 国产亚洲美女精品久久久2020 | 欧美 日韩 人妻 高清 中文 | 久久人人爽人人爽人人片av高清 | 亚洲欧美日韩综合久久久 | a国产一区二区免费入口 | www国产亚洲精品久久网站 | 中文字幕+乱码+中文字幕一区 | 日韩精品乱码av一区二区 | 又湿又紧又大又爽a视频国产 | 天天综合网天天综合色 | 麻豆蜜桃av蜜臀av色欲av | 俺去俺来也在线www色官网 | 精品成人av一区二区三区 | 欧美性猛交内射兽交老熟妇 | 国产成人无码a区在线观看视频app | 国产av剧情md精品麻豆 | 国产在线精品一区二区高清不卡 | 未满小14洗澡无码视频网站 | 久久亚洲精品中文字幕无男同 | 午夜性刺激在线视频免费 | 99久久99久久免费精品蜜桃 | 国产明星裸体无码xxxx视频 | 日本精品高清一区二区 | 国产成人精品一区二区在线小狼 | 午夜精品一区二区三区的区别 | 国产色在线 | 国产 | а√资源新版在线天堂 | 黑人粗大猛烈进出高潮视频 | 美女扒开屁股让男人桶 | 久久久www成人免费毛片 | 中文字幕+乱码+中文字幕一区 | 理论片87福利理论电影 | 亚洲 激情 小说 另类 欧美 | 国产一区二区三区精品视频 | 国产亲子乱弄免费视频 | 免费人成网站视频在线观看 | 国产精品亚洲lv粉色 | 久久五月精品中文字幕 | 激情国产av做激情国产爱 | 欧美人与动性行为视频 | 老司机亚洲精品影院 | 久久人人爽人人人人片 | 国产情侣作爱视频免费观看 | 国内少妇偷人精品视频 | 欧美老妇交乱视频在线观看 | 亚洲国产av美女网站 | 日本肉体xxxx裸交 | 免费人成在线观看网站 | 久9re热视频这里只有精品 | 人妻有码中文字幕在线 | 撕开奶罩揉吮奶头视频 | 久久午夜无码鲁丝片午夜精品 | 中文字幕av日韩精品一区二区 | 国产亚洲美女精品久久久2020 | 色婷婷综合中文久久一本 | 日日鲁鲁鲁夜夜爽爽狠狠 | 亚洲精品综合一区二区三区在线 | 99精品久久毛片a片 | 国产在线一区二区三区四区五区 | 未满小14洗澡无码视频网站 | 性色欲网站人妻丰满中文久久不卡 | 麻豆蜜桃av蜜臀av色欲av | 高清不卡一区二区三区 | 久久人人爽人人爽人人片av高清 | 国产黄在线观看免费观看不卡 | 在线播放无码字幕亚洲 | 成熟女人特级毛片www免费 | 中文无码伦av中文字幕 | 狠狠综合久久久久综合网 | 四虎国产精品一区二区 | 在教室伦流澡到高潮hnp视频 | 人人妻人人澡人人爽人人精品 | 国产熟女一区二区三区四区五区 | 精品国产一区二区三区av 性色 | 国产精品人妻一区二区三区四 | 国产乱码精品一品二品 | 老司机亚洲精品影院无码 | 高清国产亚洲精品自在久久 | 欧美精品在线观看 | 国产xxx69麻豆国语对白 | 色狠狠av一区二区三区 | 宝宝好涨水快流出来免费视频 | 亚洲一区二区三区在线观看网站 | 日本爽爽爽爽爽爽在线观看免 | 亚洲精品国产精品乱码视色 | 日韩亚洲欧美中文高清在线 | 欧美激情综合亚洲一二区 | 亚洲综合无码一区二区三区 | 亚洲精品欧美二区三区中文字幕 | 国产色视频一区二区三区 | 日日摸天天摸爽爽狠狠97 | 国产亲子乱弄免费视频 | 偷窥村妇洗澡毛毛多 | 丰满少妇人妻久久久久久 | 少妇一晚三次一区二区三区 | 亚洲成色www久久网站 | 欧美自拍另类欧美综合图片区 | 丰满人妻翻云覆雨呻吟视频 | 国产区女主播在线观看 | 精品水蜜桃久久久久久久 | 性啪啪chinese东北女人 | 人妻少妇被猛烈进入中文字幕 | 色婷婷久久一区二区三区麻豆 | 亚洲毛片av日韩av无码 | 又粗又大又硬又长又爽 | 大肉大捧一进一出视频出来呀 | 又黄又爽又色的视频 | 久久亚洲日韩精品一区二区三区 | 国产偷抇久久精品a片69 | 国产在线无码精品电影网 | 国产成人久久精品流白浆 | 久久久久亚洲精品中文字幕 | 爆乳一区二区三区无码 | 日本免费一区二区三区最新 | 亚洲人成网站在线播放942 | 精品久久久无码中文字幕 | 国产午夜精品一区二区三区嫩草 | 亚洲日韩av片在线观看 | 亚洲一区二区三区国产精华液 | 久久99精品久久久久久 | 亚洲无人区午夜福利码高清完整版 | 婷婷五月综合激情中文字幕 | √8天堂资源地址中文在线 | 国产超级va在线观看视频 | 婷婷色婷婷开心五月四房播播 | 人人爽人人澡人人人妻 | 在线欧美精品一区二区三区 | 图片区 小说区 区 亚洲五月 | 亚洲中文无码av永久不收费 | 欧美丰满老熟妇xxxxx性 | 无遮挡啪啪摇乳动态图 | 99视频精品全部免费免费观看 | 亚洲国产精品毛片av不卡在线 | 国产乡下妇女做爰 | 四虎4hu永久免费 | 丁香啪啪综合成人亚洲 | 精品aⅴ一区二区三区 | 国内老熟妇对白xxxxhd | 欧美精品一区二区精品久久 | 强辱丰满人妻hd中文字幕 | 天天躁夜夜躁狠狠是什么心态 | 宝宝好涨水快流出来免费视频 | 97精品人妻一区二区三区香蕉 | 大胆欧美熟妇xx | 亚洲国产精华液网站w | 国产无套内射久久久国产 | 欧美亚洲国产一区二区三区 | 亚洲精品www久久久 | 国产人成高清在线视频99最全资源 | 国产成人午夜福利在线播放 | 天天燥日日燥 | 亚洲成av人影院在线观看 | 久久精品中文闷骚内射 | 99视频精品全部免费免费观看 | 国产高潮视频在线观看 | 丰满诱人的人妻3 | 亚洲色无码一区二区三区 | 久久精品成人欧美大片 | 女人被男人躁得好爽免费视频 | 久久久精品欧美一区二区免费 | 免费人成在线观看网站 | 在线a亚洲视频播放在线观看 | 国产 浪潮av性色四虎 | 99久久无码一区人妻 | 露脸叫床粗话东北少妇 | a在线观看免费网站大全 | 国产网红无码精品视频 | 内射欧美老妇wbb | 激情综合激情五月俺也去 | 久久国产精品偷任你爽任你 | 女人被爽到呻吟gif动态图视看 | 精品国产乱码久久久久乱码 | 亚洲欧美精品aaaaaa片 | 无码帝国www无码专区色综合 | 女人被爽到呻吟gif动态图视看 | 国产高清不卡无码视频 | 97无码免费人妻超级碰碰夜夜 | 久久久久人妻一区精品色欧美 | 亚洲国产精品久久久久久 | av香港经典三级级 在线 | 激情国产av做激情国产爱 | 国产猛烈高潮尖叫视频免费 | 国产成人无码一二三区视频 | 国产高清不卡无码视频 | 欧美人与禽猛交狂配 | 国产97在线 | 亚洲 | 国产亲子乱弄免费视频 | 色综合视频一区二区三区 | 黄网在线观看免费网站 | 国产精品久久久午夜夜伦鲁鲁 | 无码精品人妻一区二区三区av | 久久国语露脸国产精品电影 | 玩弄人妻少妇500系列视频 | 无套内谢的新婚少妇国语播放 | 久久99精品久久久久婷婷 | 国产无套内射久久久国产 | 亚洲第一无码av无码专区 | 亚洲aⅴ无码成人网站国产app | 久久国产精品_国产精品 | 亚洲成a人片在线观看无码3d | 四虎影视成人永久免费观看视频 | 极品尤物被啪到呻吟喷水 | 精品国产一区二区三区四区 | 激情五月综合色婷婷一区二区 | 久久精品女人天堂av免费观看 | 黑人玩弄人妻中文在线 | 国产精品无套呻吟在线 | 亚洲国产精品无码一区二区三区 | 沈阳熟女露脸对白视频 | 国色天香社区在线视频 | 亚洲成av人影院在线观看 | 色欲av亚洲一区无码少妇 | 老子影院午夜伦不卡 | 久久精品人妻少妇一区二区三区 | 国产精品欧美成人 | 国产精品无码一区二区桃花视频 | 国产精品久久久久久亚洲毛片 | 国产黑色丝袜在线播放 | 色一情一乱一伦一区二区三欧美 | 日韩人妻系列无码专区 | 国产亚洲精品久久久久久久久动漫 | 中文字幕无线码免费人妻 | 国产精品18久久久久久麻辣 | 亚洲 日韩 欧美 成人 在线观看 | 天下第一社区视频www日本 | 亚洲精品成人av在线 | 76少妇精品导航 | 99视频精品全部免费免费观看 | 在线观看欧美一区二区三区 | 国产片av国语在线观看 | 天堂一区人妻无码 | 久久国产36精品色熟妇 | 粉嫩少妇内射浓精videos | 免费国产成人高清在线观看网站 | 国产亚洲视频中文字幕97精品 | 欧美自拍另类欧美综合图片区 | 亚洲成a人一区二区三区 | 国产av一区二区三区最新精品 | 亚洲第一无码av无码专区 | 人妻少妇精品无码专区动漫 | 无码人妻av免费一区二区三区 | 黑人巨大精品欧美一区二区 | 久久久久成人精品免费播放动漫 | 国产成人无码一二三区视频 | 76少妇精品导航 | 亚洲一区二区三区国产精华液 | 波多野结衣一区二区三区av免费 | 澳门永久av免费网站 | 老司机亚洲精品影院无码 | 久久97精品久久久久久久不卡 | 日本va欧美va欧美va精品 | 日日躁夜夜躁狠狠躁 | 中文字幕 人妻熟女 | 一本加勒比波多野结衣 | 中文无码伦av中文字幕 | 国产电影无码午夜在线播放 | 国产内射爽爽大片视频社区在线 | 成人亚洲精品久久久久软件 | 麻豆国产丝袜白领秘书在线观看 | 久热国产vs视频在线观看 | 中文字幕乱码人妻无码久久 | 国产人妖乱国产精品人妖 | 久久亚洲日韩精品一区二区三区 | 成人欧美一区二区三区黑人免费 | 狠狠色欧美亚洲狠狠色www | 久久亚洲精品成人无码 | 亚洲精品一区二区三区四区五区 | 99视频精品全部免费免费观看 | 中文字幕人妻无码一区二区三区 | 正在播放东北夫妻内射 | 麻豆国产人妻欲求不满谁演的 | 国产成人综合美国十次 | 精品久久久久香蕉网 | 久久久久久亚洲精品a片成人 | 伊人色综合久久天天小片 | 无码成人精品区在线观看 | 成人一在线视频日韩国产 | 久久久精品成人免费观看 | 无码午夜成人1000部免费视频 | 一二三四在线观看免费视频 | 精品一二三区久久aaa片 | 国产精品亚洲lv粉色 | 久久人妻内射无码一区三区 | 精品国产麻豆免费人成网站 | 丝袜足控一区二区三区 | 中文字幕日产无线码一区 | 国产内射爽爽大片视频社区在线 | 国产99久久精品一区二区 | 两性色午夜视频免费播放 | 欧美一区二区三区 | 国产亲子乱弄免费视频 | 亚洲国产一区二区三区在线观看 | 亚洲精品久久久久avwww潮水 | 中文字幕无码免费久久9一区9 | 亚洲综合精品香蕉久久网 | 国产办公室秘书无码精品99 | 131美女爱做视频 | 成人免费视频视频在线观看 免费 | 国产精品久久久 | 国产口爆吞精在线视频 | 黑森林福利视频导航 | 中文字幕无码日韩专区 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 永久免费观看美女裸体的网站 | 亚洲欧洲无卡二区视頻 | 国产乱人伦偷精品视频 | 亚洲男人av天堂午夜在 | 久久精品人妻少妇一区二区三区 | 狠狠色噜噜狠狠狠狠7777米奇 | 久久国产精品偷任你爽任你 | 日韩成人一区二区三区在线观看 | 国产超碰人人爽人人做人人添 | 熟妇激情内射com | 狂野欧美激情性xxxx | 夜夜夜高潮夜夜爽夜夜爰爰 | 久久精品国产一区二区三区 | 精品人妻人人做人人爽夜夜爽 | 亚洲 日韩 欧美 成人 在线观看 | 欧美激情一区二区三区成人 | 亚洲人成影院在线无码按摩店 | 丝袜 中出 制服 人妻 美腿 | 波多野结衣一区二区三区av免费 | 日本乱偷人妻中文字幕 | 沈阳熟女露脸对白视频 | 免费视频欧美无人区码 | 亚洲人成人无码网www国产 | 性做久久久久久久免费看 | 网友自拍区视频精品 | 国产在线精品一区二区三区直播 | 理论片87福利理论电影 | 高中生自慰www网站 | 最新国产乱人伦偷精品免费网站 | 亚洲精品一区二区三区婷婷月 | 亚洲精品综合一区二区三区在线 | 国产精品久久福利网站 | 熟妇女人妻丰满少妇中文字幕 | 国产无遮挡又黄又爽免费视频 | 亚洲日韩精品欧美一区二区 | 亚洲一区二区三区 | 国产激情一区二区三区 | 国产成人精品必看 | 国产精品亚洲а∨无码播放麻豆 | 少妇久久久久久人妻无码 | 国产精品国产三级国产专播 | 亚洲精品一区二区三区在线 | 亚洲国产午夜精品理论片 | 色爱情人网站 | 小sao货水好多真紧h无码视频 | 欧美日韩综合一区二区三区 | 久久久精品456亚洲影院 | 3d动漫精品啪啪一区二区中 | 亚洲综合久久一区二区 | 精品熟女少妇av免费观看 | av人摸人人人澡人人超碰下载 | 亚洲爆乳大丰满无码专区 | 天海翼激烈高潮到腰振不止 | 永久免费观看美女裸体的网站 | 最近免费中文字幕中文高清百度 | 无码人中文字幕 | 日韩精品久久久肉伦网站 | 国产精品爱久久久久久久 | 色噜噜亚洲男人的天堂 | 中文字幕+乱码+中文字幕一区 | 国产99久久精品一区二区 | 99久久亚洲精品无码毛片 | 久久国产精品偷任你爽任你 | 一本色道久久综合亚洲精品不卡 | av人摸人人人澡人人超碰下载 | 亚洲欧洲中文日韩av乱码 | 伊在人天堂亚洲香蕉精品区 | 男人的天堂av网站 | 高潮毛片无遮挡高清免费视频 | 久久久久se色偷偷亚洲精品av | 婷婷综合久久中文字幕蜜桃三电影 | 亚洲中文字幕久久无码 | 中文字幕乱码人妻无码久久 | 成人aaa片一区国产精品 | 久在线观看福利视频 | 未满成年国产在线观看 | 曰韩无码二三区中文字幕 | 奇米影视7777久久精品 | 鲁鲁鲁爽爽爽在线视频观看 | 国内揄拍国内精品人妻 | 97夜夜澡人人爽人人喊中国片 | 亚洲中文无码av永久不收费 | 99久久精品日本一区二区免费 | 四虎影视成人永久免费观看视频 | 亚洲色偷偷男人的天堂 | 色婷婷香蕉在线一区二区 | 国内精品久久毛片一区二区 | 荫蒂添的好舒服视频囗交 | 国产猛烈高潮尖叫视频免费 | 婷婷五月综合激情中文字幕 | 国产精品va在线观看无码 | 成人性做爰aaa片免费看 | 国产乱人伦偷精品视频 | 少妇久久久久久人妻无码 | 又色又爽又黄的美女裸体网站 | 久久综合网欧美色妞网 | 四虎国产精品免费久久 | 久久99精品国产麻豆蜜芽 | 中文字幕无码av激情不卡 | 久精品国产欧美亚洲色aⅴ大片 | 国产国产精品人在线视 | 亚洲中文字幕无码一久久区 | 日韩欧美中文字幕公布 | 牲欲强的熟妇农村老妇女视频 | 377p欧洲日本亚洲大胆 | 国产人妻精品午夜福利免费 | 丝袜人妻一区二区三区 | 国产香蕉尹人综合在线观看 | 国产精品办公室沙发 | 在线观看国产一区二区三区 | 色一情一乱一伦一视频免费看 | 国产乱人偷精品人妻a片 | 99精品国产综合久久久久五月天 | 午夜无码区在线观看 | 亚洲国产精品久久久天堂 | 久久久久久a亚洲欧洲av冫 | 一区二区三区乱码在线 | 欧洲 | 国产精品鲁鲁鲁 | 欧美第一黄网免费网站 | 天天摸天天碰天天添 | 精品无码国产自产拍在线观看蜜 | 国产精品亚洲五月天高清 | 黑人大群体交免费视频 | 丝袜人妻一区二区三区 | 国产精品香蕉在线观看 | 少妇高潮喷潮久久久影院 | 四虎影视成人永久免费观看视频 | 日本大香伊一区二区三区 | 极品嫩模高潮叫床 | 免费看男女做好爽好硬视频 | 国产午夜无码精品免费看 | av香港经典三级级 在线 | 久久成人a毛片免费观看网站 | 一本精品99久久精品77 | 亚洲成av人综合在线观看 | 亚洲精品久久久久久久久久久 | 清纯唯美经典一区二区 | 国产网红无码精品视频 | 97人妻精品一区二区三区 | 国产麻豆精品一区二区三区v视界 | 成人欧美一区二区三区 | 又黄又爽又色的视频 | 亚洲区欧美区综合区自拍区 | 亚洲国产成人a精品不卡在线 | 伊人久久大香线焦av综合影院 | 人人妻人人澡人人爽人人精品 | 亚洲一区二区三区无码久久 | 国产乱人伦av在线无码 | 日韩欧美中文字幕在线三区 | 国产精品久久久久久亚洲毛片 | 日韩亚洲欧美中文高清在线 | 麻豆果冻传媒2021精品传媒一区下载 | 综合人妻久久一区二区精品 | 国产亚av手机在线观看 | 超碰97人人做人人爱少妇 | 久久久久国色av免费观看性色 | 伊人久久大香线蕉午夜 | 欧美xxxx黑人又粗又长 | 国产国语老龄妇女a片 | 亚洲の无码国产の无码影院 | 四虎国产精品一区二区 | 中文字幕日韩精品一区二区三区 | 成人一区二区免费视频 | 久久婷婷五月综合色国产香蕉 | 无码人妻精品一区二区三区不卡 | 亚洲gv猛男gv无码男同 | 人妻中文无码久热丝袜 | 亚洲国产精品毛片av不卡在线 | 国产人妻人伦精品 | 久久国产精品萌白酱免费 | 日韩欧美成人免费观看 | 香蕉久久久久久av成人 | 日日噜噜噜噜夜夜爽亚洲精品 | 国产精品亚洲一区二区三区喷水 | 午夜精品久久久内射近拍高清 | 成人三级无码视频在线观看 | 台湾无码一区二区 | 狠狠色丁香久久婷婷综合五月 | 国产精品内射视频免费 | 亚洲狠狠婷婷综合久久 | 国产精品福利视频导航 | 国产成人午夜福利在线播放 | 无码一区二区三区在线 | 国产莉萝无码av在线播放 | 十八禁视频网站在线观看 | 熟妇人妻无乱码中文字幕 | 天堂亚洲免费视频 | 在线精品国产一区二区三区 | 欧洲欧美人成视频在线 | 久久亚洲精品中文字幕无男同 | 国产高清不卡无码视频 | 国产av人人夜夜澡人人爽麻豆 | 乱人伦中文视频在线观看 | 日韩精品无码一本二本三本色 | 永久免费观看国产裸体美女 | 无码免费一区二区三区 | 亚洲а∨天堂久久精品2021 | 欧美xxxxx精品 | 日日噜噜噜噜夜夜爽亚洲精品 | 好男人社区资源 | 水蜜桃色314在线观看 | 亚洲日韩乱码中文无码蜜桃臀网站 | 久久久久久av无码免费看大片 | 中文精品无码中文字幕无码专区 | 色婷婷综合中文久久一本 | 亚洲成a人片在线观看无码 | 欧美日本免费一区二区三区 | 伊在人天堂亚洲香蕉精品区 | 亚洲一区二区三区国产精华液 | 免费无码av一区二区 | 成人综合网亚洲伊人 | 妺妺窝人体色www在线小说 | 亚洲精品中文字幕久久久久 | 国产亚洲精品久久久久久久久动漫 | 狠狠色噜噜狠狠狠狠7777米奇 | 高潮毛片无遮挡高清免费视频 | 中文字幕无码免费久久9一区9 | 无套内谢老熟女 | 女人和拘做爰正片视频 | 精品水蜜桃久久久久久久 | 在线观看欧美一区二区三区 | 高潮毛片无遮挡高清免费视频 | 国产成人无码区免费内射一片色欲 | 人人爽人人澡人人人妻 | 国产午夜手机精彩视频 | 久久 国产 尿 小便 嘘嘘 | 大色综合色综合网站 | 亚洲国产欧美国产综合一区 | 九九综合va免费看 | 亚洲色无码一区二区三区 | 窝窝午夜理论片影院 | 亚洲欧美日韩成人高清在线一区 | 欧美 丝袜 自拍 制服 另类 | 青青青手机频在线观看 | 国产av一区二区三区最新精品 | 国产两女互慰高潮视频在线观看 | 思思久久99热只有频精品66 | 一本久道久久综合狠狠爱 | 亚洲中文字幕无码中字 | 国内精品久久毛片一区二区 | 中文字幕av伊人av无码av | 日韩av无码中文无码电影 | 国产麻豆精品精东影业av网站 | 久久久av男人的天堂 | 国内精品人妻无码久久久影院蜜桃 | 国产精品亚洲一区二区三区喷水 | 鲁一鲁av2019在线 | 纯爱无遮挡h肉动漫在线播放 | 乱码午夜-极国产极内射 | 在线天堂新版最新版在线8 | 免费无码的av片在线观看 | 人人妻人人澡人人爽人人精品浪潮 | 久久精品中文字幕大胸 | 婷婷丁香五月天综合东京热 | 亚洲欧美日韩国产精品一区二区 | 一本加勒比波多野结衣 | a国产一区二区免费入口 | 波多野结衣乳巨码无在线观看 | 四十如虎的丰满熟妇啪啪 | 色综合久久久无码网中文 | 熟女体下毛毛黑森林 | 久久久久久久人妻无码中文字幕爆 | 国产手机在线αⅴ片无码观看 | 久青草影院在线观看国产 | 在线欧美精品一区二区三区 | 性欧美videos高清精品 | 国产人妻久久精品二区三区老狼 | 亚洲欧洲日本无在线码 | 日韩精品成人一区二区三区 | 巨爆乳无码视频在线观看 | 亚洲爆乳大丰满无码专区 | 东京热男人av天堂 | 日本护士xxxxhd少妇 | 久久久久久亚洲精品a片成人 | 无码纯肉视频在线观看 | 天天拍夜夜添久久精品 | 大乳丰满人妻中文字幕日本 | 无码av中文字幕免费放 | 3d动漫精品啪啪一区二区中 | 蜜桃av抽搐高潮一区二区 | 中文精品久久久久人妻不卡 | 国产免费无码一区二区视频 | 男女爱爱好爽视频免费看 | 国产乱人伦偷精品视频 | 久久精品女人的天堂av | 日韩精品无码一本二本三本色 | 亚洲国产av精品一区二区蜜芽 | 欧美高清在线精品一区 | 精品一区二区三区无码免费视频 | 久久无码专区国产精品s | 久久无码中文字幕免费影院蜜桃 | 日本熟妇人妻xxxxx人hd | 国产无遮挡吃胸膜奶免费看 | 色综合久久中文娱乐网 | 国产后入清纯学生妹 | 亚洲热妇无码av在线播放 | 国产在线无码精品电影网 | 亚洲成av人在线观看网址 | 最新版天堂资源中文官网 | 亚洲春色在线视频 | 国产黑色丝袜在线播放 | 少妇无码一区二区二三区 | 欧美熟妇另类久久久久久多毛 | 成人性做爰aaa片免费看 | 日本一区二区三区免费高清 | 5858s亚洲色大成网站www | 2020久久香蕉国产线看观看 | 中文无码成人免费视频在线观看 | 男人扒开女人内裤强吻桶进去 | 人人妻人人藻人人爽欧美一区 | 成年女人永久免费看片 | 未满小14洗澡无码视频网站 | 国产精品亚洲一区二区三区喷水 | 午夜精品久久久内射近拍高清 | 一个人看的www免费视频在线观看 | 欧洲精品码一区二区三区免费看 | 人妻aⅴ无码一区二区三区 | 久久99精品久久久久久 | 老子影院午夜精品无码 | 久久精品国产一区二区三区肥胖 | 久久人人爽人人人人片 | 欧美黑人巨大xxxxx | 日日躁夜夜躁狠狠躁 | 澳门永久av免费网站 | 日本熟妇大屁股人妻 | 国产av无码专区亚洲a∨毛片 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 国产精品国产三级国产专播 | 欧美喷潮久久久xxxxx | 人人妻人人澡人人爽人人精品 | 国产精品对白交换视频 | 亚洲精品鲁一鲁一区二区三区 | 欧美日本精品一区二区三区 | 人妻有码中文字幕在线 | √天堂中文官网8在线 | 国产在线精品一区二区三区直播 | 国产午夜福利亚洲第一 | 丁香花在线影院观看在线播放 | 日本精品少妇一区二区三区 | 中文字幕人成乱码熟女app | 免费乱码人妻系列无码专区 | 国产真实乱对白精彩久久 | 午夜精品久久久内射近拍高清 | 久久人人爽人人人人片 | 亚洲一区二区观看播放 | 欧美日韩视频无码一区二区三 | 九月婷婷人人澡人人添人人爽 | 中文字幕无码人妻少妇免费 | 亚洲天堂2017无码中文 | 日韩精品乱码av一区二区 | 亚洲国产欧美国产综合一区 | 亚洲无人区午夜福利码高清完整版 | 日日干夜夜干 | 亚洲一区二区观看播放 | 国产亚洲精品久久久久久久 | 天堂在线观看www | 亚洲国精产品一二二线 | 性欧美熟妇videofreesex | 一二三四社区在线中文视频 | 久久久久国色av免费观看性色 | 国产色在线 | 国产 | 久精品国产欧美亚洲色aⅴ大片 | 久久99精品国产.久久久久 | 又湿又紧又大又爽a视频国产 | 亚洲aⅴ无码成人网站国产app | 美女极度色诱视频国产 | 国产熟妇另类久久久久 | 国内揄拍国内精品少妇国语 | 日本精品人妻无码77777 天堂一区人妻无码 | 国产精品毛多多水多 | 亚洲人成网站色7799 | 无码国模国产在线观看 | 2020最新国产自产精品 | 国产在线精品一区二区高清不卡 | 伊人久久大香线蕉av一区二区 | 色综合久久中文娱乐网 | 日本丰满熟妇videos | 国产亚洲欧美日韩亚洲中文色 | 爱做久久久久久 | 人妻少妇被猛烈进入中文字幕 | 国产精品亚洲lv粉色 | 亚洲欧洲中文日韩av乱码 | 国产亚洲精品久久久久久 | 一本无码人妻在中文字幕免费 | 激情爆乳一区二区三区 | 性欧美大战久久久久久久 | 无码国产乱人伦偷精品视频 | 97se亚洲精品一区 | 老太婆性杂交欧美肥老太 | 久久亚洲国产成人精品性色 | 又大又黄又粗又爽的免费视频 | 久久久久久久久888 | 亚洲码国产精品高潮在线 | 搡女人真爽免费视频大全 | 色欲久久久天天天综合网精品 | 久久97精品久久久久久久不卡 | 久久国产精品精品国产色婷婷 | 成年美女黄网站色大免费全看 | 国产高清不卡无码视频 | 亚洲人成网站色7799 | 亚洲 另类 在线 欧美 制服 | 99久久99久久免费精品蜜桃 | 亚洲精品美女久久久久久久 | 久久99精品久久久久久 | 国产精品无码成人午夜电影 | 无码人妻丰满熟妇区五十路百度 | 久久97精品久久久久久久不卡 | 国产99久久精品一区二区 | 日本熟妇乱子伦xxxx | 欧美 日韩 亚洲 在线 | 熟妇人妻无乱码中文字幕 | 日韩av无码一区二区三区不卡 | 午夜福利试看120秒体验区 | 国产精品香蕉在线观看 | 亚洲经典千人经典日产 | 又大又紧又粉嫩18p少妇 | 久久久国产精品无码免费专区 | 国产 精品 自在自线 | 国产亚洲精品久久久久久大师 | 久久人人爽人人人人片 | 亚洲色www成人永久网址 | 欧美阿v高清资源不卡在线播放 | 一二三四社区在线中文视频 | 亚洲精品一区三区三区在线观看 | 久久精品国产一区二区三区肥胖 | 国产精品手机免费 | 成人性做爰aaa片免费看不忠 | 伊人色综合久久天天小片 | 妺妺窝人体色www在线小说 | 亚洲国精产品一二二线 |