成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring JDBCTemplate 核心架構(gòu)與執(zhí)行流程詳解:從原理到實踐

開發(fā) 架構(gòu)
JDBCTemplate 是 Spring 框架對 JDBC 的封裝,它簡化了傳統(tǒng) JDBC 的開發(fā)流程,減少了大量樣板代碼。下面是一個完整的 JDBCTemplate 入門案例。

圖表 系統(tǒng)解析了 Spring JDBCTemplate 的核心架構(gòu)與執(zhí)行流程,包含以下內(nèi)容:

  1. 架構(gòu)設(shè)計:展示 JdbcTemplateDataSourceRowMapper 等核心組件的協(xié)作關(guān)系,對比傳統(tǒng) JDBC 的簡化設(shè)計。
  2. 執(zhí)行流程:以查詢和更新操作為例,詳細(xì)拆解 SQL 執(zhí)行、參數(shù)綁定、結(jié)果映射、資源釋放等關(guān)鍵步驟。
  3. 交互與狀態(tài):通過序列圖、流程圖和狀態(tài)圖,直觀呈現(xiàn)組件交互時序和操作狀態(tài)轉(zhuǎn)換。
  4. 擴展能力:涵蓋 NamedParameterJdbcTemplate 和自定義 RowMapper 等高級用法。

適合開發(fā)者快速掌握 JDBCTemplate 的 自動化資源管理、異常封裝 和 高效數(shù)據(jù)訪問 原理,為 Spring 數(shù)據(jù)層開發(fā)提供清晰指導(dǎo)。

一、Spring JDBCTemplate 相關(guān)設(shè)計圖

1、核心類圖

圖片圖片

2、JDBCTemplate 核心組件交互圖

圖片圖片


3. 查詢操作狀態(tài)圖

圖片圖片

4. JDBCTemplate 執(zhí)行流程圖(以 query 方法為例)

圖片圖片

5. 更新操作流程圖

圖片圖片

這些圖表展示了:

  1. JDBCTemplate 的核心組件及其關(guān)系
  2. 執(zhí)行 SQL 查詢時的完整流程
  3. 各組件之間的交互順序
  4. 操作的不同狀態(tài)轉(zhuǎn)換

關(guān)鍵點說明:

  • JdbcTemplate 通過 DataSource 獲取數(shù)據(jù)庫連接
  • 使用 PreparedStatement 防止 SQL 注入
  • RowMapper 負(fù)責(zé)結(jié)果集到對象的映射
  • 自動處理資源的打開和關(guān)閉
  • 統(tǒng)一轉(zhuǎn)換 SQLException 為 DataAccessException

二、Spring JDBCTemplate 入門案例

JDBCTemplate 是 Spring 框架對 JDBC 的封裝,它簡化了傳統(tǒng) JDBC 的開發(fā)流程,減少了大量樣板代碼。下面是一個完整的 JDBCTemplate 入門案例。

1. 準(zhǔn)備工作

1.1 添加依賴

首先需要在項目中添加 Spring JDBC 和數(shù)據(jù)庫驅(qū)動的依賴(以 Maven 為例):

<!-- Spring JDBC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.18</version>
</dependency>

<!-- 數(shù)據(jù)庫驅(qū)動 (以MySQL為例) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>

<!-- 數(shù)據(jù)源 (以HikariCP為例) -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>

1.2 創(chuàng)建數(shù)據(jù)庫表

假設(shè)我們有一個簡單的用戶表:

CREATETABLE users (
    id INTPRIMARYKEYAUTO_INCREMENT,
    name VARCHAR(50)NOTNULL,
    age INT,
    email VARCHAR(100)
);

2. 配置數(shù)據(jù)源

2.1 Java 配置方式

importcom.zaxxer.hikari.HikariDataSource;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.jdbc.core.JdbcTemplate;

@Configuration
publicclassAppConfig{

@Bean
publicHikariDataSourcedataSource(){
HikariDataSource dataSource =newHikariDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/your_database");
        dataSource.setUsername("your_username");
        dataSource.setPassword("your_password");
        dataSource.setMaximumPoolSize(10);
return dataSource;
}

@Bean
publicJdbcTemplatejdbcTemplate(HikariDataSource dataSource){
returnnewJdbcTemplate(dataSource);
}
}

2.2 XML 配置方式

<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

<beanid="dataSource"class="com.zaxxer.hikari.HikariDataSource">
<propertyname="driverClassName"value="com.mysql.cj.jdbc.Driver"/>
<propertyname="jdbcUrl"value="jdbc:mysql://localhost:3306/your_database"/>
<propertyname="username"value="your_username"/>
<propertyname="password"value="your_password"/>
<propertyname="maximumPoolSize"value="10"/>
</bean>

<beanid="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate">
<propertyname="dataSource"ref="dataSource"/>
</bean>
</beans>

3. 創(chuàng)建實體類

publicclassUser{
privateInteger id;
privateString name;
privateInteger age;
privateString email;

// 構(gòu)造方法、getter和setter、toString等
publicUser(){}

publicUser(String name,Integer age,String email){
this.name = name;
this.age = age;
this.email = email;
}

// 省略其他getter和setter

@Override
publicStringtoString(){
return"User{"+
"id="+ id +
", name='"+ name + ''' +
", age="+ age +
", email='"+ email + ''' +
'}';
}
}

4. 創(chuàng)建 DAO 類

importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.jdbc.core.BeanPropertyRowMapper;
importorg.springframework.jdbc.core.JdbcTemplate;
importorg.springframework.jdbc.core.RowMapper;
importorg.springframework.stereotype.Repository;

importjava.util.List;

@Repository
publicclassUserDao{

@Autowired
privateJdbcTemplate jdbcTemplate;

// 添加用戶
publicintaddUser(User user){
String sql ="INSERT INTO users(name, age, email) VALUES(?, ?, ?)";
return jdbcTemplate.update(sql, user.getName(), user.getAge(), user.getEmail());
}

// 更新用戶
publicintupdateUser(User user){
String sql ="UPDATE users SET name=?, age=?, email=? WHERE id=?";
return jdbcTemplate.update(sql, user.getName(), user.getAge(), user.getEmail(), user.getId());
}

// 刪除用戶
publicintdeleteUser(Integer id){
String sql ="DELETE FROM users WHERE id=?";
return jdbcTemplate.update(sql, id);
}

// 根據(jù)ID查詢用戶
publicUsergetUserById(Integer id){
String sql ="SELECT * FROM users WHERE id=?";
RowMapper<User> rowMapper =newBeanPropertyRowMapper<>(User.class);
return jdbcTemplate.queryForObject(sql, rowMapper, id);
}

// 查詢所有用戶
publicList<User>getAllUsers(){
String sql ="SELECT * FROM users";
RowMapper<User> rowMapper =newBeanPropertyRowMapper<>(User.class);
return jdbcTemplate.query(sql, rowMapper);
}

// 查詢用戶數(shù)量
publicIntegergetCount(){
String sql ="SELECT COUNT(*) FROM users";
return jdbcTemplate.queryForObject(sql,Integer.class);
}
}

5. 測試類

importorg.springframework.context.ApplicationContext;
importorg.springframework.context.annotation.AnnotationConfigApplicationContext;

publicclassJdbcTemplateDemo{
publicstaticvoidmain(String[] args){
// 加載配置類
ApplicationContext context =newAnnotationConfigApplicationContext(AppConfig.class);

// 獲取UserDao實例
UserDao userDao = context.getBean(UserDao.class);

// 添加用戶
User user1 =newUser("張三",25,"zhangsan@example.com");
int result = userDao.addUser(user1);
System.out.println("添加用戶結(jié)果: "+ result);

// 查詢所有用戶
System.out.println("所有用戶:");
        userDao.getAllUsers().forEach(System.out::println);

// 更新用戶
User userToUpdate = userDao.getUserById(1);
        userToUpdate.setName("李四");
        userToUpdate.setEmail("lisi@example.com");
        result = userDao.updateUser(userToUpdate);
System.out.println("更新用戶結(jié)果: "+ result);

// 再次查詢所有用戶
System.out.println("更新后的所有用戶:");
        userDao.getAllUsers().forEach(System.out::println);

// 查詢用戶數(shù)量
System.out.println("用戶總數(shù): "+ userDao.getCount());

// 刪除用戶
        result = userDao.deleteUser(1);
System.out.println("刪除用戶結(jié)果: "+ result);
}
}

6. 核心方法說明

JDBCTemplate 提供了多種便捷方法:

  • update()  - 執(zhí)行 INSERT/UPDATE/DELETE 語句
jdbcTemplate.update(sql, params...);
  • queryForObject()  - 查詢單個對象
jdbcTemplate.queryForObject(sql, rowMapper, params...);
  • query()  - 查詢對象列表
jdbcTemplate.query(sql, rowMapper, params...);
  • queryForList()  - 查詢結(jié)果集到List[map]
jdbcTemplate.queryForList(sql, params...);
  • execute()  - 執(zhí)行任意SQL語句
jdbcTemplate.execute(sql);

三、Spring JDBCTemplate 入門案例

下面我將通過一個完整的 Spring Boot 整合 JDBCTemplate 的案例,詳細(xì)介紹如何使用 JDBCTemplate 進(jìn)行數(shù)據(jù)庫操作。

1. 創(chuàng)建 Spring Boot 項目

首先創(chuàng)建一個 Spring Boot 項目,可以使用 Spring Initializr 或 IDE 創(chuàng)建。

1.1 添加必要依賴

在 pom.xml 中添加以下依賴:

<dependencies>
<!-- Spring Boot Starter Web (可選,用于創(chuàng)建Controller測試) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Boot Starter JDBC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<!-- 數(shù)據(jù)庫驅(qū)動 (以MySQL為例) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

<!-- Lombok (可選,簡化代碼) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- 測試依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

2. 配置數(shù)據(jù)源

2.1 配置文件

在 application.properties 或 application.yml 中配置數(shù)據(jù)源:

# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/springboot_jdbc?useSSL=false&serverTimezone=UTC&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# HikariCP連接池配置 (Spring Boot默認(rèn)使用HikariCP)
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000

或者使用 YAML 格式:

# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/springboot_jdbc?useSSL=false&serverTimezone=UTC&characterEncoding=utf8
username: root
password:123456
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size:10
minimum-idle:5
idle-timeout:600000
max-lifetime:1800000
connection-timeout:30000

3. 創(chuàng)建實體類

importlombok.Data;

@Data
publicclassUser{
privateInteger id;
privateString name;
privateInteger age;
privateString email;

// 無參構(gòu)造和有參構(gòu)造會被Lombok自動生成
}

4. 創(chuàng)建 Repository (DAO)

importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.jdbc.core.BeanPropertyRowMapper;
importorg.springframework.jdbc.core.JdbcTemplate;
importorg.springframework.jdbc.core.RowMapper;
importorg.springframework.stereotype.Repository;

importjava.util.List;

@Repository
publicclassUserRepository{

privatefinalJdbcTemplate jdbcTemplate;

@Autowired
publicUserRepository(JdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}

// 創(chuàng)建表
publicvoidcreateTable(){
String sql ="CREATE TABLE IF NOT EXISTS users ("+
"id INT PRIMARY KEY AUTO_INCREMENT,"+
"name VARCHAR(50) NOT NULL,"+
"age INT,"+
"email VARCHAR(100)"+
")";
        jdbcTemplate.execute(sql);
}

// 添加用戶
publicintsave(User user){
String sql ="INSERT INTO users(name, age, email) VALUES(?, ?, ?)";
return jdbcTemplate.update(sql, user.getName(), user.getAge(), user.getEmail());
}

// 批量添加用戶
publicint[]batchSave(List<User> users){
String sql ="INSERT INTO users(name, age, email) VALUES(?, ?, ?)";
return jdbcTemplate.batchUpdate(sql, users, users.size(),
(ps, user)->{
                ps.setString(1, user.getName());
                ps.setInt(2, user.getAge());
                ps.setString(3, user.getEmail());
});
}

// 更新用戶
publicintupdate(User user){
String sql ="UPDATE users SET name=?, age=?, email=? WHERE id=?";
return jdbcTemplate.update(sql, user.getName(), user.getAge(), user.getEmail(), user.getId());
}

// 刪除用戶
publicintdeleteById(Integer id){
String sql ="DELETE FROM users WHERE id=?";
return jdbcTemplate.update(sql, id);
}

// 根據(jù)ID查詢用戶
publicUserfindById(Integer id){
String sql ="SELECT * FROM users WHERE id=?";
RowMapper<User> rowMapper =newBeanPropertyRowMapper<>(User.class);
return jdbcTemplate.queryForObject(sql, rowMapper, id);
}

// 查詢所有用戶
publicList<User>findAll(){
String sql ="SELECT * FROM users";
RowMapper<User> rowMapper =newBeanPropertyRowMapper<>(User.class);
return jdbcTemplate.query(sql, rowMapper);
}

// 根據(jù)名稱查詢用戶
publicList<User>findByName(String name){
String sql ="SELECT * FROM users WHERE name LIKE ?";
RowMapper<User> rowMapper =newBeanPropertyRowMapper<>(User.class);
return jdbcTemplate.query(sql, rowMapper,"%"+ name +"%");
}

// 查詢用戶數(shù)量
publicIntegercount(){
String sql ="SELECT COUNT(*) FROM users";
return jdbcTemplate.queryForObject(sql,Integer.class);
}
}

5. 創(chuàng)建 Service 層

importorg.springframework.stereotype.Service;
importorg.springframework.transaction.annotation.Transactional;

importjava.util.List;

@Service
publicclassUserService{

privatefinalUserRepository userRepository;

publicUserService(UserRepository userRepository){
this.userRepository = userRepository;
}

// 初始化表
publicvoidinitTable(){
        userRepository.createTable();
}

// 保存用戶
publicintsave(User user){
return userRepository.save(user);
}

// 批量保存用戶
@Transactional
publicint[]batchSave(List<User> users){
return userRepository.batchSave(users);
}

// 更新用戶
publicintupdate(User user){
return userRepository.update(user);
}

// 刪除用戶
publicintdeleteById(Integer id){
return userRepository.deleteById(id);
}

// 根據(jù)ID查詢用戶
publicUserfindById(Integer id){
return userRepository.findById(id);
}

// 查詢所有用戶
publicList<User>findAll(){
return userRepository.findAll();
}

// 根據(jù)名稱查詢用戶
publicList<User>findByName(String name){
return userRepository.findByName(name);
}

// 查詢用戶數(shù)量
publicIntegercount(){
return userRepository.count();
}
}

6. 創(chuàng)建 Controller (可選)

importorg.springframework.web.bind.annotation.*;

importjava.util.List;

@RestController
@RequestMapping("/api/users")
publicclassUserController{

privatefinalUserService userService;

publicUserController(UserService userService){
this.userService = userService;
}

@PostMapping
publicintsave(@RequestBodyUser user){
return userService.save(user);
}

@PutMapping
publicintupdate(@RequestBodyUser user){
return userService.update(user);
}

@DeleteMapping("/{id}")
publicintdeleteById(@PathVariableInteger id){
return userService.deleteById(id);
}

@GetMapping("/{id}")
publicUserfindById(@PathVariableInteger id){
return userService.findById(id);
}

@GetMapping
publicList<User>findAll(){
return userService.findAll();
}

@GetMapping("/search")
publicList<User>findByName(@RequestParamString name){
return userService.findByName(name);
}

@GetMapping("/count")
publicIntegercount(){
return userService.count();
}
}

7. 測試代碼

7.1 單元測試

importorg.junit.jupiter.api.BeforeEach;
importorg.junit.jupiter.api.Test;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.context.SpringBootTest;

importjava.util.Arrays;
importjava.util.List;

importstaticorg.junit.jupiter.api.Assertions.*;

@SpringBootTest
classUserServiceTest{

@Autowired
privateUserService userService;

@BeforeEach
voidsetUp(){
        userService.initTable();
}

@Test
voidtestCRUD(){
// 測試保存
User user =newUser();
        user.setName("張三");
        user.setAge(25);
        user.setEmail("zhangsan@example.com");
int result = userService.save(user);
assertEquals(1, result);

// 測試查詢
List<User> users = userService.findAll();
assertFalse(users.isEmpty());
assertEquals("張三", users.get(0).getName());

// 測試更新
User updatedUser = users.get(0);
        updatedUser.setName("李四");
        result = userService.update(updatedUser);
assertEquals(1, result);

// 驗證更新
User foundUser = userService.findById(updatedUser.getId());
assertEquals("李四", foundUser.getName());

// 測試刪除
        result = userService.deleteById(foundUser.getId());
assertEquals(1, result);

// 驗證刪除
assertEquals(0, userService.count());
}

@Test
voidtestBatchSave(){
List<User> users =Arrays.asList(
newUser(null,"張三",25,"zhangsan@example.com"),
newUser(null,"李四",30,"lisi@example.com"),
newUser(null,"王五",28,"wangwu@example.com")
);

int[] results = userService.batchSave(users);
assertEquals(3, results.length);
assertEquals(1, results[0]);

assertEquals(3, userService.count());
}
}

7.2 主程序測試

importorg.springframework.boot.CommandLineRunner;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importorg.springframework.context.annotation.Bean;

importjava.util.Arrays;

@SpringBootApplication
publicclassJdbcTemplateDemoApplication{

publicstaticvoidmain(String[] args){
SpringApplication.run(JdbcTemplateDemoApplication.class, args);
}

@Bean
publicCommandLineRunnerdemo(UserService userService){
return args ->{
// 初始化表
            userService.initTable();

// 添加單個用戶
User user1 =newUser();
            user1.setName("張三");
            user1.setAge(25);
            user1.setEmail("zhangsan@example.com");
            userService.save(user1);

// 批量添加用戶
List<User> users =Arrays.asList(
newUser(null,"李四",30,"lisi@example.com"),
newUser(null,"王五",28,"wangwu@example.com")
);
            userService.batchSave(users);

// 查詢所有用戶
System.out.println("所有用戶:");
            userService.findAll().forEach(System.out::println);

// 查詢用戶數(shù)量
System.out.println("用戶總數(shù): "+ userService.count());
};
}
}

8. 高級特性

8.1 使用 NamedParameterJdbcTemplate

對于命名參數(shù)的支持:

importorg.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
importorg.springframework.jdbc.core.namedparam.MapSqlParameterSource;
importorg.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
importorg.springframework.jdbc.core.namedparam.SqlParameterSource;
importorg.springframework.stereotype.Repository;

importjava.util.List;

@Repository
publicclassUserNamedParameterRepository{

privatefinalNamedParameterJdbcTemplate namedParameterJdbcTemplate;

publicUserNamedParameterRepository(NamedParameterJdbcTemplate namedParameterJdbcTemplate){
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
}

// 使用命名參數(shù)添加用戶
publicintsave(User user){
String sql ="INSERT INTO users(name, age, email) VALUES(:name, :age, :email)";
SqlParameterSource paramSource =newBeanPropertySqlParameterSource(user);
return namedParameterJdbcTemplate.update(sql, paramSource);
}

// 使用命名參數(shù)批量添加
publicint[]batchSave(List<User> users){
String sql ="INSERT INTO users(name, age, email) VALUES(:name, :age, :email)";
SqlParameterSource[] batchParams = users.stream()
.map(BeanPropertySqlParameterSource::new)
.toArray(SqlParameterSource[]::new);
return namedParameterJdbcTemplate.batchUpdate(sql, batchParams);
}

// 使用命名參數(shù)查詢
publicList<User>findByNameAndAge(String name,Integer age){
String sql ="SELECT * FROM users WHERE name LIKE :name AND age > :age";
SqlParameterSource paramSource =newMapSqlParameterSource()
.addValue("name","%"+ name +"%")
.addValue("age", age);
return namedParameterJdbcTemplate.query(sql, paramSource,
newBeanPropertyRowMapper<>(User.class));
}
}

8.2 自定義 RowMapper

importorg.springframework.jdbc.core.RowMapper;

importjava.sql.ResultSet;
importjava.sql.SQLException;

publicclassUserRowMapperimplementsRowMapper<User>{
@Override
publicUsermapRow(ResultSet rs,int rowNum)throwsSQLException{
User user =newUser();
        user.setId(rs.getInt("id"));
        user.setName(rs.getString("name"));
        user.setAge(rs.getInt("age"));
        user.setEmail(rs.getString("email"));
// 可以在這里進(jìn)行額外的處理,如數(shù)據(jù)轉(zhuǎn)換等
return user;
}
}

// 使用自定義RowMapper
publicList<User>findAllWithCustomMapper(){
String sql ="SELECT * FROM users";
return jdbcTemplate.query(sql,newUserRowMapper());
}


責(zé)任編輯:武曉燕 來源: Solomon肖哥彈架構(gòu)
相關(guān)推薦

2024-07-07 21:49:22

2022-02-07 07:48:17

MyBatisJavaORM

2024-03-27 10:14:48

2021-05-11 07:51:30

React ref 前端

2022-02-28 10:05:12

組件化架構(gòu)設(shè)計從原組件化模塊化

2025-06-30 04:15:00

2018-05-17 15:18:48

Logistic回歸算法機器學(xué)習(xí)

2025-04-02 07:29:14

2024-12-17 08:04:04

2024-12-12 09:00:28

2021-12-20 00:03:38

Webpack運行機制

2025-03-07 10:23:46

2025-03-17 01:55:00

TCP服務(wù)迭代

2024-03-08 10:50:44

Spring技術(shù)應(yīng)用程序

2024-07-15 09:58:03

OpenRestyNginx日志

2010-06-29 14:20:52

2024-09-18 08:25:46

2024-05-23 08:02:23

2025-06-03 00:00:04

VMware FT虛擬機服務(wù)器

2023-02-23 08:15:33

Spring異常處理機制
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 精品视频免费 | 欧美日韩国产不卡 | 2021天天躁夜夜看 | 精精国产xxxx视频在线播放7 | 免费一区二区 | 国产高清免费视频 | 黄网站色大毛片 | 视频一区二区中文字幕 | 国产乱码精品一区二区三区五月婷 | 男人天堂网址 | av在线播放不卡 | 国产不卡视频 | 久久av一区二区三区 | 99国产视频 | 欧美日韩免费在线 | 狠狠撸在线视频 | 六月婷婷久久 | 午夜免费观看体验区 | 日韩一区二区三区精品 | 中文字幕亚洲欧美日韩在线不卡 | 9久久精品| 国产成人av在线 | 日日草夜夜草 | 亚洲91视频 | 毛片.com| 午夜精品久久久久久久星辰影院 | 亚洲国产精品激情在线观看 | 国产福利视频导航 | 亚洲精品自在在线观看 | 亚洲日本视频 | 岛国视频| 亚洲精品乱码久久久久v最新版 | 日韩国产欧美视频 | 在线视频一区二区三区 | 欧美亚洲一区二区三区 | 亚洲精品中文字幕在线观看 | 成人在线视频免费看 | 九九色九九| 91在线第一页 | 欧美一区免费 | 成人一区av偷拍 |