1.8
diff --git a/2.1.x/chapter3-1/src/main/java/com/didispace/chapter31/Chapter31Application.java b/2.x/chapter3-1/src/main/java/com/didispace/chapter31/Chapter31Application.java
similarity index 100%
rename from 2.1.x/chapter3-1/src/main/java/com/didispace/chapter31/Chapter31Application.java
rename to 2.x/chapter3-1/src/main/java/com/didispace/chapter31/Chapter31Application.java
diff --git a/2.1.x/chapter3-1/src/main/java/com/didispace/chapter31/User.java b/2.x/chapter3-1/src/main/java/com/didispace/chapter31/User.java
similarity index 100%
rename from 2.1.x/chapter3-1/src/main/java/com/didispace/chapter31/User.java
rename to 2.x/chapter3-1/src/main/java/com/didispace/chapter31/User.java
diff --git a/2.1.x/chapter3-1/src/main/java/com/didispace/chapter31/UserService.java b/2.x/chapter3-1/src/main/java/com/didispace/chapter31/UserService.java
similarity index 100%
rename from 2.1.x/chapter3-1/src/main/java/com/didispace/chapter31/UserService.java
rename to 2.x/chapter3-1/src/main/java/com/didispace/chapter31/UserService.java
diff --git a/2.1.x/chapter3-1/src/main/java/com/didispace/chapter31/UserServiceImpl.java b/2.x/chapter3-1/src/main/java/com/didispace/chapter31/UserServiceImpl.java
similarity index 100%
rename from 2.1.x/chapter3-1/src/main/java/com/didispace/chapter31/UserServiceImpl.java
rename to 2.x/chapter3-1/src/main/java/com/didispace/chapter31/UserServiceImpl.java
diff --git a/2.1.x/chapter3-1/src/main/resources/application.properties b/2.x/chapter3-1/src/main/resources/application.properties
similarity index 100%
rename from 2.1.x/chapter3-1/src/main/resources/application.properties
rename to 2.x/chapter3-1/src/main/resources/application.properties
diff --git a/2.1.x/chapter3-1/src/test/java/com/didispace/chapter31/Chapter31ApplicationTests.java b/2.x/chapter3-1/src/test/java/com/didispace/chapter31/Chapter31ApplicationTests.java
similarity index 100%
rename from 2.1.x/chapter3-1/src/test/java/com/didispace/chapter31/Chapter31ApplicationTests.java
rename to 2.x/chapter3-1/src/test/java/com/didispace/chapter31/Chapter31ApplicationTests.java
diff --git a/2.1.x/chapter3-6/.gitignore b/2.x/chapter3-10/.gitignore
similarity index 100%
rename from 2.1.x/chapter3-6/.gitignore
rename to 2.x/chapter3-10/.gitignore
diff --git a/2.x/chapter3-10/pom.xml b/2.x/chapter3-10/pom.xml
new file mode 100644
index 00000000..72162203
--- /dev/null
+++ b/2.x/chapter3-10/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+
+ com.didispace
+ chapter3-10
+ 0.0.1-SNAPSHOT
+ 事务管理入门
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter3-10/src/main/java/com/didispace/chapter310/Chapter310Application.java b/2.x/chapter3-10/src/main/java/com/didispace/chapter310/Chapter310Application.java
new file mode 100644
index 00000000..72a7dd3e
--- /dev/null
+++ b/2.x/chapter3-10/src/main/java/com/didispace/chapter310/Chapter310Application.java
@@ -0,0 +1,25 @@
+package com.didispace.chapter310;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@SpringBootApplication
+public class Chapter310Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter310Application.class, args);
+ }
+
+ @RestController
+ static class TextController {
+
+ @GetMapping("/hello")
+ public String hello() {
+ return "hello world";
+ }
+
+ }
+
+}
diff --git a/2.x/chapter3-10/src/main/java/com/didispace/chapter310/User.java b/2.x/chapter3-10/src/main/java/com/didispace/chapter310/User.java
new file mode 100644
index 00000000..a2347ea8
--- /dev/null
+++ b/2.x/chapter3-10/src/main/java/com/didispace/chapter310/User.java
@@ -0,0 +1,27 @@
+package com.didispace.chapter310;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import javax.validation.constraints.Max;
+
+@Entity
+@Data
+@NoArgsConstructor
+public class User {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String name;
+ @Max(50)
+ private Integer age;
+
+ public User(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter3-10/src/main/java/com/didispace/chapter310/UserRepository.java b/2.x/chapter3-10/src/main/java/com/didispace/chapter310/UserRepository.java
new file mode 100644
index 00000000..366e1d21
--- /dev/null
+++ b/2.x/chapter3-10/src/main/java/com/didispace/chapter310/UserRepository.java
@@ -0,0 +1,22 @@
+package com.didispace.chapter310;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+/**
+ * Created by 程序猿DD/翟永超 on 2020/7/9.
+ *
+ * Blog: http://blog.didispace.com/
+ * Github: https://github.com/dyc87112/
+ */
+public interface UserRepository extends JpaRepository {
+
+ User findByName(String name);
+
+ User findByNameAndAge(String name, Integer age);
+
+ @Query("from User u where u.name=:name")
+ User findUser(@Param("name") String name);
+
+}
diff --git a/2.x/chapter3-10/src/main/resources/application.properties b/2.x/chapter3-10/src/main/resources/application.properties
new file mode 100644
index 00000000..7238387a
--- /dev/null
+++ b/2.x/chapter3-10/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+spring.datasource.url=jdbc:mysql://localhost:3306/test
+spring.datasource.username=root
+spring.datasource.password=12345678
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+
+spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
+spring.jpa.hibernate.ddl-auto=create
diff --git a/2.x/chapter3-10/src/test/java/com/didispace/chapter310/Chapter310ApplicationTests.java b/2.x/chapter3-10/src/test/java/com/didispace/chapter310/Chapter310ApplicationTests.java
new file mode 100644
index 00000000..02fee65b
--- /dev/null
+++ b/2.x/chapter3-10/src/test/java/com/didispace/chapter310/Chapter310ApplicationTests.java
@@ -0,0 +1,56 @@
+package com.didispace.chapter310;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+
+@Slf4j
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class Chapter310ApplicationTests {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Test
+ @Transactional
+ public void test() throws Exception {
+ // 创建10条记录
+ userRepository.save(new User("AAA", 10));
+ userRepository.save(new User("BBB", 20));
+ userRepository.save(new User("CCC", 30));
+ userRepository.save(new User("DDD", 40));
+ userRepository.save(new User("EEE", 50));
+ userRepository.save(new User("FFF", 60));
+ userRepository.save(new User("GGG", 70));
+ userRepository.save(new User("HHH", 80));
+ userRepository.save(new User("III", 90));
+ userRepository.save(new User("JJJ", 100));
+
+ // 测试findAll, 查询所有记录
+ Assert.assertEquals(10, userRepository.findAll().size());
+
+ // 测试findByName, 查询姓名为FFF的User
+ Assert.assertEquals(60, userRepository.findByName("FFF").getAge().longValue());
+
+ // 测试findUser, 查询姓名为FFF的User
+ Assert.assertEquals(60, userRepository.findUser("FFF").getAge().longValue());
+
+ // 测试findByNameAndAge, 查询姓名为FFF并且年龄为60的User
+ Assert.assertEquals("FFF", userRepository.findByNameAndAge("FFF", 60).getName());
+
+ // 测试删除姓名为AAA的User
+ userRepository.delete(userRepository.findByName("AAA"));
+
+ // 测试findAll, 查询所有记录, 验证上面的删除是否成功
+ Assert.assertEquals(9, userRepository.findAll().size());
+
+ }
+
+}
diff --git a/2.1.x/chapter4-1/.gitignore b/2.x/chapter3-11/.gitignore
similarity index 100%
rename from 2.1.x/chapter4-1/.gitignore
rename to 2.x/chapter3-11/.gitignore
diff --git a/2.x/chapter3-11/pom.xml b/2.x/chapter3-11/pom.xml
new file mode 100644
index 00000000..c9692e8d
--- /dev/null
+++ b/2.x/chapter3-11/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.4.1
+
+
+
+ com.didispace
+ chapter3-11
+ 0.0.1-SNAPSHOT
+ 使用Flyway管理数据库版本
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.flywaydb
+ flyway-core
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter3-11/src/main/java/com/didispace/chapter311/Chapter311Application.java b/2.x/chapter3-11/src/main/java/com/didispace/chapter311/Chapter311Application.java
new file mode 100644
index 00000000..9273268c
--- /dev/null
+++ b/2.x/chapter3-11/src/main/java/com/didispace/chapter311/Chapter311Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter311;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter311Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter311Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter3-11/src/main/java/com/didispace/chapter311/User.java b/2.x/chapter3-11/src/main/java/com/didispace/chapter311/User.java
new file mode 100644
index 00000000..1ca17f9c
--- /dev/null
+++ b/2.x/chapter3-11/src/main/java/com/didispace/chapter311/User.java
@@ -0,0 +1,14 @@
+package com.didispace.chapter311;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+public class User {
+
+ private Long id;
+ private String name;
+ private Integer age;
+
+}
\ No newline at end of file
diff --git a/2.x/chapter3-11/src/main/java/com/didispace/chapter311/UserService.java b/2.x/chapter3-11/src/main/java/com/didispace/chapter311/UserService.java
new file mode 100644
index 00000000..d5591de0
--- /dev/null
+++ b/2.x/chapter3-11/src/main/java/com/didispace/chapter311/UserService.java
@@ -0,0 +1,40 @@
+package com.didispace.chapter311;
+
+import java.util.List;
+
+public interface UserService {
+
+ /**
+ * 新增一个用户
+ *
+ * @param name
+ * @param age
+ */
+ int create(String name, Integer age);
+
+ /**
+ * 根据name查询用户
+ *
+ * @param name
+ * @return
+ */
+ List getByName(String name);
+
+ /**
+ * 根据name删除用户
+ *
+ * @param name
+ */
+ int deleteByName(String name);
+
+ /**
+ * 获取用户总量
+ */
+ int getAllUsers();
+
+ /**
+ * 删除所有用户
+ */
+ int deleteAllUsers();
+
+}
\ No newline at end of file
diff --git a/2.x/chapter3-11/src/main/java/com/didispace/chapter311/UserServiceImpl.java b/2.x/chapter3-11/src/main/java/com/didispace/chapter311/UserServiceImpl.java
new file mode 100644
index 00000000..54aa40fe
--- /dev/null
+++ b/2.x/chapter3-11/src/main/java/com/didispace/chapter311/UserServiceImpl.java
@@ -0,0 +1,49 @@
+package com.didispace.chapter311;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class UserServiceImpl implements UserService {
+
+ private JdbcTemplate jdbcTemplate;
+
+ UserServiceImpl(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ @Override
+ public int create(String name, Integer age) {
+ return jdbcTemplate.update("insert into USER(NAME, AGE) values(?, ?)", name, age);
+ }
+
+ @Override
+ public List getByName(String name) {
+ List users = jdbcTemplate.query("select * from USER where NAME = ?", (resultSet, i) -> {
+ User user = new User();
+ user.setId(resultSet.getLong("ID"));
+ user.setName(resultSet.getString("NAME"));
+ user.setAge(resultSet.getInt("AGE"));
+ return user;
+ }, name);
+ return users;
+ }
+
+ @Override
+ public int deleteByName(String name) {
+ return jdbcTemplate.update("delete from USER where NAME = ?", name);
+ }
+
+ @Override
+ public int getAllUsers() {
+ return jdbcTemplate.queryForObject("select count(1) from USER", Integer.class);
+ }
+
+ @Override
+ public int deleteAllUsers() {
+ return jdbcTemplate.update("delete from USER");
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter3-11/src/main/resources/application.properties b/2.x/chapter3-11/src/main/resources/application.properties
new file mode 100644
index 00000000..b36e87bd
--- /dev/null
+++ b/2.x/chapter3-11/src/main/resources/application.properties
@@ -0,0 +1,6 @@
+spring.datasource.url=jdbc:mysql://localhost:3306/test
+spring.datasource.username=root
+spring.datasource.password=12345678
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+
+spring.flyway.locations=classpath:db/migration
\ No newline at end of file
diff --git a/2.x/chapter3-11/src/main/resources/db/migration/V1_1__alter_table_user.sql b/2.x/chapter3-11/src/main/resources/db/migration/V1_1__alter_table_user.sql
new file mode 100644
index 00000000..667486c5
--- /dev/null
+++ b/2.x/chapter3-11/src/main/resources/db/migration/V1_1__alter_table_user.sql
@@ -0,0 +1 @@
+ALTER TABLE `user` ADD COLUMN `address` VARCHAR(20) DEFAULT NULL;
diff --git a/2.x/chapter3-11/src/main/resources/db/migration/V1__Base_version.sql b/2.x/chapter3-11/src/main/resources/db/migration/V1__Base_version.sql
new file mode 100644
index 00000000..428f2187
--- /dev/null
+++ b/2.x/chapter3-11/src/main/resources/db/migration/V1__Base_version.sql
@@ -0,0 +1,7 @@
+DROP TABLE IF EXISTS user ;
+CREATE TABLE `user` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `name` varchar(20) NOT NULL COMMENT '姓名',
+ `age` int(5) DEFAULT NULL COMMENT '年龄',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
diff --git a/2.x/chapter3-11/src/test/java/com/didispace/chapter311/Chapter311ApplicationTests.java b/2.x/chapter3-11/src/test/java/com/didispace/chapter311/Chapter311ApplicationTests.java
new file mode 100644
index 00000000..4b902ab9
--- /dev/null
+++ b/2.x/chapter3-11/src/test/java/com/didispace/chapter311/Chapter311ApplicationTests.java
@@ -0,0 +1,45 @@
+package com.didispace.chapter311;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.List;
+
+@Slf4j
+@SpringBootTest
+public class Chapter311ApplicationTests {
+
+ @Autowired
+ private UserService userSerivce;
+
+ @Test
+ public void test() throws Exception {
+ userSerivce.deleteAllUsers();
+
+ // 插入5个用户
+ userSerivce.create("Tom", 10);
+ userSerivce.create("Mike", 11);
+ userSerivce.create("Didispace", 30);
+ userSerivce.create("Oscar", 21);
+ userSerivce.create("Linda", 17);
+
+ // 查询名为Oscar的用户,判断年龄是否匹配
+ List userList = userSerivce.getByName("Oscar");
+ Assertions.assertEquals(21, userList.get(0).getAge().intValue());
+
+ // 查数据库,应该有5个用户
+ Assertions.assertEquals(5, userSerivce.getAllUsers());
+
+ // 删除两个用户
+ userSerivce.deleteByName("Tom");
+ userSerivce.deleteByName("Mike");
+
+ // 查数据库,应该有5个用户
+ Assertions.assertEquals(3, userSerivce.getAllUsers());
+
+ }
+
+}
diff --git a/2.1.x/chapter4-2/.gitignore b/2.x/chapter3-12/.gitignore
similarity index 100%
rename from 2.1.x/chapter4-2/.gitignore
rename to 2.x/chapter3-12/.gitignore
diff --git a/2.x/chapter3-12/pom.xml b/2.x/chapter3-12/pom.xml
new file mode 100644
index 00000000..a61772d3
--- /dev/null
+++ b/2.x/chapter3-12/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.4.2
+
+
+
+ com.didispace
+ chapter3-12
+ 0.0.1-SNAPSHOT
+ 使用JTA实现多数据源的事务
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jta-atomikos
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter3-12/src/main/java/com/didispace/chapter312/Chapter312Application.java b/2.x/chapter3-12/src/main/java/com/didispace/chapter312/Chapter312Application.java
new file mode 100644
index 00000000..325ef162
--- /dev/null
+++ b/2.x/chapter3-12/src/main/java/com/didispace/chapter312/Chapter312Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter312;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter312Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter312Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter3-12/src/main/java/com/didispace/chapter312/DataSourceConfiguration.java b/2.x/chapter3-12/src/main/java/com/didispace/chapter312/DataSourceConfiguration.java
new file mode 100644
index 00000000..8b71d643
--- /dev/null
+++ b/2.x/chapter3-12/src/main/java/com/didispace/chapter312/DataSourceConfiguration.java
@@ -0,0 +1,40 @@
+package com.didispace.chapter312;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import javax.sql.DataSource;
+
+@Configuration
+public class DataSourceConfiguration {
+
+ @Primary
+ @Bean
+ @ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.primary")
+ public DataSource primaryDataSource() {
+ return new AtomikosDataSourceBean();
+ }
+
+ @Bean
+ @ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.secondary")
+ public DataSource secondaryDataSource() {
+ return new AtomikosDataSourceBean();
+ }
+
+ @Bean
+ public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
+ return new JdbcTemplate(primaryDataSource);
+ }
+
+ @Bean
+ public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
+ return new JdbcTemplate(secondaryDataSource);
+ }
+
+}
diff --git a/2.x/chapter3-12/src/main/java/com/didispace/chapter312/TestService.java b/2.x/chapter3-12/src/main/java/com/didispace/chapter312/TestService.java
new file mode 100644
index 00000000..119241dc
--- /dev/null
+++ b/2.x/chapter3-12/src/main/java/com/didispace/chapter312/TestService.java
@@ -0,0 +1,34 @@
+package com.didispace.chapter312;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class TestService {
+
+ private JdbcTemplate primaryJdbcTemplate;
+ private JdbcTemplate secondaryJdbcTemplate;
+
+ public TestService(JdbcTemplate primaryJdbcTemplate, JdbcTemplate secondaryJdbcTemplate) {
+ this.primaryJdbcTemplate = primaryJdbcTemplate;
+ this.secondaryJdbcTemplate = secondaryJdbcTemplate;
+ }
+
+ @Transactional
+ public void tx() {
+ // 修改test1库中的数据
+ primaryJdbcTemplate.update("update user set age = ? where name = ?", 30, "aaa");
+ // 修改test2库中的数据
+ secondaryJdbcTemplate.update("update user set age = ? where name = ?", 30, "aaa");
+ }
+
+ @Transactional
+ public void tx2() {
+ // 修改test1库中的数据
+ primaryJdbcTemplate.update("update user set age = ? where name = ?", 40, "aaa");
+ // 模拟:修改test2库之前抛出异常
+ throw new RuntimeException();
+ }
+
+}
diff --git a/2.x/chapter3-12/src/main/resources/application.properties b/2.x/chapter3-12/src/main/resources/application.properties
new file mode 100644
index 00000000..312835d1
--- /dev/null
+++ b/2.x/chapter3-12/src/main/resources/application.properties
@@ -0,0 +1,31 @@
+spring.jta.enabled=true
+
+spring.jta.atomikos.datasource.primary.xa-properties.url=jdbc:mysql://localhost:3306/test1
+spring.jta.atomikos.datasource.primary.xa-properties.user=root
+spring.jta.atomikos.datasource.primary.xa-properties.password=12345678
+spring.jta.atomikos.datasource.primary.xa-data-source-class-name=com.mysql.cj.jdbc.MysqlXADataSource
+spring.jta.atomikos.datasource.primary.unique-resource-name=test1
+spring.jta.atomikos.datasource.primary.max-pool-size=25
+spring.jta.atomikos.datasource.primary.min-pool-size=3
+spring.jta.atomikos.datasource.primary.max-lifetime=20000
+spring.jta.atomikos.datasource.primary.borrow-connection-timeout=10000
+
+spring.jta.atomikos.datasource.secondary.xa-properties.url=jdbc:mysql://localhost:3306/test2
+spring.jta.atomikos.datasource.secondary.xa-properties.user=root
+spring.jta.atomikos.datasource.secondary.xa-properties.password=12345678
+spring.jta.atomikos.datasource.secondary.xa-data-source-class-name=com.mysql.cj.jdbc.MysqlXADataSource
+spring.jta.atomikos.datasource.secondary.unique-resource-name=test2
+spring.jta.atomikos.datasource.secondary.max-pool-size=25
+spring.jta.atomikos.datasource.secondary.min-pool-size=3
+spring.jta.atomikos.datasource.secondary.max-lifetime=20000
+spring.jta.atomikos.datasource.secondary.borrow-connection-timeout=10000
+
+#spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
+#spring.datasource.primary.username=root
+#spring.datasource.primary.password=12345678
+#spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
+#
+#spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
+#spring.datasource.secondary.username=root
+#spring.datasource.secondary.password=12345678
+#spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
\ No newline at end of file
diff --git a/2.x/chapter3-12/src/test/java/com/didispace/chapter312/Chapter312ApplicationTests.java b/2.x/chapter3-12/src/test/java/com/didispace/chapter312/Chapter312ApplicationTests.java
new file mode 100644
index 00000000..649b8b17
--- /dev/null
+++ b/2.x/chapter3-12/src/test/java/com/didispace/chapter312/Chapter312ApplicationTests.java
@@ -0,0 +1,45 @@
+package com.didispace.chapter312;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.transaction.annotation.Transactional;
+
+
+@SpringBootTest(classes = Chapter312Application.class)
+public class Chapter312ApplicationTests {
+
+ @Autowired
+ protected JdbcTemplate primaryJdbcTemplate;
+ @Autowired
+ protected JdbcTemplate secondaryJdbcTemplate;
+
+ @Autowired
+ private TestService testService;
+
+ @Test
+ public void test1() throws Exception {
+ // 正确更新的情况
+ testService.tx();
+ Assertions.assertEquals(30, primaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
+ Assertions.assertEquals(30, secondaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
+ }
+
+ @Test
+ public void test2() throws Exception {
+ // 更新失败的情况
+ try {
+ testService.tx2();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ // 部分更新失败,test1中的更新应该回滚
+ Assertions.assertEquals(30, primaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
+ Assertions.assertEquals(30, secondaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
+ }
+ }
+
+}
diff --git a/2.x/chapter3-13/.gitignore b/2.x/chapter3-13/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter3-13/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.x/chapter3-13/pom.xml b/2.x/chapter3-13/pom.xml
new file mode 100644
index 00000000..de7746d3
--- /dev/null
+++ b/2.x/chapter3-13/pom.xml
@@ -0,0 +1,59 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.0
+
+
+
+ com.didispace
+ chapter3-13
+ 0.0.1-SNAPSHOT
+ 2.5版本之后的数据脚本初始化
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter3-13/src/main/java/com/didispace/chapter313/Chapter313Application.java b/2.x/chapter3-13/src/main/java/com/didispace/chapter313/Chapter313Application.java
new file mode 100644
index 00000000..88768410
--- /dev/null
+++ b/2.x/chapter3-13/src/main/java/com/didispace/chapter313/Chapter313Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter313;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter313Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter313Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter3-13/src/main/resources/application.properties b/2.x/chapter3-13/src/main/resources/application.properties
new file mode 100644
index 00000000..225ddd22
--- /dev/null
+++ b/2.x/chapter3-13/src/main/resources/application.properties
@@ -0,0 +1,15 @@
+spring.datasource.url=jdbc:mysql://localhost:3306/test
+spring.datasource.username=root
+spring.datasource.password=
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+
+# Spring Boot 2.5.0 init schema & data
+spring.sql.init.username=root
+spring.sql.init.password=
+spring.sql.init.schema-locations=classpath*:schema-all.sql
+#spring.sql.init.enabled=true
+#spring.sql.init.data-locations=classpath*:
+#spring.sql.init.encoding=UTF-8
+#spring.sql.init.separator=;
+#spring.sql.init.continue-on-error=true
+
diff --git a/2.x/chapter3-13/src/main/resources/schema-all.sql b/2.x/chapter3-13/src/main/resources/schema-all.sql
new file mode 100644
index 00000000..cdbe26c1
--- /dev/null
+++ b/2.x/chapter3-13/src/main/resources/schema-all.sql
@@ -0,0 +1,18 @@
+create table test.user_info
+(
+ id int unsigned auto_increment comment '用户id'
+ primary key,
+ open_id varchar(255) default '' null comment '微信小程序openid',
+ nick_name varchar(255) default '' null comment '微信名',
+ head_img varchar(255) default '' null comment '微信头像',
+ sex varchar(255) default '' null comment '性别',
+ phone varchar(255) default '' null comment '手机',
+ province varchar(255) default '' null comment '注册地址:省',
+ city varchar(255) default '' null comment '注册地址:城市',
+ country varchar(255) default '' null comment '注册地址:县/区',
+ status tinyint unsigned default 0 not null comment '是否标记删除 0:否 1:是',
+ create_time datetime not null comment '创建时间',
+ update_time datetime not null comment '更新时间'
+)
+ comment '用户表';
+
diff --git a/2.x/chapter3-13/src/test/java/com/didispace/chapter31/Chapter31ApplicationTests.java b/2.x/chapter3-13/src/test/java/com/didispace/chapter31/Chapter31ApplicationTests.java
new file mode 100644
index 00000000..e65f6029
--- /dev/null
+++ b/2.x/chapter3-13/src/test/java/com/didispace/chapter31/Chapter31ApplicationTests.java
@@ -0,0 +1,17 @@
+package com.didispace.chapter31;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+
+@SpringBootTest
+public class Chapter31ApplicationTests {
+
+
+ @Test
+ public void test() throws Exception {
+
+
+ }
+
+}
diff --git a/2.x/chapter3-2/.gitignore b/2.x/chapter3-2/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter3-2/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.1.x/chapter3-2/pom.xml b/2.x/chapter3-2/pom.xml
similarity index 95%
rename from 2.1.x/chapter3-2/pom.xml
rename to 2.x/chapter3-2/pom.xml
index 2de383a2..d3a5f35d 100644
--- a/2.1.x/chapter3-2/pom.xml
+++ b/2.x/chapter3-2/pom.xml
@@ -13,6 +13,7 @@
com.didispace
chapter3-2
0.0.1-SNAPSHOT
+ 默认数据源Hikari的配置详解
1.8
diff --git a/2.1.x/chapter3-2/src/main/java/com/didispace/chapter32/Chapter32Application.java b/2.x/chapter3-2/src/main/java/com/didispace/chapter32/Chapter32Application.java
similarity index 100%
rename from 2.1.x/chapter3-2/src/main/java/com/didispace/chapter32/Chapter32Application.java
rename to 2.x/chapter3-2/src/main/java/com/didispace/chapter32/Chapter32Application.java
diff --git a/2.1.x/chapter3-2/src/main/java/com/didispace/chapter32/User.java b/2.x/chapter3-2/src/main/java/com/didispace/chapter32/User.java
similarity index 100%
rename from 2.1.x/chapter3-2/src/main/java/com/didispace/chapter32/User.java
rename to 2.x/chapter3-2/src/main/java/com/didispace/chapter32/User.java
diff --git a/2.1.x/chapter3-2/src/main/java/com/didispace/chapter32/UserService.java b/2.x/chapter3-2/src/main/java/com/didispace/chapter32/UserService.java
similarity index 100%
rename from 2.1.x/chapter3-2/src/main/java/com/didispace/chapter32/UserService.java
rename to 2.x/chapter3-2/src/main/java/com/didispace/chapter32/UserService.java
diff --git a/2.1.x/chapter3-2/src/main/java/com/didispace/chapter32/UserServiceImpl.java b/2.x/chapter3-2/src/main/java/com/didispace/chapter32/UserServiceImpl.java
similarity index 100%
rename from 2.1.x/chapter3-2/src/main/java/com/didispace/chapter32/UserServiceImpl.java
rename to 2.x/chapter3-2/src/main/java/com/didispace/chapter32/UserServiceImpl.java
diff --git a/2.1.x/chapter3-2/src/main/resources/application.properties b/2.x/chapter3-2/src/main/resources/application.properties
similarity index 100%
rename from 2.1.x/chapter3-2/src/main/resources/application.properties
rename to 2.x/chapter3-2/src/main/resources/application.properties
diff --git a/2.1.x/chapter3-2/src/test/java/com/didispace/chapter32/Chapter32ApplicationTests.java b/2.x/chapter3-2/src/test/java/com/didispace/chapter32/Chapter32ApplicationTests.java
similarity index 100%
rename from 2.1.x/chapter3-2/src/test/java/com/didispace/chapter32/Chapter32ApplicationTests.java
rename to 2.x/chapter3-2/src/test/java/com/didispace/chapter32/Chapter32ApplicationTests.java
diff --git a/2.x/chapter3-3/.gitignore b/2.x/chapter3-3/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter3-3/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.1.x/chapter3-3/pom.xml b/2.x/chapter3-3/pom.xml
similarity index 96%
rename from 2.1.x/chapter3-3/pom.xml
rename to 2.x/chapter3-3/pom.xml
index c83eddc6..63a0dbe3 100644
--- a/2.1.x/chapter3-3/pom.xml
+++ b/2.x/chapter3-3/pom.xml
@@ -13,6 +13,7 @@
com.didispace
chapter3-3
0.0.1-SNAPSHOT
+ 使用国产数据库连接池Druid
1.8
diff --git a/2.1.x/chapter3-3/src/main/java/com/didispace/chapter33/Chapter33Application.java b/2.x/chapter3-3/src/main/java/com/didispace/chapter33/Chapter33Application.java
similarity index 100%
rename from 2.1.x/chapter3-3/src/main/java/com/didispace/chapter33/Chapter33Application.java
rename to 2.x/chapter3-3/src/main/java/com/didispace/chapter33/Chapter33Application.java
diff --git a/2.1.x/chapter3-3/src/main/java/com/didispace/chapter33/User.java b/2.x/chapter3-3/src/main/java/com/didispace/chapter33/User.java
similarity index 100%
rename from 2.1.x/chapter3-3/src/main/java/com/didispace/chapter33/User.java
rename to 2.x/chapter3-3/src/main/java/com/didispace/chapter33/User.java
diff --git a/2.1.x/chapter3-3/src/main/java/com/didispace/chapter33/UserController.java b/2.x/chapter3-3/src/main/java/com/didispace/chapter33/UserController.java
similarity index 100%
rename from 2.1.x/chapter3-3/src/main/java/com/didispace/chapter33/UserController.java
rename to 2.x/chapter3-3/src/main/java/com/didispace/chapter33/UserController.java
diff --git a/2.1.x/chapter3-3/src/main/java/com/didispace/chapter33/UserService.java b/2.x/chapter3-3/src/main/java/com/didispace/chapter33/UserService.java
similarity index 100%
rename from 2.1.x/chapter3-3/src/main/java/com/didispace/chapter33/UserService.java
rename to 2.x/chapter3-3/src/main/java/com/didispace/chapter33/UserService.java
diff --git a/2.1.x/chapter3-3/src/main/java/com/didispace/chapter33/UserServiceImpl.java b/2.x/chapter3-3/src/main/java/com/didispace/chapter33/UserServiceImpl.java
similarity index 100%
rename from 2.1.x/chapter3-3/src/main/java/com/didispace/chapter33/UserServiceImpl.java
rename to 2.x/chapter3-3/src/main/java/com/didispace/chapter33/UserServiceImpl.java
diff --git a/2.1.x/chapter3-3/src/main/resources/application.properties b/2.x/chapter3-3/src/main/resources/application.properties
similarity index 100%
rename from 2.1.x/chapter3-3/src/main/resources/application.properties
rename to 2.x/chapter3-3/src/main/resources/application.properties
diff --git a/2.1.x/chapter3-3/src/test/java/com/didispace/chapter33/Chapter33ApplicationTests.java b/2.x/chapter3-3/src/test/java/com/didispace/chapter33/Chapter33ApplicationTests.java
similarity index 100%
rename from 2.1.x/chapter3-3/src/test/java/com/didispace/chapter33/Chapter33ApplicationTests.java
rename to 2.x/chapter3-3/src/test/java/com/didispace/chapter33/Chapter33ApplicationTests.java
diff --git a/2.x/chapter3-4/.gitignore b/2.x/chapter3-4/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter3-4/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.1.x/chapter3-4/pom.xml b/2.x/chapter3-4/pom.xml
similarity index 96%
rename from 2.1.x/chapter3-4/pom.xml
rename to 2.x/chapter3-4/pom.xml
index 602beb6d..d529c02b 100644
--- a/2.1.x/chapter3-4/pom.xml
+++ b/2.x/chapter3-4/pom.xml
@@ -13,6 +13,7 @@
com.didispace
chapter3-4
0.0.1-SNAPSHOT
+ 使用Spring Data JPA访问MySQL
1.8
diff --git a/2.1.x/chapter3-4/src/main/java/com/didispace/chapter34/Chapter34Application.java b/2.x/chapter3-4/src/main/java/com/didispace/chapter34/Chapter34Application.java
similarity index 100%
rename from 2.1.x/chapter3-4/src/main/java/com/didispace/chapter34/Chapter34Application.java
rename to 2.x/chapter3-4/src/main/java/com/didispace/chapter34/Chapter34Application.java
diff --git a/2.1.x/chapter3-4/src/main/java/com/didispace/chapter34/User.java b/2.x/chapter3-4/src/main/java/com/didispace/chapter34/User.java
similarity index 100%
rename from 2.1.x/chapter3-4/src/main/java/com/didispace/chapter34/User.java
rename to 2.x/chapter3-4/src/main/java/com/didispace/chapter34/User.java
diff --git a/2.1.x/chapter3-4/src/main/java/com/didispace/chapter34/UserRepository.java b/2.x/chapter3-4/src/main/java/com/didispace/chapter34/UserRepository.java
similarity index 100%
rename from 2.1.x/chapter3-4/src/main/java/com/didispace/chapter34/UserRepository.java
rename to 2.x/chapter3-4/src/main/java/com/didispace/chapter34/UserRepository.java
diff --git a/2.1.x/chapter3-4/src/main/resources/application.properties b/2.x/chapter3-4/src/main/resources/application.properties
similarity index 100%
rename from 2.1.x/chapter3-4/src/main/resources/application.properties
rename to 2.x/chapter3-4/src/main/resources/application.properties
diff --git a/2.1.x/chapter3-4/src/test/java/com/didispace/chapter34/Chapter34ApplicationTests.java b/2.x/chapter3-4/src/test/java/com/didispace/chapter34/Chapter34ApplicationTests.java
similarity index 100%
rename from 2.1.x/chapter3-4/src/test/java/com/didispace/chapter34/Chapter34ApplicationTests.java
rename to 2.x/chapter3-4/src/test/java/com/didispace/chapter34/Chapter34ApplicationTests.java
diff --git a/2.x/chapter3-5/.gitignore b/2.x/chapter3-5/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter3-5/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.1.x/chapter3-5/pom.xml b/2.x/chapter3-5/pom.xml
similarity index 96%
rename from 2.1.x/chapter3-5/pom.xml
rename to 2.x/chapter3-5/pom.xml
index 2cb4f499..43bfeb2a 100644
--- a/2.1.x/chapter3-5/pom.xml
+++ b/2.x/chapter3-5/pom.xml
@@ -13,6 +13,7 @@
com.didispace
chapter3-5
0.0.1-SNAPSHOT
+ 使用MyBatis访问MySQL
1.8
diff --git a/2.1.x/chapter3-5/src/main/java/com/didispace/chapter35/Chapter35Application.java b/2.x/chapter3-5/src/main/java/com/didispace/chapter35/Chapter35Application.java
similarity index 100%
rename from 2.1.x/chapter3-5/src/main/java/com/didispace/chapter35/Chapter35Application.java
rename to 2.x/chapter3-5/src/main/java/com/didispace/chapter35/Chapter35Application.java
diff --git a/2.1.x/chapter3-5/src/main/java/com/didispace/chapter35/User.java b/2.x/chapter3-5/src/main/java/com/didispace/chapter35/User.java
similarity index 100%
rename from 2.1.x/chapter3-5/src/main/java/com/didispace/chapter35/User.java
rename to 2.x/chapter3-5/src/main/java/com/didispace/chapter35/User.java
diff --git a/2.1.x/chapter3-5/src/main/java/com/didispace/chapter35/UserMapper.java b/2.x/chapter3-5/src/main/java/com/didispace/chapter35/UserMapper.java
similarity index 100%
rename from 2.1.x/chapter3-5/src/main/java/com/didispace/chapter35/UserMapper.java
rename to 2.x/chapter3-5/src/main/java/com/didispace/chapter35/UserMapper.java
diff --git a/2.1.x/chapter3-5/src/main/resources/application.properties b/2.x/chapter3-5/src/main/resources/application.properties
similarity index 100%
rename from 2.1.x/chapter3-5/src/main/resources/application.properties
rename to 2.x/chapter3-5/src/main/resources/application.properties
diff --git a/2.1.x/chapter3-5/src/test/java/com/didispace/chapter35/Chapter35ApplicationTests.java b/2.x/chapter3-5/src/test/java/com/didispace/chapter35/Chapter35ApplicationTests.java
similarity index 100%
rename from 2.1.x/chapter3-5/src/test/java/com/didispace/chapter35/Chapter35ApplicationTests.java
rename to 2.x/chapter3-5/src/test/java/com/didispace/chapter35/Chapter35ApplicationTests.java
diff --git a/2.x/chapter3-6/.gitignore b/2.x/chapter3-6/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter3-6/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.1.x/chapter3-6/pom.xml b/2.x/chapter3-6/pom.xml
similarity index 95%
rename from 2.1.x/chapter3-6/pom.xml
rename to 2.x/chapter3-6/pom.xml
index 2f515975..97869305 100644
--- a/2.1.x/chapter3-6/pom.xml
+++ b/2.x/chapter3-6/pom.xml
@@ -13,6 +13,7 @@
com.didispace
chapter3-6
0.0.1-SNAPSHOT
+ 使用MyBatis(xml配置方式)
1.8
diff --git a/2.1.x/chapter3-6/src/main/java/com/didispace/chapter36/Chapter36Application.java b/2.x/chapter3-6/src/main/java/com/didispace/chapter36/Chapter36Application.java
similarity index 100%
rename from 2.1.x/chapter3-6/src/main/java/com/didispace/chapter36/Chapter36Application.java
rename to 2.x/chapter3-6/src/main/java/com/didispace/chapter36/Chapter36Application.java
diff --git a/2.1.x/chapter3-6/src/main/java/com/didispace/chapter36/entity/User.java b/2.x/chapter3-6/src/main/java/com/didispace/chapter36/entity/User.java
similarity index 100%
rename from 2.1.x/chapter3-6/src/main/java/com/didispace/chapter36/entity/User.java
rename to 2.x/chapter3-6/src/main/java/com/didispace/chapter36/entity/User.java
diff --git a/2.1.x/chapter3-6/src/main/java/com/didispace/chapter36/mapper/UserMapper.java b/2.x/chapter3-6/src/main/java/com/didispace/chapter36/mapper/UserMapper.java
similarity index 100%
rename from 2.1.x/chapter3-6/src/main/java/com/didispace/chapter36/mapper/UserMapper.java
rename to 2.x/chapter3-6/src/main/java/com/didispace/chapter36/mapper/UserMapper.java
diff --git a/2.1.x/chapter3-6/src/main/resources/application.properties b/2.x/chapter3-6/src/main/resources/application.properties
similarity index 100%
rename from 2.1.x/chapter3-6/src/main/resources/application.properties
rename to 2.x/chapter3-6/src/main/resources/application.properties
diff --git a/2.1.x/chapter3-6/src/main/resources/mapper/UserMapper.xml b/2.x/chapter3-6/src/main/resources/mapper/UserMapper.xml
similarity index 100%
rename from 2.1.x/chapter3-6/src/main/resources/mapper/UserMapper.xml
rename to 2.x/chapter3-6/src/main/resources/mapper/UserMapper.xml
diff --git a/2.1.x/chapter3-6/src/test/java/com/didispace/chapter36/Chapter36ApplicationTests.java b/2.x/chapter3-6/src/test/java/com/didispace/chapter36/Chapter36ApplicationTests.java
similarity index 100%
rename from 2.1.x/chapter3-6/src/test/java/com/didispace/chapter36/Chapter36ApplicationTests.java
rename to 2.x/chapter3-6/src/test/java/com/didispace/chapter36/Chapter36ApplicationTests.java
diff --git a/2.x/chapter3-7/.gitignore b/2.x/chapter3-7/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter3-7/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.x/chapter3-7/pom.xml b/2.x/chapter3-7/pom.xml
new file mode 100644
index 00000000..589d40ec
--- /dev/null
+++ b/2.x/chapter3-7/pom.xml
@@ -0,0 +1,59 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+
+ com.didispace
+ chapter3-7
+ 0.0.1-SNAPSHOT
+ JdbcTemplate的多数据源配置
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter3-7/src/main/java/com/didispace/chapter37/Chapter37Application.java b/2.x/chapter3-7/src/main/java/com/didispace/chapter37/Chapter37Application.java
new file mode 100644
index 00000000..92be7068
--- /dev/null
+++ b/2.x/chapter3-7/src/main/java/com/didispace/chapter37/Chapter37Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter37;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter37Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter37Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter3-7/src/main/java/com/didispace/chapter37/DataSourceConfiguration.java b/2.x/chapter3-7/src/main/java/com/didispace/chapter37/DataSourceConfiguration.java
new file mode 100644
index 00000000..f821153b
--- /dev/null
+++ b/2.x/chapter3-7/src/main/java/com/didispace/chapter37/DataSourceConfiguration.java
@@ -0,0 +1,39 @@
+package com.didispace.chapter37;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import javax.sql.DataSource;
+
+@Configuration
+public class DataSourceConfiguration {
+
+ @Primary
+ @Bean
+ @ConfigurationProperties(prefix = "spring.datasource.primary")
+ public DataSource primaryDataSource() {
+ return DataSourceBuilder.create().build();
+ }
+
+ @Bean
+ @ConfigurationProperties(prefix = "spring.datasource.secondary")
+ public DataSource secondaryDataSource() {
+ return DataSourceBuilder.create().build();
+ }
+
+ @Bean
+ public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
+ return new JdbcTemplate(primaryDataSource);
+ }
+
+ @Bean
+ public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
+ return new JdbcTemplate(secondaryDataSource);
+ }
+
+}
diff --git a/2.x/chapter3-7/src/main/resources/application.properties b/2.x/chapter3-7/src/main/resources/application.properties
new file mode 100644
index 00000000..25937c84
--- /dev/null
+++ b/2.x/chapter3-7/src/main/resources/application.properties
@@ -0,0 +1,11 @@
+# pring boot 1.x的配置:spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1
+spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
+spring.datasource.primary.username=root
+spring.datasource.primary.password=123456
+spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
+
+# spring boot 1.x的配置:spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2
+spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
+spring.datasource.secondary.username=root
+spring.datasource.secondary.password=123456
+spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
\ No newline at end of file
diff --git a/2.x/chapter3-7/src/test/java/com/didispace/chapter37/Chapter37ApplicationTests.java b/2.x/chapter3-7/src/test/java/com/didispace/chapter37/Chapter37ApplicationTests.java
new file mode 100644
index 00000000..5aa8a72f
--- /dev/null
+++ b/2.x/chapter3-7/src/test/java/com/didispace/chapter37/Chapter37ApplicationTests.java
@@ -0,0 +1,46 @@
+package com.didispace.chapter37;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.context.junit4.SpringRunner;
+
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class Chapter37ApplicationTests {
+
+ @Autowired
+ protected JdbcTemplate primaryJdbcTemplate;
+
+ @Autowired
+ protected JdbcTemplate secondaryJdbcTemplate;
+
+ @Before
+ public void setUp() {
+ primaryJdbcTemplate.update("DELETE FROM USER ");
+ secondaryJdbcTemplate.update("DELETE FROM USER ");
+ }
+
+ @Test
+ public void test() throws Exception {
+ // 往第一个数据源中插入 2 条数据
+ primaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "aaa", 20);
+ primaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "bbb", 30);
+
+ // 往第二个数据源中插入 1 条数据,若插入的是第一个数据源,则会主键冲突报错
+ secondaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "ccc", 20);
+
+ // 查一下第一个数据源中是否有 2 条数据,验证插入是否成功
+ Assert.assertEquals("2", primaryJdbcTemplate.queryForObject("select count(1) from user", String.class));
+
+ // 查一下第一个数据源中是否有 1 条数据,验证插入是否成功
+ Assert.assertEquals("1", secondaryJdbcTemplate.queryForObject("select count(1) from user", String.class));
+ }
+
+}
diff --git a/2.x/chapter3-8/.gitignore b/2.x/chapter3-8/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter3-8/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.x/chapter3-8/pom.xml b/2.x/chapter3-8/pom.xml
new file mode 100644
index 00000000..fcb9d03a
--- /dev/null
+++ b/2.x/chapter3-8/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+
+ com.didispace
+ chapter3-8
+ 0.0.1-SNAPSHOT
+ Spring Data JPA的多数据源配置
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter3-8/src/main/java/com/didispace/chapter38/Chapter38Application.java b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/Chapter38Application.java
new file mode 100644
index 00000000..d2e5f499
--- /dev/null
+++ b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/Chapter38Application.java
@@ -0,0 +1,15 @@
+package com.didispace.chapter38;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@SpringBootApplication
+public class Chapter38Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter38Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter3-8/src/main/java/com/didispace/chapter38/DataSourceConfiguration.java b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/DataSourceConfiguration.java
new file mode 100644
index 00000000..6470beb6
--- /dev/null
+++ b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/DataSourceConfiguration.java
@@ -0,0 +1,29 @@
+package com.didispace.chapter38;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import javax.sql.DataSource;
+
+@Configuration
+public class DataSourceConfiguration {
+
+ @Primary
+ @Bean
+ @ConfigurationProperties(prefix = "spring.datasource.primary")
+ public DataSource primaryDataSource() {
+ return DataSourceBuilder.create().build();
+ }
+
+ @Bean
+ @ConfigurationProperties(prefix = "spring.datasource.secondary")
+ public DataSource secondaryDataSource() {
+ return DataSourceBuilder.create().build();
+ }
+
+}
diff --git a/2.x/chapter3-8/src/main/java/com/didispace/chapter38/PrimaryConfig.java b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/PrimaryConfig.java
new file mode 100644
index 00000000..3bcfadc0
--- /dev/null
+++ b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/PrimaryConfig.java
@@ -0,0 +1,70 @@
+package com.didispace.chapter38;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
+import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
+import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.persistence.EntityManager;
+import javax.sql.DataSource;
+import java.util.Map;
+
+@Configuration
+@EnableTransactionManagement
+@EnableJpaRepositories(
+ entityManagerFactoryRef="entityManagerFactoryPrimary",
+ transactionManagerRef="transactionManagerPrimary",
+ basePackages= { "com.didispace.chapter38.p" }) //设置Repository所在位置
+public class PrimaryConfig {
+
+ @Autowired
+ @Qualifier("primaryDataSource")
+ private DataSource primaryDataSource;
+
+ @Autowired
+ private JpaProperties jpaProperties;
+ @Autowired
+ private HibernateProperties hibernateProperties;
+
+ private Map getVendorProperties() {
+ return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
+ }
+
+ @Primary
+ @Bean(name = "entityManagerPrimary")
+ public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
+ return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
+ }
+
+ @Primary
+ @Bean(name = "entityManagerFactoryPrimary")
+ public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
+// HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
+// jpaVendorAdapter.setGenerateDdl(true);
+ return builder
+ .dataSource(primaryDataSource)
+ .packages("com.didispace.chapter38.p") //设置实体类所在位置
+ .persistenceUnit("primaryPersistenceUnit")
+ .properties(getVendorProperties())
+ .build();
+ }
+
+ @Primary
+ @Bean(name = "transactionManagerPrimary")
+ public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
+ return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
+ }
+
+
+}
\ No newline at end of file
diff --git a/2.x/chapter3-8/src/main/java/com/didispace/chapter38/SecondaryConfig.java b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/SecondaryConfig.java
new file mode 100644
index 00000000..7b8df6a3
--- /dev/null
+++ b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/SecondaryConfig.java
@@ -0,0 +1,62 @@
+package com.didispace.chapter38;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
+import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
+import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.persistence.EntityManager;
+import javax.sql.DataSource;
+import java.util.Map;
+
+@Configuration
+@EnableTransactionManagement
+@EnableJpaRepositories(
+ entityManagerFactoryRef="entityManagerFactorySecondary",
+ transactionManagerRef="transactionManagerSecondary",
+ basePackages= { "com.didispace.chapter38.s" }) //设置Repository所在位置
+public class SecondaryConfig {
+
+ @Autowired
+ @Qualifier("secondaryDataSource")
+ private DataSource secondaryDataSource;
+
+ @Autowired
+ private JpaProperties jpaProperties;
+ @Autowired
+ private HibernateProperties hibernateProperties;
+
+ private Map getVendorProperties() {
+ return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
+ }
+
+ @Bean(name = "entityManagerSecondary")
+ public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
+ return entityManagerFactorySecondary(builder).getObject().createEntityManager();
+ }
+
+ @Bean(name = "entityManagerFactorySecondary")
+ public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {
+ return builder
+ .dataSource(secondaryDataSource)
+ .packages("com.didispace.chapter38.s") //设置实体类所在位置
+ .persistenceUnit("secondaryPersistenceUnit")
+ .properties(getVendorProperties())
+ .build();
+ }
+
+ @Bean(name = "transactionManagerSecondary")
+ PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
+ return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter3-8/src/main/java/com/didispace/chapter38/p/User.java b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/p/User.java
new file mode 100644
index 00000000..83aaf3c9
--- /dev/null
+++ b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/p/User.java
@@ -0,0 +1,27 @@
+package com.didispace.chapter38.p;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+@Data
+@NoArgsConstructor
+public class User {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String name;
+ private Integer age;
+
+ public User(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+}
\ No newline at end of file
diff --git a/2.x/chapter3-8/src/main/java/com/didispace/chapter38/p/UserRepository.java b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/p/UserRepository.java
new file mode 100644
index 00000000..e91080e1
--- /dev/null
+++ b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/p/UserRepository.java
@@ -0,0 +1,15 @@
+package com.didispace.chapter38.p;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+/**
+ * Created by 程序猿DD/翟永超 on 2020/6/22.
+ *
+ * Blog: http://blog.didispace.com/
+ * Github: https://github.com/dyc87112/
+ */
+public interface UserRepository extends JpaRepository {
+
+}
diff --git a/2.x/chapter3-8/src/main/java/com/didispace/chapter38/s/Message.java b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/s/Message.java
new file mode 100644
index 00000000..956178b8
--- /dev/null
+++ b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/s/Message.java
@@ -0,0 +1,29 @@
+package com.didispace.chapter38.s;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+@Data
+@NoArgsConstructor
+public class Message {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String title;
+ private String message;
+
+ public Message(String title, String message) {
+ this.title = title;
+ this.message = message;
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter3-8/src/main/java/com/didispace/chapter38/s/MessageRepository.java b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/s/MessageRepository.java
new file mode 100644
index 00000000..13360488
--- /dev/null
+++ b/2.x/chapter3-8/src/main/java/com/didispace/chapter38/s/MessageRepository.java
@@ -0,0 +1,14 @@
+package com.didispace.chapter38.s;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+/**
+ * Created by 程序猿DD/翟永超 on 2020/6/22.
+ *
+ * Blog: http://blog.didispace.com/
+ * Github: https://github.com/dyc87112/
+ */
+public interface MessageRepository extends JpaRepository {
+
+
+}
diff --git a/2.x/chapter3-8/src/main/resources/application.properties b/2.x/chapter3-8/src/main/resources/application.properties
new file mode 100644
index 00000000..0d82f6cd
--- /dev/null
+++ b/2.x/chapter3-8/src/main/resources/application.properties
@@ -0,0 +1,16 @@
+# pring boot 1.x的配置:spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1
+spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
+spring.datasource.primary.username=root
+spring.datasource.primary.password=12345678
+spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
+
+# spring boot 1.x的配置:spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2
+spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
+spring.datasource.secondary.username=root
+spring.datasource.secondary.password=12345678
+spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
+
+# 日志打印执行的SQL
+spring.jpa.show-sql=true
+# Hibernate的DDL策略
+spring.jpa.hibernate.ddl-auto=create-drop
diff --git a/2.x/chapter3-8/src/test/java/com/didispace/chapter38/Chapter38ApplicationTests.java b/2.x/chapter3-8/src/test/java/com/didispace/chapter38/Chapter38ApplicationTests.java
new file mode 100644
index 00000000..9c9ef3e7
--- /dev/null
+++ b/2.x/chapter3-8/src/test/java/com/didispace/chapter38/Chapter38ApplicationTests.java
@@ -0,0 +1,42 @@
+package com.didispace.chapter38;
+
+import com.didispace.chapter38.p.User;
+import com.didispace.chapter38.p.UserRepository;
+import com.didispace.chapter38.s.Message;
+import com.didispace.chapter38.s.MessageRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@Slf4j
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class Chapter38ApplicationTests {
+
+ @Autowired
+ private UserRepository userRepository;
+ @Autowired
+ private MessageRepository messageRepository;
+
+ @Test
+ public void test() throws Exception {
+ userRepository.save(new User("aaa", 10));
+ userRepository.save(new User("bbb", 20));
+ userRepository.save(new User("ccc", 30));
+ userRepository.save(new User("ddd", 40));
+ userRepository.save(new User("eee", 50));
+
+ Assert.assertEquals(5, userRepository.findAll().size());
+
+ messageRepository.save(new Message("o1", "aaaaaaaaaa"));
+ messageRepository.save(new Message("o2", "bbbbbbbbbb"));
+ messageRepository.save(new Message("o3", "cccccccccc"));
+
+ Assert.assertEquals(3, messageRepository.findAll().size());
+ }
+
+}
diff --git a/2.x/chapter3-9/.gitignore b/2.x/chapter3-9/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter3-9/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.x/chapter3-9/pom.xml b/2.x/chapter3-9/pom.xml
new file mode 100644
index 00000000..c8f731ef
--- /dev/null
+++ b/2.x/chapter3-9/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+
+ com.didispace
+ chapter3-9
+ 0.0.1-SNAPSHOT
+ MyBatis的多数据源配置
+
+
+ 1.8
+
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 2.1.1
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter3-9/src/main/java/com/didispace/chapter39/Chapter39Application.java b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/Chapter39Application.java
new file mode 100644
index 00000000..eb46b057
--- /dev/null
+++ b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/Chapter39Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter39;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter39Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter39Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter3-9/src/main/java/com/didispace/chapter39/DataSourceConfiguration.java b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/DataSourceConfiguration.java
new file mode 100644
index 00000000..6eaae095
--- /dev/null
+++ b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/DataSourceConfiguration.java
@@ -0,0 +1,27 @@
+package com.didispace.chapter39;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import javax.sql.DataSource;
+
+@Configuration
+public class DataSourceConfiguration {
+
+ @Primary
+ @Bean
+ @ConfigurationProperties(prefix = "spring.datasource.primary")
+ public DataSource primaryDataSource() {
+ return DataSourceBuilder.create().build();
+ }
+
+ @Bean
+ @ConfigurationProperties(prefix = "spring.datasource.secondary")
+ public DataSource secondaryDataSource() {
+ return DataSourceBuilder.create().build();
+ }
+
+}
diff --git a/2.x/chapter3-9/src/main/java/com/didispace/chapter39/PrimaryConfig.java b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/PrimaryConfig.java
new file mode 100644
index 00000000..f6d1bbe5
--- /dev/null
+++ b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/PrimaryConfig.java
@@ -0,0 +1,38 @@
+package com.didispace.chapter39;
+
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+
+@Configuration
+@MapperScan(
+ basePackages = "com.didispace.chapter39.p",
+ sqlSessionFactoryRef = "sqlSessionFactoryPrimary",
+ sqlSessionTemplateRef = "sqlSessionTemplatePrimary")
+public class PrimaryConfig {
+
+ private DataSource primaryDataSource;
+
+ public PrimaryConfig(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
+ this.primaryDataSource = primaryDataSource;
+ }
+
+ @Bean
+ public SqlSessionFactory sqlSessionFactoryPrimary() throws Exception {
+ SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
+ bean.setDataSource(primaryDataSource);
+ return bean.getObject();
+ }
+
+ @Bean
+ public SqlSessionTemplate sqlSessionTemplatePrimary() throws Exception {
+ return new SqlSessionTemplate(sqlSessionFactoryPrimary());
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter3-9/src/main/java/com/didispace/chapter39/SecondaryConfig.java b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/SecondaryConfig.java
new file mode 100644
index 00000000..bdb17fba
--- /dev/null
+++ b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/SecondaryConfig.java
@@ -0,0 +1,38 @@
+package com.didispace.chapter39;
+
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+
+@Configuration
+@MapperScan(
+ basePackages = "com.didispace.chapter39.s",
+ sqlSessionFactoryRef = "sqlSessionFactorySecondary",
+ sqlSessionTemplateRef = "sqlSessionTemplateSecondary")
+public class SecondaryConfig {
+
+ private DataSource secondaryDataSource;
+
+ public SecondaryConfig(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
+ this.secondaryDataSource = secondaryDataSource;
+ }
+
+ @Bean
+ public SqlSessionFactory sqlSessionFactorySecondary() throws Exception {
+ SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
+ bean.setDataSource(secondaryDataSource);
+ return bean.getObject();
+ }
+
+ @Bean
+ public SqlSessionTemplate sqlSessionTemplateSecondary() throws Exception {
+ return new SqlSessionTemplate(sqlSessionFactorySecondary());
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter3-9/src/main/java/com/didispace/chapter39/p/entity/UserPrimary.java b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/p/entity/UserPrimary.java
new file mode 100644
index 00000000..f4c2a299
--- /dev/null
+++ b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/p/entity/UserPrimary.java
@@ -0,0 +1,20 @@
+package com.didispace.chapter39.p.entity;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+@Data
+@NoArgsConstructor
+public class UserPrimary {
+
+ private Long id;
+
+ private String name;
+ private Integer age;
+
+ public UserPrimary(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+}
\ No newline at end of file
diff --git a/2.x/chapter3-9/src/main/java/com/didispace/chapter39/p/mapper/UserMapperPrimary.java b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/p/mapper/UserMapperPrimary.java
new file mode 100644
index 00000000..869ab546
--- /dev/null
+++ b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/p/mapper/UserMapperPrimary.java
@@ -0,0 +1,26 @@
+package com.didispace.chapter39.p.mapper;
+
+import com.didispace.chapter39.p.entity.UserPrimary;
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * Created by 程序猿DD/翟永超 on 2020/2/28.
+ *
+ * Blog: http://blog.didispace.com/
+ * Github: https://github.com/dyc87112/
+ */
+public interface UserMapperPrimary {
+
+ @Select("SELECT * FROM USER WHERE NAME = #{name}")
+ UserPrimary findByName(@Param("name") String name);
+
+ @Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")
+ int insert(@Param("name") String name, @Param("age") Integer age);
+
+ @Delete("DELETE FROM USER")
+ int deleteAll();
+
+}
diff --git a/2.x/chapter3-9/src/main/java/com/didispace/chapter39/s/entity/UserSecondary.java b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/s/entity/UserSecondary.java
new file mode 100644
index 00000000..fdd64dff
--- /dev/null
+++ b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/s/entity/UserSecondary.java
@@ -0,0 +1,20 @@
+package com.didispace.chapter39.s.entity;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+@Data
+@NoArgsConstructor
+public class UserSecondary {
+
+ private Long id;
+
+ private String name;
+ private Integer age;
+
+ public UserSecondary(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+}
\ No newline at end of file
diff --git a/2.x/chapter3-9/src/main/java/com/didispace/chapter39/s/mapper/UserMapperSecondary.java b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/s/mapper/UserMapperSecondary.java
new file mode 100644
index 00000000..bb4b004c
--- /dev/null
+++ b/2.x/chapter3-9/src/main/java/com/didispace/chapter39/s/mapper/UserMapperSecondary.java
@@ -0,0 +1,25 @@
+package com.didispace.chapter39.s.mapper;
+
+import com.didispace.chapter39.s.entity.UserSecondary;
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * Created by 程序猿DD/翟永超 on 2020/2/28.
+ *
+ * Blog: http://blog.didispace.com/
+ * Github: https://github.com/dyc87112/
+ */
+public interface UserMapperSecondary {
+
+ @Select("SELECT * FROM USER WHERE NAME = #{name}")
+ UserSecondary findByName(@Param("name") String name);
+
+ @Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")
+ int insert(@Param("name") String name, @Param("age") Integer age);
+
+ @Delete("DELETE FROM USER")
+ int deleteAll();
+}
diff --git a/2.x/chapter3-9/src/main/resources/application.properties b/2.x/chapter3-9/src/main/resources/application.properties
new file mode 100644
index 00000000..87777023
--- /dev/null
+++ b/2.x/chapter3-9/src/main/resources/application.properties
@@ -0,0 +1,13 @@
+# pring boot 1.x的配置:spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1
+spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
+spring.datasource.primary.username=root
+spring.datasource.primary.password=12345678
+spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
+
+# spring boot 1.x的配置:spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2
+spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
+spring.datasource.secondary.username=root
+spring.datasource.secondary.password=12345678
+spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
+
+#mybatis.mapper-locations=classpath:mapper/*.xml
diff --git a/2.x/chapter3-9/src/main/resources/mapper.primary/UserMapper.xml b/2.x/chapter3-9/src/main/resources/mapper.primary/UserMapper.xml
new file mode 100644
index 00000000..6eae360b
--- /dev/null
+++ b/2.x/chapter3-9/src/main/resources/mapper.primary/UserMapper.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ SELECT * FROM USER WHERE NAME = #{name}
+
+
+
+ INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter3-9/src/main/resources/mapper.secondary/UserMapper.xml b/2.x/chapter3-9/src/main/resources/mapper.secondary/UserMapper.xml
new file mode 100644
index 00000000..361cd16e
--- /dev/null
+++ b/2.x/chapter3-9/src/main/resources/mapper.secondary/UserMapper.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ SELECT * FROM USER WHERE NAME = #{name}
+
+
+
+ INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter3-9/src/test/java/com/didispace/chapter39/Chapter39ApplicationTests.java b/2.x/chapter3-9/src/test/java/com/didispace/chapter39/Chapter39ApplicationTests.java
new file mode 100644
index 00000000..a1bd3a81
--- /dev/null
+++ b/2.x/chapter3-9/src/test/java/com/didispace/chapter39/Chapter39ApplicationTests.java
@@ -0,0 +1,60 @@
+package com.didispace.chapter39;
+
+import com.didispace.chapter39.p.entity.UserPrimary;
+import com.didispace.chapter39.p.mapper.UserMapperPrimary;
+import com.didispace.chapter39.s.entity.UserSecondary;
+import com.didispace.chapter39.s.mapper.UserMapperSecondary;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+@Slf4j
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@Transactional
+public class Chapter39ApplicationTests {
+
+ @Autowired
+ private UserMapperPrimary userMapperPrimary;
+ @Autowired
+ private UserMapperSecondary userMapperSecondary;
+
+ @Before
+ public void setUp() {
+ // 清空测试表,保证每次结果一样
+ userMapperPrimary.deleteAll();
+ userMapperSecondary.deleteAll();
+ }
+
+ @Test
+ public void test() throws Exception {
+ // 往Primary数据源插入一条数据
+ userMapperPrimary.insert("AAA", 20);
+
+ // 从Primary数据源查询刚才插入的数据,配置正确就可以查询到
+ UserPrimary userPrimary = userMapperPrimary.findByName("AAA");
+ Assert.assertEquals(20, userPrimary.getAge().intValue());
+
+ // 从Secondary数据源查询刚才插入的数据,配置正确应该是查询不到的
+ UserSecondary userSecondary = userMapperSecondary.findByName("AAA");
+ Assert.assertNull(userSecondary);
+
+ // 往Secondary数据源插入一条数据
+ userMapperSecondary.insert("BBB", 20);
+
+ // 从Primary数据源查询刚才插入的数据,配置正确应该是查询不到的
+ userPrimary = userMapperPrimary.findByName("BBB");
+ Assert.assertNull(userPrimary);
+
+ // 从Secondary数据源查询刚才插入的数据,配置正确就可以查询到
+ userSecondary = userMapperSecondary.findByName("BBB");
+ Assert.assertEquals(20, userSecondary.getAge().intValue());
+ }
+
+}
diff --git a/2.x/chapter4-1/.gitignore b/2.x/chapter4-1/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter4-1/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.1.x/chapter4-1/pom.xml b/2.x/chapter4-1/pom.xml
similarity index 96%
rename from 2.1.x/chapter4-1/pom.xml
rename to 2.x/chapter4-1/pom.xml
index e8191b85..07c54958 100644
--- a/2.1.x/chapter4-1/pom.xml
+++ b/2.x/chapter4-1/pom.xml
@@ -13,6 +13,7 @@
com.didispace
chapter4-1
0.0.1-SNAPSHOT
+ 使用 Thymeleaf开发Web页面
1.8
diff --git a/2.1.x/chapter4-1/src/main/java/com/didispace/chapter41/Chapter41Application.java b/2.x/chapter4-1/src/main/java/com/didispace/chapter41/Chapter41Application.java
similarity index 100%
rename from 2.1.x/chapter4-1/src/main/java/com/didispace/chapter41/Chapter41Application.java
rename to 2.x/chapter4-1/src/main/java/com/didispace/chapter41/Chapter41Application.java
diff --git a/2.1.x/chapter4-1/src/main/java/com/didispace/chapter41/HelloController.java b/2.x/chapter4-1/src/main/java/com/didispace/chapter41/HelloController.java
similarity index 100%
rename from 2.1.x/chapter4-1/src/main/java/com/didispace/chapter41/HelloController.java
rename to 2.x/chapter4-1/src/main/java/com/didispace/chapter41/HelloController.java
diff --git a/2.1.x/chapter4-1/src/main/resources/application.properties b/2.x/chapter4-1/src/main/resources/application.properties
similarity index 100%
rename from 2.1.x/chapter4-1/src/main/resources/application.properties
rename to 2.x/chapter4-1/src/main/resources/application.properties
diff --git a/2.1.x/chapter4-1/src/main/resources/templates/index.html b/2.x/chapter4-1/src/main/resources/templates/index.html
similarity index 100%
rename from 2.1.x/chapter4-1/src/main/resources/templates/index.html
rename to 2.x/chapter4-1/src/main/resources/templates/index.html
diff --git a/2.x/chapter4-2/.gitignore b/2.x/chapter4-2/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter4-2/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.1.x/chapter4-2/pom.xml b/2.x/chapter4-2/pom.xml
similarity index 96%
rename from 2.1.x/chapter4-2/pom.xml
rename to 2.x/chapter4-2/pom.xml
index d6022db9..26b9d0e6 100644
--- a/2.1.x/chapter4-2/pom.xml
+++ b/2.x/chapter4-2/pom.xml
@@ -13,6 +13,7 @@
com.didispace
chapter4-2
0.0.1-SNAPSHOT
+ 使用 ECharts 绘制折线图
1.8
diff --git a/2.1.x/chapter4-2/src/main/java/com/didispace/chapter42/Chapter42Application.java b/2.x/chapter4-2/src/main/java/com/didispace/chapter42/Chapter42Application.java
similarity index 100%
rename from 2.1.x/chapter4-2/src/main/java/com/didispace/chapter42/Chapter42Application.java
rename to 2.x/chapter4-2/src/main/java/com/didispace/chapter42/Chapter42Application.java
diff --git a/2.1.x/chapter4-2/src/main/java/com/didispace/chapter42/HelloController.java b/2.x/chapter4-2/src/main/java/com/didispace/chapter42/HelloController.java
similarity index 100%
rename from 2.1.x/chapter4-2/src/main/java/com/didispace/chapter42/HelloController.java
rename to 2.x/chapter4-2/src/main/java/com/didispace/chapter42/HelloController.java
diff --git a/2.1.x/chapter4-2/src/main/resources/application.properties b/2.x/chapter4-2/src/main/resources/application.properties
similarity index 100%
rename from 2.1.x/chapter4-2/src/main/resources/application.properties
rename to 2.x/chapter4-2/src/main/resources/application.properties
diff --git a/2.1.x/chapter4-2/src/main/resources/templates/index.html b/2.x/chapter4-2/src/main/resources/templates/index.html
similarity index 100%
rename from 2.1.x/chapter4-2/src/main/resources/templates/index.html
rename to 2.x/chapter4-2/src/main/resources/templates/index.html
diff --git a/2.x/chapter4-3/.gitignore b/2.x/chapter4-3/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter4-3/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.x/chapter4-3/pom.xml b/2.x/chapter4-3/pom.xml
new file mode 100644
index 00000000..21238608
--- /dev/null
+++ b/2.x/chapter4-3/pom.xml
@@ -0,0 +1,54 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.4.1
+
+
+
+ com.didispace
+ chapter4-3
+ 0.0.1-SNAPSHOT
+ 文件上传
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter4-3/src/main/java/com/didispace/chapter43/Chapter43Application.java b/2.x/chapter4-3/src/main/java/com/didispace/chapter43/Chapter43Application.java
new file mode 100644
index 00000000..f54783ed
--- /dev/null
+++ b/2.x/chapter4-3/src/main/java/com/didispace/chapter43/Chapter43Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter43;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter43Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter43Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter4-3/src/main/java/com/didispace/chapter43/UploadController.java b/2.x/chapter4-3/src/main/java/com/didispace/chapter43/UploadController.java
new file mode 100644
index 00000000..e36f32b2
--- /dev/null
+++ b/2.x/chapter4-3/src/main/java/com/didispace/chapter43/UploadController.java
@@ -0,0 +1,39 @@
+package com.didispace.chapter43;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+@Controller
+@Slf4j
+public class UploadController {
+
+ @Value("${file.upload.path}")
+ private String path;
+
+ @GetMapping("/")
+ public String uploadPage() {
+ return "upload";
+ }
+
+ @PostMapping("/upload")
+ @ResponseBody
+ public String create(@RequestPart MultipartFile file) throws IOException {
+ String fileName = file.getOriginalFilename();
+ String filePath = path + fileName;
+
+ File dest = new File(filePath);
+ Files.copy(file.getInputStream(), dest.toPath());
+ return "Upload file success : " + dest.getAbsolutePath();
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter4-3/src/main/resources/application.properties b/2.x/chapter4-3/src/main/resources/application.properties
new file mode 100644
index 00000000..08991f4c
--- /dev/null
+++ b/2.x/chapter4-3/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+
+spring.servlet.multipart.max-file-size=2MB
+spring.servlet.multipart.max-request-size=2MB
+
+file.upload.path=/Users/zhaiyongchao/
\ No newline at end of file
diff --git a/2.x/chapter4-3/src/main/resources/templates/upload.html b/2.x/chapter4-3/src/main/resources/templates/upload.html
new file mode 100644
index 00000000..59b8166a
--- /dev/null
+++ b/2.x/chapter4-3/src/main/resources/templates/upload.html
@@ -0,0 +1,15 @@
+
+
+
+
+ 文件上传页面
+
+
+文件上传页面
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter4-3/src/test/java/FileTest.java b/2.x/chapter4-3/src/test/java/FileTest.java
new file mode 100644
index 00000000..d19d55e0
--- /dev/null
+++ b/2.x/chapter4-3/src/test/java/FileTest.java
@@ -0,0 +1,48 @@
+import com.didispace.chapter43.Chapter43Application;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+
+@SpringBootTest(classes = Chapter43Application.class)
+public class FileTest {
+
+ @Autowired
+ protected WebApplicationContext context;
+ protected MockMvc mvc;
+
+ @BeforeEach
+ public void setUp() {
+ mvc = MockMvcBuilders.webAppContextSetup(context).build();
+ }
+
+ @Test
+ public void uploadFile() throws Exception {
+ MockMultipartFile file = new MockMultipartFile(
+ "file",
+ "hello.txt",
+ MediaType.TEXT_PLAIN_VALUE,
+ "Hello, World!".getBytes()
+ );
+
+ final MvcResult result = mvc.perform(
+ MockMvcRequestBuilders
+ .multipart("/upload")
+ .file(file))
+ .andDo(print())
+ .andExpect(status().isOk())
+ .andReturn();
+ }
+
+}
diff --git a/2.x/chapter4-4/.gitignore b/2.x/chapter4-4/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter4-4/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.x/chapter4-4/pom.xml b/2.x/chapter4-4/pom.xml
new file mode 100644
index 00000000..49da68de
--- /dev/null
+++ b/2.x/chapter4-4/pom.xml
@@ -0,0 +1,54 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.4.1
+
+
+
+ com.didispace
+ chapter4-4
+ 0.0.1-SNAPSHOT
+ 多文件上传
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter4-4/src/main/java/com/didispace/chapter44/Chapter44Application.java b/2.x/chapter4-4/src/main/java/com/didispace/chapter44/Chapter44Application.java
new file mode 100644
index 00000000..a0145c56
--- /dev/null
+++ b/2.x/chapter4-4/src/main/java/com/didispace/chapter44/Chapter44Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter44;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter44Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter44Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter4-4/src/main/java/com/didispace/chapter44/UploadController.java b/2.x/chapter4-4/src/main/java/com/didispace/chapter44/UploadController.java
new file mode 100644
index 00000000..82ce1741
--- /dev/null
+++ b/2.x/chapter4-4/src/main/java/com/didispace/chapter44/UploadController.java
@@ -0,0 +1,44 @@
+package com.didispace.chapter44;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+@Controller
+@Slf4j
+public class UploadController {
+
+ @Value("${file.upload.path}")
+ private String path;
+
+ @GetMapping("/")
+ public String uploadPage() {
+ return "upload";
+ }
+
+ @PostMapping("/upload")
+ @ResponseBody
+ public String create(@RequestPart MultipartFile[] files) throws IOException {
+ StringBuffer message = new StringBuffer();
+
+ for (MultipartFile file : files) {
+ String fileName = file.getOriginalFilename();
+ String filePath = path + fileName;
+
+ File dest = new File(filePath);
+ Files.copy(file.getInputStream(), dest.toPath());
+ message.append("Upload file success : " + dest.getAbsolutePath()).append(" ");
+ }
+ return message.toString();
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter4-4/src/main/resources/application.properties b/2.x/chapter4-4/src/main/resources/application.properties
new file mode 100644
index 00000000..0d9500e2
--- /dev/null
+++ b/2.x/chapter4-4/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+
+spring.servlet.multipart.max-file-size=2MB
+spring.servlet.multipart.max-request-size=2MB
+
+file.upload.path=/Users/didi/
\ No newline at end of file
diff --git a/2.x/chapter4-4/src/main/resources/templates/upload.html b/2.x/chapter4-4/src/main/resources/templates/upload.html
new file mode 100644
index 00000000..b7307dac
--- /dev/null
+++ b/2.x/chapter4-4/src/main/resources/templates/upload.html
@@ -0,0 +1,16 @@
+
+
+
+
+ 文件上传页面
+
+
+文件上传页面
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter4-4/src/test/java/FileTest.java b/2.x/chapter4-4/src/test/java/FileTest.java
new file mode 100644
index 00000000..04cdeb58
--- /dev/null
+++ b/2.x/chapter4-4/src/test/java/FileTest.java
@@ -0,0 +1,11 @@
+import org.junit.jupiter.api.Test;
+
+public class FileTest {
+
+ @Test
+ public void uploadFile() throws Exception {
+
+
+ }
+
+}
diff --git a/2.x/chapter4-5/pom.xml b/2.x/chapter4-5/pom.xml
new file mode 100644
index 00000000..7120c77a
--- /dev/null
+++ b/2.x/chapter4-5/pom.xml
@@ -0,0 +1,63 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+ com.didispace
+ chapter4-5
+ 0.0.1-SNAPSHOT
+ Spring Security快速入门
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter4-5/src/main/java/com/didispace/chapter45/Application.java b/2.x/chapter4-5/src/main/java/com/didispace/chapter45/Application.java
new file mode 100644
index 00000000..00d2d076
--- /dev/null
+++ b/2.x/chapter4-5/src/main/java/com/didispace/chapter45/Application.java
@@ -0,0 +1,22 @@
+package com.didispace.chapter45;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ *
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @blog http://blog.didispace.com
+ *
+ */
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+
+ SpringApplication.run(Application.class, args);
+
+ }
+
+}
diff --git a/2.x/chapter4-5/src/main/java/com/didispace/chapter45/HelloController.java b/2.x/chapter4-5/src/main/java/com/didispace/chapter45/HelloController.java
new file mode 100644
index 00000000..849a125d
--- /dev/null
+++ b/2.x/chapter4-5/src/main/java/com/didispace/chapter45/HelloController.java
@@ -0,0 +1,33 @@
+package com.didispace.chapter45;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ *
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @blog http://blog.didispace.com
+ *
+ */
+@Controller
+public class HelloController {
+
+ @RequestMapping("/")
+ public String index() {
+ return "index";
+ }
+
+ @RequestMapping("/hello")
+ public String hello() {
+ return "hello";
+ }
+
+ @RequestMapping(value = "/login", method = RequestMethod.GET)
+ public String login() {
+ return "login";
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter4-5/src/main/java/com/didispace/chapter45/WebSecurityConfig.java b/2.x/chapter4-5/src/main/java/com/didispace/chapter45/WebSecurityConfig.java
new file mode 100644
index 00000000..30fffef5
--- /dev/null
+++ b/2.x/chapter4-5/src/main/java/com/didispace/chapter45/WebSecurityConfig.java
@@ -0,0 +1,36 @@
+package com.didispace.chapter45;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+@Configuration
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .authorizeRequests()
+ .antMatchers("/", "/home").permitAll()
+ .anyRequest().authenticated()
+ .and()
+ .formLogin()
+ .loginPage("/login")
+ .permitAll()
+ .and()
+ .logout()
+ .permitAll();
+ }
+
+ @Autowired
+ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+ auth
+ .inMemoryAuthentication()
+ .withUser("user").password("password").roles("USER");
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter4-5/src/main/resources/application.properties b/2.x/chapter4-5/src/main/resources/application.properties
new file mode 100644
index 00000000..e69de29b
diff --git a/2.x/chapter4-5/src/main/resources/templates/hello.html b/2.x/chapter4-5/src/main/resources/templates/hello.html
new file mode 100644
index 00000000..51477131
--- /dev/null
+++ b/2.x/chapter4-5/src/main/resources/templates/hello.html
@@ -0,0 +1,13 @@
+
+
+
+ Hello World!
+
+
+Hello [[${#httpServletRequest.remoteUser}]]!
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter4-5/src/main/resources/templates/index.html b/2.x/chapter4-5/src/main/resources/templates/index.html
new file mode 100644
index 00000000..ffe28340
--- /dev/null
+++ b/2.x/chapter4-5/src/main/resources/templates/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Spring Security入门
+
+
+欢迎使用Spring Security!
+
+点击 这里 打个招呼吧
+
+
\ No newline at end of file
diff --git a/2.x/chapter4-5/src/main/resources/templates/login.html b/2.x/chapter4-5/src/main/resources/templates/login.html
new file mode 100644
index 00000000..f5cbe8e2
--- /dev/null
+++ b/2.x/chapter4-5/src/main/resources/templates/login.html
@@ -0,0 +1,21 @@
+
+
+
+ Spring Security Example
+
+
+
+ 用户名或密码错
+
+
+ 您已注销成功
+
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter5-1/.gitignore b/2.x/chapter5-1/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter5-1/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.x/chapter5-1/pom.xml b/2.x/chapter5-1/pom.xml
new file mode 100644
index 00000000..19540eff
--- /dev/null
+++ b/2.x/chapter5-1/pom.xml
@@ -0,0 +1,70 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+
+ com.didispace
+ chapter5-1
+ 0.0.1-SNAPSHOT
+ 使用进程内缓存
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter5-1/src/main/java/com/didispace/chapter51/Chapter51Application.java b/2.x/chapter5-1/src/main/java/com/didispace/chapter51/Chapter51Application.java
new file mode 100644
index 00000000..b855c592
--- /dev/null
+++ b/2.x/chapter5-1/src/main/java/com/didispace/chapter51/Chapter51Application.java
@@ -0,0 +1,15 @@
+package com.didispace.chapter51;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+
+@EnableCaching
+@SpringBootApplication
+public class Chapter51Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter51Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter5-1/src/main/java/com/didispace/chapter51/User.java b/2.x/chapter5-1/src/main/java/com/didispace/chapter51/User.java
new file mode 100644
index 00000000..55ae4a76
--- /dev/null
+++ b/2.x/chapter5-1/src/main/java/com/didispace/chapter51/User.java
@@ -0,0 +1,26 @@
+package com.didispace.chapter51;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+@Data
+@NoArgsConstructor
+public class User {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String name;
+ private Integer age;
+
+ public User(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+}
\ No newline at end of file
diff --git a/2.x/chapter5-1/src/main/java/com/didispace/chapter51/UserRepository.java b/2.x/chapter5-1/src/main/java/com/didispace/chapter51/UserRepository.java
new file mode 100644
index 00000000..2785e7ae
--- /dev/null
+++ b/2.x/chapter5-1/src/main/java/com/didispace/chapter51/UserRepository.java
@@ -0,0 +1,26 @@
+package com.didispace.chapter51;
+
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+/**
+ * Created by 程序猿DD/翟永超 on 2020/7/13.
+ *
+ * Blog: http://blog.didispace.com/
+ * Github: https://github.com/dyc87112/
+ */
+@CacheConfig(cacheNames = "users")
+public interface UserRepository extends JpaRepository {
+
+ @Cacheable
+ User findByName(String name);
+
+ User findByNameAndAge(String name, Integer age);
+
+ @Query("from User u where u.name=:name")
+ User findUser(@Param("name") String name);
+
+}
diff --git a/2.x/chapter5-1/src/main/resources/application.properties b/2.x/chapter5-1/src/main/resources/application.properties
new file mode 100644
index 00000000..ba1e5990
--- /dev/null
+++ b/2.x/chapter5-1/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+spring.datasource.url=jdbc:mysql://localhost:3306/test
+spring.datasource.username=root
+spring.datasource.password=12345678
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+
+spring.jpa.show-sql=true
+spring.jpa.hibernate.ddl-auto=create-drop
\ No newline at end of file
diff --git a/2.x/chapter5-1/src/test/java/com/didispace/chapter51/Chapter51ApplicationTests.java b/2.x/chapter5-1/src/test/java/com/didispace/chapter51/Chapter51ApplicationTests.java
new file mode 100644
index 00000000..3d4dabbd
--- /dev/null
+++ b/2.x/chapter5-1/src/test/java/com/didispace/chapter51/Chapter51ApplicationTests.java
@@ -0,0 +1,34 @@
+package com.didispace.chapter51;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cache.CacheManager;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@Slf4j
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class Chapter51ApplicationTests {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ private CacheManager cacheManager;
+
+ @Test
+ public void test() throws Exception {
+ // 创建1条记录
+ userRepository.save(new User("AAA", 10));
+
+ User u1 = userRepository.findByName("AAA");
+ System.out.println("第一次查询:" + u1.getAge());
+
+ User u2 = userRepository.findByName("AAA");
+ System.out.println("第二次查询:" + u2.getAge());
+ }
+
+}
diff --git a/2.x/chapter5-2/.gitignore b/2.x/chapter5-2/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter5-2/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.x/chapter5-2/pom.xml b/2.x/chapter5-2/pom.xml
new file mode 100644
index 00000000..affc2e9c
--- /dev/null
+++ b/2.x/chapter5-2/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+
+ com.didispace
+ chapter5-2
+ 0.0.1-SNAPSHOT
+ 使用进程内缓存 EhCache
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+
+ net.sf.ehcache
+ ehcache
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter5-2/src/main/java/com/didispace/chapter52/Chapter52Application.java b/2.x/chapter5-2/src/main/java/com/didispace/chapter52/Chapter52Application.java
new file mode 100644
index 00000000..e4842885
--- /dev/null
+++ b/2.x/chapter5-2/src/main/java/com/didispace/chapter52/Chapter52Application.java
@@ -0,0 +1,15 @@
+package com.didispace.chapter52;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+
+@EnableCaching
+@SpringBootApplication
+public class Chapter52Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter52Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter5-2/src/main/java/com/didispace/chapter52/User.java b/2.x/chapter5-2/src/main/java/com/didispace/chapter52/User.java
new file mode 100644
index 00000000..9fb641f0
--- /dev/null
+++ b/2.x/chapter5-2/src/main/java/com/didispace/chapter52/User.java
@@ -0,0 +1,26 @@
+package com.didispace.chapter52;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+@Data
+@NoArgsConstructor
+public class User {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String name;
+ private Integer age;
+
+ public User(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+}
\ No newline at end of file
diff --git a/2.x/chapter5-2/src/main/java/com/didispace/chapter52/UserRepository.java b/2.x/chapter5-2/src/main/java/com/didispace/chapter52/UserRepository.java
new file mode 100644
index 00000000..4dad3d06
--- /dev/null
+++ b/2.x/chapter5-2/src/main/java/com/didispace/chapter52/UserRepository.java
@@ -0,0 +1,21 @@
+package com.didispace.chapter52;
+
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+/**
+ * Created by 程序猿DD/翟永超 on 2020/7/14.
+ *
+ * Blog: http://blog.didispace.com/
+ * Github: https://github.com/dyc87112/
+ */
+@CacheConfig(cacheNames = "users")
+public interface UserRepository extends JpaRepository {
+
+ @Cacheable
+ User findByName(String name);
+
+}
diff --git a/2.x/chapter5-2/src/main/resources/application.properties b/2.x/chapter5-2/src/main/resources/application.properties
new file mode 100644
index 00000000..ba1e5990
--- /dev/null
+++ b/2.x/chapter5-2/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+spring.datasource.url=jdbc:mysql://localhost:3306/test
+spring.datasource.username=root
+spring.datasource.password=12345678
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+
+spring.jpa.show-sql=true
+spring.jpa.hibernate.ddl-auto=create-drop
\ No newline at end of file
diff --git a/2.x/chapter5-2/src/main/resources/ehcache.xml b/2.x/chapter5-2/src/main/resources/ehcache.xml
new file mode 100644
index 00000000..c178cc9f
--- /dev/null
+++ b/2.x/chapter5-2/src/main/resources/ehcache.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter5-2/src/test/java/com/didispace/chapter52/Chapter52ApplicationTests.java b/2.x/chapter5-2/src/test/java/com/didispace/chapter52/Chapter52ApplicationTests.java
new file mode 100644
index 00000000..76c505c9
--- /dev/null
+++ b/2.x/chapter5-2/src/test/java/com/didispace/chapter52/Chapter52ApplicationTests.java
@@ -0,0 +1,36 @@
+package com.didispace.chapter52;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cache.CacheManager;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@Slf4j
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class Chapter52ApplicationTests {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ private CacheManager cacheManager;
+
+ @Test
+ public void test() throws Exception {
+ System.out.println("CacheManager type : " + cacheManager.getClass());
+
+ // 创建1条记录
+ userRepository.save(new User("AAA", 10));
+
+ User u1 = userRepository.findByName("AAA");
+ System.out.println("第一次查询:" + u1.getAge());
+
+ User u2 = userRepository.findByName("AAA");
+ System.out.println("第二次查询:" + u2.getAge());
+ }
+
+}
diff --git a/2.x/chapter5-3/.gitignore b/2.x/chapter5-3/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter5-3/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.x/chapter5-3/pom.xml b/2.x/chapter5-3/pom.xml
new file mode 100644
index 00000000..5c729543
--- /dev/null
+++ b/2.x/chapter5-3/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+
+ com.didispace
+ chapter5-3
+ 0.0.1-SNAPSHOT
+ 使用EhCache缓存集群
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+
+ net.sf.ehcache
+ ehcache
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter5-3/src/main/java/com/didispace/chapter53/Chapter53Application.java b/2.x/chapter5-3/src/main/java/com/didispace/chapter53/Chapter53Application.java
new file mode 100644
index 00000000..3abe9f33
--- /dev/null
+++ b/2.x/chapter5-3/src/main/java/com/didispace/chapter53/Chapter53Application.java
@@ -0,0 +1,50 @@
+package com.didispace.chapter53;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.rmi.registry.LocateRegistry;
+
+@EnableCaching
+@SpringBootApplication
+public class Chapter53Application {
+
+ public static void main(String[] args) throws Exception {
+// LocateRegistry.createRegistry(Integer.valueOf(System.getProperty("rmi.port")));
+ SpringApplication.run(Chapter53Application.class, args);
+ }
+
+ @RestController
+ static class HelloController {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @GetMapping("/create")
+ public void create() {
+ userRepository.save(new User("AAA", 10));
+ }
+
+ @GetMapping("/update")
+ public User update() {
+ User u1 = userRepository.findByName("AAA");
+ u1.setAge(20);
+ u1 = userRepository.save(u1);
+ return u1;
+ }
+
+ @GetMapping("/find")
+ public User find() {
+ User u1 = userRepository.findByName("AAA");
+ System.out.println("查询AAA用户:" + u1.getAge());
+ return u1;
+ }
+
+ }
+
+}
diff --git a/2.x/chapter5-3/src/main/java/com/didispace/chapter53/User.java b/2.x/chapter5-3/src/main/java/com/didispace/chapter53/User.java
new file mode 100644
index 00000000..2986b7d4
--- /dev/null
+++ b/2.x/chapter5-3/src/main/java/com/didispace/chapter53/User.java
@@ -0,0 +1,27 @@
+package com.didispace.chapter53;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import java.io.Serializable;
+
+@Entity
+@Data
+@NoArgsConstructor
+public class User implements Serializable {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String name;
+ private Integer age;
+
+ public User(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+}
diff --git a/2.x/chapter5-3/src/main/java/com/didispace/chapter53/UserRepository.java b/2.x/chapter5-3/src/main/java/com/didispace/chapter53/UserRepository.java
new file mode 100644
index 00000000..4d52745e
--- /dev/null
+++ b/2.x/chapter5-3/src/main/java/com/didispace/chapter53/UserRepository.java
@@ -0,0 +1,21 @@
+package com.didispace.chapter53;
+
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+/**
+ * Created by 程序猿DD/翟永超 on 2020/7/16.
+ *
+ * Blog: http://blog.didispace.com/
+ * Github: https://github.com/dyc87112/
+ */
+@CacheConfig(cacheNames = "users")
+public interface UserRepository extends JpaRepository {
+
+ @Cacheable
+ User findByName(String name);
+
+}
diff --git a/2.x/chapter5-3/src/main/resources/application.properties b/2.x/chapter5-3/src/main/resources/application.properties
new file mode 100644
index 00000000..43e74c79
--- /dev/null
+++ b/2.x/chapter5-3/src/main/resources/application.properties
@@ -0,0 +1,17 @@
+spring.datasource.url=jdbc:mysql://localhost:3306/test
+spring.datasource.username=root
+spring.datasource.password=12345678
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+
+spring.jpa.show-sql=true
+spring.jpa.hibernate.ddl-auto=create
+
+#logging.level.net.sf.ehcache=debug
+
+# 不同实例的配置
+#spring.cache.ehcache.config=classpath:ehcache-1.xml
+#spring.cache.ehcache.config=classpath:ehcache-2.xml
+
+# 用不同命令启动不同实例
+#-Dserver.port=8001 -Dspring.cache.ehcache.config=classpath:ehcache-1.xml
+#-Dserver.port=8002 -Dspring.cache.ehcache.config=classpath:ehcache-2.xml
diff --git a/2.x/chapter5-3/src/main/resources/ehcache-1.xml b/2.x/chapter5-3/src/main/resources/ehcache-1.xml
new file mode 100644
index 00000000..fbc88162
--- /dev/null
+++ b/2.x/chapter5-3/src/main/resources/ehcache-1.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter5-3/src/main/resources/ehcache-2.xml b/2.x/chapter5-3/src/main/resources/ehcache-2.xml
new file mode 100644
index 00000000..878b6be2
--- /dev/null
+++ b/2.x/chapter5-3/src/main/resources/ehcache-2.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter5-3/src/test/java/com/didispace/chapter53/Chapter53ApplicationTests.java b/2.x/chapter5-3/src/test/java/com/didispace/chapter53/Chapter53ApplicationTests.java
new file mode 100644
index 00000000..0e9c2939
--- /dev/null
+++ b/2.x/chapter5-3/src/test/java/com/didispace/chapter53/Chapter53ApplicationTests.java
@@ -0,0 +1,36 @@
+package com.didispace.chapter53;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cache.CacheManager;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@Slf4j
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class Chapter53ApplicationTests {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ private CacheManager cacheManager;
+
+ @Test
+ public void test() throws Exception {
+ System.out.println("CacheManager type : " + cacheManager.getClass());
+
+ // 创建1条记录
+ userRepository.save(new User("AAA", 10));
+
+ User u1 = userRepository.findByName("AAA");
+ System.out.println("第一次查询:" + u1.getAge());
+
+ User u2 = userRepository.findByName("AAA");
+ System.out.println("第二次查询:" + u2.getAge());
+ }
+
+}
diff --git a/2.x/chapter5-4/.gitignore b/2.x/chapter5-4/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter5-4/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.x/chapter5-4/pom.xml b/2.x/chapter5-4/pom.xml
new file mode 100644
index 00000000..1f4de65e
--- /dev/null
+++ b/2.x/chapter5-4/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+
+ com.didispace
+ chapter5-4
+ 0.0.1-SNAPSHOT
+ 使用集中式缓存Redis
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter5-4/src/main/java/com/didispace/chapter54/Chapter54Application.java b/2.x/chapter5-4/src/main/java/com/didispace/chapter54/Chapter54Application.java
new file mode 100644
index 00000000..f2789f8b
--- /dev/null
+++ b/2.x/chapter5-4/src/main/java/com/didispace/chapter54/Chapter54Application.java
@@ -0,0 +1,15 @@
+package com.didispace.chapter54;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+
+@EnableCaching
+@SpringBootApplication
+public class Chapter54Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter54Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter5-4/src/main/java/com/didispace/chapter54/User.java b/2.x/chapter5-4/src/main/java/com/didispace/chapter54/User.java
new file mode 100644
index 00000000..11e2dc13
--- /dev/null
+++ b/2.x/chapter5-4/src/main/java/com/didispace/chapter54/User.java
@@ -0,0 +1,27 @@
+package com.didispace.chapter54;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import java.io.Serializable;
+
+@Entity
+@Data
+@NoArgsConstructor
+public class User implements Serializable {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String name;
+ private Integer age;
+
+ public User(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+}
\ No newline at end of file
diff --git a/2.x/chapter5-4/src/main/java/com/didispace/chapter54/UserRepository.java b/2.x/chapter5-4/src/main/java/com/didispace/chapter54/UserRepository.java
new file mode 100644
index 00000000..4b14b113
--- /dev/null
+++ b/2.x/chapter5-4/src/main/java/com/didispace/chapter54/UserRepository.java
@@ -0,0 +1,26 @@
+package com.didispace.chapter54;
+
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+/**
+ * Created by 程序猿DD/翟永超 on 2020/7/26.
+ *
+ * Blog: http://blog.didispace.com/
+ * Github: https://github.com/dyc87112/
+ */
+@CacheConfig(cacheNames = "users")
+public interface UserRepository extends JpaRepository {
+
+ @Cacheable
+ User findByName(String name);
+
+ User findByNameAndAge(String name, Integer age);
+
+ @Query("from User u where u.name=:name")
+ User findUser(@Param("name") String name);
+
+}
diff --git a/2.x/chapter5-4/src/main/resources/application.properties b/2.x/chapter5-4/src/main/resources/application.properties
new file mode 100644
index 00000000..7136291e
--- /dev/null
+++ b/2.x/chapter5-4/src/main/resources/application.properties
@@ -0,0 +1,16 @@
+spring.datasource.url=jdbc:mysql://localhost:3306/test
+spring.datasource.username=root
+spring.datasource.password=12345678
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+
+spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
+spring.jpa.show-sql=true
+spring.jpa.hibernate.ddl-auto=create-drop
+
+spring.redis.host=localhost
+spring.redis.port=6379
+spring.redis.lettuce.pool.max-idle=8
+spring.redis.lettuce.pool.max-active=8
+spring.redis.lettuce.pool.max-wait=-1ms
+spring.redis.lettuce.pool.min-idle=0
+spring.redis.lettuce.shutdown-timeout=100ms
diff --git a/2.x/chapter5-4/src/test/java/com/didispace/chapter54/Chapter54ApplicationTests.java b/2.x/chapter5-4/src/test/java/com/didispace/chapter54/Chapter54ApplicationTests.java
new file mode 100644
index 00000000..de5a7185
--- /dev/null
+++ b/2.x/chapter5-4/src/test/java/com/didispace/chapter54/Chapter54ApplicationTests.java
@@ -0,0 +1,36 @@
+package com.didispace.chapter54;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cache.CacheManager;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@Slf4j
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class Chapter54ApplicationTests {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ private CacheManager cacheManager;
+
+ @Test
+ public void test() throws Exception {
+ System.out.println("CacheManager type : " + cacheManager.getClass());
+
+ // 创建1条记录
+ userRepository.save(new User("AAA", 10));
+
+ User u1 = userRepository.findByName("AAA");
+ System.out.println("第一次查询:" + u1.getAge());
+
+ User u2 = userRepository.findByName("AAA");
+ System.out.println("第二次查询:" + u2.getAge());
+ }
+
+}
diff --git a/2.x/chapter5-5/.gitignore b/2.x/chapter5-5/.gitignore
new file mode 100644
index 00000000..153c9335
--- /dev/null
+++ b/2.x/chapter5-5/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/2.x/chapter5-5/pom.xml b/2.x/chapter5-5/pom.xml
new file mode 100644
index 00000000..dc1d2874
--- /dev/null
+++ b/2.x/chapter5-5/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+ com.didispace
+ chapter5-5
+ 0.0.1-SNAPSHOT
+ 使用Redis的发布订阅
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter5-5/src/main/java/com/didispace/chapter55/Chapter55Application.java b/2.x/chapter5-5/src/main/java/com/didispace/chapter55/Chapter55Application.java
new file mode 100644
index 00000000..8da3b8b0
--- /dev/null
+++ b/2.x/chapter5-5/src/main/java/com/didispace/chapter55/Chapter55Application.java
@@ -0,0 +1,61 @@
+package com.didispace.chapter55;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.data.redis.connection.Message;
+import org.springframework.data.redis.connection.MessageListener;
+import org.springframework.data.redis.connection.RedisConnection;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.nio.charset.StandardCharsets;
+
+@SpringBootApplication
+public class Chapter55Application {
+
+ private static String CHANNEL = "didispace";
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter55Application.class, args);
+ }
+
+ @RestController
+ static class RedisController {
+
+ private RedisTemplate redisTemplate;
+
+ public RedisController(RedisTemplate redisTemplate) {
+ this.redisTemplate = redisTemplate;
+ }
+
+ @GetMapping("/publish")
+ public void publish(@RequestParam String message) {
+ // 发送消息
+ redisTemplate.convertAndSend(CHANNEL, message);
+ }
+
+ }
+
+ @Slf4j
+ @Service
+ static class MessageSubscriber {
+
+ public MessageSubscriber(RedisTemplate redisTemplate) {
+ RedisConnection redisConnection = redisTemplate.getConnectionFactory().getConnection();
+ redisConnection.subscribe(new MessageListener() {
+ @Override
+ public void onMessage(Message message, byte[] bytes) {
+ // 收到消息的处理逻辑
+ log.info("Receive message : " + message);
+ }
+ }, CHANNEL.getBytes(StandardCharsets.UTF_8));
+
+ }
+
+ }
+
+}
diff --git a/2.x/chapter5-5/src/main/resources/application.properties b/2.x/chapter5-5/src/main/resources/application.properties
new file mode 100644
index 00000000..2992f608
--- /dev/null
+++ b/2.x/chapter5-5/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+spring.redis.host=localhost
+spring.redis.port=6379
+spring.redis.lettuce.pool.max-idle=8
+spring.redis.lettuce.pool.max-active=8
+spring.redis.lettuce.pool.max-wait=-1ms
+spring.redis.lettuce.pool.min-idle=0
+spring.redis.lettuce.shutdown-timeout=100ms
diff --git a/2.x/chapter6-1/pom.xml b/2.x/chapter6-1/pom.xml
new file mode 100755
index 00000000..10a0116e
--- /dev/null
+++ b/2.x/chapter6-1/pom.xml
@@ -0,0 +1,55 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.4.1
+
+
+
+ com.didispace
+ chapter6-1
+ 0.0.1-SNAPSHOT
+ 使用MongoDB
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter6-1/src/main/java/com/didispace/chapter61/Chapter61Application.java b/2.x/chapter6-1/src/main/java/com/didispace/chapter61/Chapter61Application.java
new file mode 100755
index 00000000..dfd534eb
--- /dev/null
+++ b/2.x/chapter6-1/src/main/java/com/didispace/chapter61/Chapter61Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter61;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter61Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter61Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter6-1/src/main/java/com/didispace/chapter61/User.java b/2.x/chapter6-1/src/main/java/com/didispace/chapter61/User.java
new file mode 100644
index 00000000..e94f10c0
--- /dev/null
+++ b/2.x/chapter6-1/src/main/java/com/didispace/chapter61/User.java
@@ -0,0 +1,22 @@
+package com.didispace.chapter61;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.springframework.data.annotation.Id;
+
+/**
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @blog http://blog.didispace.com
+ */
+@Data
+@AllArgsConstructor
+public class User {
+
+ @Id
+ private Long id;
+
+ private String username;
+ private Integer age;
+
+}
diff --git a/2.x/chapter6-1/src/main/java/com/didispace/chapter61/UserRepository.java b/2.x/chapter6-1/src/main/java/com/didispace/chapter61/UserRepository.java
new file mode 100644
index 00000000..f1336f96
--- /dev/null
+++ b/2.x/chapter6-1/src/main/java/com/didispace/chapter61/UserRepository.java
@@ -0,0 +1,14 @@
+package com.didispace.chapter61;
+
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+/**
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @blog http://blog.didispace.com
+ */
+public interface UserRepository extends MongoRepository {
+
+ User findByUsername(String username);
+
+}
diff --git a/2.x/chapter6-1/src/main/resources/application.properties b/2.x/chapter6-1/src/main/resources/application.properties
new file mode 100644
index 00000000..0e2f083f
--- /dev/null
+++ b/2.x/chapter6-1/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+spring.data.mongodb.uri=mongodb://localhost:27017/test
+
+
diff --git a/2.x/chapter6-1/src/test/java/com/didispace/chapter61/ApplicationTests.java b/2.x/chapter6-1/src/test/java/com/didispace/chapter61/ApplicationTests.java
new file mode 100755
index 00000000..e1ee421a
--- /dev/null
+++ b/2.x/chapter6-1/src/test/java/com/didispace/chapter61/ApplicationTests.java
@@ -0,0 +1,35 @@
+package com.didispace.chapter61;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest(classes = Chapter61Application.class)
+public class ApplicationTests {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Test
+ public void test() throws Exception {
+ userRepository.deleteAll();
+
+ // 创建三个User,并验证User总数
+ userRepository.save(new User(1L, "didi", 30));
+ userRepository.save(new User(2L, "mama", 40));
+ userRepository.save(new User(3L, "kaka", 50));
+ Assertions.assertEquals(3, userRepository.findAll().size());
+
+ // 删除一个User,再验证User总数
+ User u = userRepository.findById(1L).get();
+ userRepository.delete(u);
+ Assertions.assertEquals(2, userRepository.findAll().size());
+
+ // 删除一个User,再验证User总数
+ u = userRepository.findByUsername("mama");
+ userRepository.delete(u);
+ Assertions.assertEquals(1, userRepository.findAll().size());
+ }
+
+}
diff --git a/2.x/chapter6-2/pom.xml b/2.x/chapter6-2/pom.xml
new file mode 100644
index 00000000..dc1b63bd
--- /dev/null
+++ b/2.x/chapter6-2/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+ com.didispace
+ chapter6-2
+ 1.0.0
+ jar
+ 使用轻量级树状存储 LDAP
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+
+ UTF-8
+ 1.8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-ldap
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ com.unboundid
+ unboundid-ldapsdk
+ test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter6-2/src/main/java/com/didispace/chapter62/Chapter62Application.java b/2.x/chapter6-2/src/main/java/com/didispace/chapter62/Chapter62Application.java
new file mode 100644
index 00000000..5baa9594
--- /dev/null
+++ b/2.x/chapter6-2/src/main/java/com/didispace/chapter62/Chapter62Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter62;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter62Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter62Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter6-2/src/main/java/com/didispace/chapter62/Person.java b/2.x/chapter6-2/src/main/java/com/didispace/chapter62/Person.java
new file mode 100644
index 00000000..cc078f67
--- /dev/null
+++ b/2.x/chapter6-2/src/main/java/com/didispace/chapter62/Person.java
@@ -0,0 +1,22 @@
+package com.didispace.chapter62;
+
+import lombok.Data;
+import org.springframework.ldap.odm.annotations.*;
+
+import javax.naming.Name;
+
+@Entry(base = "ou=people,dc=didispace,dc=com", objectClasses = "inetOrgPerson")
+@Data
+public class Person {
+
+ @Id
+ private Name id;
+ @DnAttribute(value = "uid", index = 3)
+ private String uid;
+ @Attribute(name = "cn")
+ private String commonName;
+ @Attribute(name = "sn")
+ private String userName;
+ private String userPassword;
+
+}
diff --git a/2.x/chapter6-2/src/main/java/com/didispace/chapter62/PersonRepository.java b/2.x/chapter6-2/src/main/java/com/didispace/chapter62/PersonRepository.java
new file mode 100644
index 00000000..53258324
--- /dev/null
+++ b/2.x/chapter6-2/src/main/java/com/didispace/chapter62/PersonRepository.java
@@ -0,0 +1,10 @@
+package com.didispace.chapter62;
+
+import org.springframework.data.repository.CrudRepository;
+
+import javax.naming.Name;
+
+public interface PersonRepository extends CrudRepository {
+
+
+}
\ No newline at end of file
diff --git a/2.x/chapter6-2/src/main/resources/application.properties b/2.x/chapter6-2/src/main/resources/application.properties
new file mode 100644
index 00000000..d2726e89
--- /dev/null
+++ b/2.x/chapter6-2/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+#spring.ldap.urls=ldap://localhost:1235
+#spring.ldap.base=dc=didispace,dc=com
+#spring.ldap.username=didispace
+#spring.ldap.password=123456
diff --git a/2.x/chapter6-2/src/test/java/com/didispace/chapter62/ApplicationTests.java b/2.x/chapter6-2/src/test/java/com/didispace/chapter62/ApplicationTests.java
new file mode 100644
index 00000000..b1e2a2fd
--- /dev/null
+++ b/2.x/chapter6-2/src/test/java/com/didispace/chapter62/ApplicationTests.java
@@ -0,0 +1,38 @@
+package com.didispace.chapter62;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@Slf4j
+@SpringBootTest
+public class ApplicationTests {
+
+ @Autowired
+ private PersonRepository personRepository;
+
+ @Test
+ public void findAll() {
+
+ personRepository.findAll().forEach(p -> {
+ System.out.println(p);
+ });
+
+ }
+
+ @Test
+ public void save() {
+ Person person = new Person();
+ person.setUid("uid:1");
+ person.setUserName("AAA");
+ person.setCommonName("aaa");
+ person.setUserPassword("123456");
+ personRepository.save(person);
+
+ personRepository.findAll().forEach(p -> {
+ System.out.println(p);
+ });
+ }
+
+}
diff --git a/2.x/chapter6-2/src/test/resources/application.properties b/2.x/chapter6-2/src/test/resources/application.properties
new file mode 100644
index 00000000..55e19357
--- /dev/null
+++ b/2.x/chapter6-2/src/test/resources/application.properties
@@ -0,0 +1,3 @@
+spring.ldap.embedded.ldif=classpath:ldap-server.ldif
+spring.ldap.embedded.base-dn=dc=didispace,dc=com
+
diff --git a/2.x/chapter6-2/src/test/resources/ldap-server.ldif b/2.x/chapter6-2/src/test/resources/ldap-server.ldif
new file mode 100644
index 00000000..353a4939
--- /dev/null
+++ b/2.x/chapter6-2/src/test/resources/ldap-server.ldif
@@ -0,0 +1,20 @@
+dn: dc=didispace,dc=com
+objectClass: top
+objectClass: domain
+objectclass: extensibleObject
+dc: didispace
+
+dn: ou=people,dc=didispace,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: people
+
+dn: uid=ben,ou=people,dc=didispace,dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: didi
+sn: zhaiyongchao
+uid: didi
+userPassword: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ=
diff --git a/2.x/chapter6-3/pom.xml b/2.x/chapter6-3/pom.xml
new file mode 100644
index 00000000..686e3150
--- /dev/null
+++ b/2.x/chapter6-3/pom.xml
@@ -0,0 +1,59 @@
+
+
+ 4.0.0
+
+ com.didispace
+ chapter6-3
+ 1.0.0
+ jar
+ 使用时序数据库InfluxDB
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+
+ UTF-8
+ 1.8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.influxdb
+ influxdb-java
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter6-3/src/main/java/com/didispace/chapter63/Chapter63Application.java b/2.x/chapter6-3/src/main/java/com/didispace/chapter63/Chapter63Application.java
new file mode 100644
index 00000000..54cc0e22
--- /dev/null
+++ b/2.x/chapter6-3/src/main/java/com/didispace/chapter63/Chapter63Application.java
@@ -0,0 +1,15 @@
+package com.didispace.chapter63;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@EnableScheduling
+@SpringBootApplication
+public class Chapter63Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter63Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter6-3/src/main/java/com/didispace/chapter63/Monitor.java b/2.x/chapter6-3/src/main/java/com/didispace/chapter63/Monitor.java
new file mode 100644
index 00000000..fd62dc20
--- /dev/null
+++ b/2.x/chapter6-3/src/main/java/com/didispace/chapter63/Monitor.java
@@ -0,0 +1,43 @@
+package com.didispace.chapter63;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.influxdb.InfluxDB;
+import org.influxdb.dto.Point;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Created by 程序猿DD on 2021/8/2.
+ *
+ * Blog: http://blog.didispace.com/
+ * Github: https://github.com/dyc87112/
+ */
+@Service
+@AllArgsConstructor
+@Slf4j
+public class Monitor {
+
+ private InfluxDB influxDB;
+
+ @Scheduled(fixedRate = 5000)
+ public void writeQPS() {
+ // 模拟要上报的统计数据
+ int count = (int) (Math.random() * 100);
+
+ Point point = Point.measurement("ApiQPS") // ApiQPS表
+ .tag("url", "/hello") // url字段
+ .addField("count", count) // 统计数据
+ .time(System.currentTimeMillis(), TimeUnit.MILLISECONDS) // 时间
+ .build();
+
+ // 往test库写数据
+ influxDB.write("test", "autogen", point);
+
+ log.info("上报统计数据:" + count);
+ }
+
+}
diff --git a/2.x/chapter6-3/src/main/resources/application.properties b/2.x/chapter6-3/src/main/resources/application.properties
new file mode 100644
index 00000000..0df52b44
--- /dev/null
+++ b/2.x/chapter6-3/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+
+spring.influx.url=http://localhost:8086
+spring.influx.user=admin
+spring.influx.password=
+
diff --git a/2.x/chapter6-3/src/test/java/com/didispace/chapter63/ApplicationTests.java b/2.x/chapter6-3/src/test/java/com/didispace/chapter63/ApplicationTests.java
new file mode 100644
index 00000000..4720d3cc
--- /dev/null
+++ b/2.x/chapter6-3/src/test/java/com/didispace/chapter63/ApplicationTests.java
@@ -0,0 +1,22 @@
+package com.didispace.chapter63;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@Slf4j
+@SpringBootTest
+public class ApplicationTests {
+
+ @Test
+ public void findAll() {
+
+ }
+
+ @Test
+ public void save() {
+
+ }
+
+}
diff --git a/2.x/chapter6-4/pom.xml b/2.x/chapter6-4/pom.xml
new file mode 100644
index 00000000..c1683b06
--- /dev/null
+++ b/2.x/chapter6-4/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+ com.didispace
+ chapter6-4
+ 1.0.0
+ jar
+ 使用PostgreSQL数据库
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+
+ UTF-8
+ 1.8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.postgresql
+ postgresql
+ runtime
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter6-4/src/main/java/com/didispace/chapter64/Chapter64Application.java b/2.x/chapter6-4/src/main/java/com/didispace/chapter64/Chapter64Application.java
new file mode 100644
index 00000000..83ebf477
--- /dev/null
+++ b/2.x/chapter6-4/src/main/java/com/didispace/chapter64/Chapter64Application.java
@@ -0,0 +1,14 @@
+package com.didispace.chapter64;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication
+public class Chapter64Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter64Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter6-4/src/main/java/com/didispace/chapter64/UserInfo.java b/2.x/chapter6-4/src/main/java/com/didispace/chapter64/UserInfo.java
new file mode 100644
index 00000000..cc83d361
--- /dev/null
+++ b/2.x/chapter6-4/src/main/java/com/didispace/chapter64/UserInfo.java
@@ -0,0 +1,26 @@
+package com.didispace.chapter64;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+@Data
+@NoArgsConstructor
+public class UserInfo {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String name;
+ private Integer age;
+
+ public UserInfo(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+}
\ No newline at end of file
diff --git a/2.x/chapter6-4/src/main/java/com/didispace/chapter64/UserInfoRepository.java b/2.x/chapter6-4/src/main/java/com/didispace/chapter64/UserInfoRepository.java
new file mode 100644
index 00000000..85214e24
--- /dev/null
+++ b/2.x/chapter6-4/src/main/java/com/didispace/chapter64/UserInfoRepository.java
@@ -0,0 +1,22 @@
+package com.didispace.chapter64;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+/**
+ * Created by 程序猿DD/翟永超 on 2021/10/08.
+ *
+ * Blog: http://blog.didispace.com/
+ * Github: https://github.com/dyc87112/
+ */
+public interface UserInfoRepository extends JpaRepository {
+
+ UserInfo findByName(String name);
+
+ UserInfo findByNameAndAge(String name, Integer age);
+
+ @Query("from UserInfo u where u.name=:name")
+ UserInfo findUser(@Param("name") String name);
+
+}
diff --git a/2.x/chapter6-4/src/main/resources/application.properties b/2.x/chapter6-4/src/main/resources/application.properties
new file mode 100644
index 00000000..3c000bf2
--- /dev/null
+++ b/2.x/chapter6-4/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+spring.datasource.url=jdbc:postgresql://localhost:5432/test
+spring.datasource.username=postgres
+spring.datasource.password=123456
+spring.datasource.driver-class-name=org.postgresql.Driver
+
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+spring.jpa.properties.hibernate.hbm2ddl.auto=create
\ No newline at end of file
diff --git a/2.x/chapter6-4/src/test/java/com/didispace/chapter64/ApplicationTests.java b/2.x/chapter6-4/src/test/java/com/didispace/chapter64/ApplicationTests.java
new file mode 100644
index 00000000..1ae64fb4
--- /dev/null
+++ b/2.x/chapter6-4/src/test/java/com/didispace/chapter64/ApplicationTests.java
@@ -0,0 +1,51 @@
+package com.didispace.chapter64;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@Slf4j
+@SpringBootTest
+public class ApplicationTests {
+
+ @Autowired
+ private UserInfoRepository userRepository;
+
+ @Test
+ public void test() throws Exception {
+ // 创建10条记录
+ userRepository.save(new UserInfo("AAA", 10));
+ userRepository.save(new UserInfo("BBB", 20));
+ userRepository.save(new UserInfo("CCC", 30));
+ userRepository.save(new UserInfo("DDD", 40));
+ userRepository.save(new UserInfo("EEE", 50));
+ userRepository.save(new UserInfo("FFF", 60));
+ userRepository.save(new UserInfo("GGG", 70));
+ userRepository.save(new UserInfo("HHH", 80));
+ userRepository.save(new UserInfo("III", 90));
+ userRepository.save(new UserInfo("JJJ", 100));
+
+ // 测试findAll, 查询所有记录
+ Assertions.assertEquals(10, userRepository.findAll().size());
+
+ // 测试findByName, 查询姓名为FFF的User
+ Assertions.assertEquals(60, userRepository.findByName("FFF").getAge().longValue());
+
+ // 测试findUser, 查询姓名为FFF的User
+ Assertions.assertEquals(60, userRepository.findUser("FFF").getAge().longValue());
+
+ // 测试findByNameAndAge, 查询姓名为FFF并且年龄为60的User
+ Assertions.assertEquals("FFF", userRepository.findByNameAndAge("FFF", 60).getName());
+
+ // 测试删除姓名为AAA的User
+ userRepository.delete(userRepository.findByName("AAA"));
+
+ // 测试findAll, 查询所有记录, 验证上面的删除是否成功
+ Assertions.assertEquals(9, userRepository.findAll().size());
+
+ }
+
+}
diff --git a/2.x/chapter7-1/pom.xml b/2.x/chapter7-1/pom.xml
new file mode 100755
index 00000000..fc9142ad
--- /dev/null
+++ b/2.x/chapter7-1/pom.xml
@@ -0,0 +1,50 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+ com.didispace
+ chapter7-1
+ 0.0.1-SNAPSHOT
+ 使用@Scheduled实现定时任务
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter7-1/src/main/java/com/didispace/chapter71/Chapter71Application.java b/2.x/chapter7-1/src/main/java/com/didispace/chapter71/Chapter71Application.java
new file mode 100755
index 00000000..95fd0d2d
--- /dev/null
+++ b/2.x/chapter7-1/src/main/java/com/didispace/chapter71/Chapter71Application.java
@@ -0,0 +1,15 @@
+package com.didispace.chapter71;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@EnableScheduling
+@SpringBootApplication
+public class Chapter71Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter71Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter7-1/src/main/java/com/didispace/chapter71/ScheduledTasks.java b/2.x/chapter7-1/src/main/java/com/didispace/chapter71/ScheduledTasks.java
new file mode 100644
index 00000000..27f1d0db
--- /dev/null
+++ b/2.x/chapter7-1/src/main/java/com/didispace/chapter71/ScheduledTasks.java
@@ -0,0 +1,24 @@
+package com.didispace.chapter71;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@Slf4j
+@Component
+@AllArgsConstructor
+public class ScheduledTasks {
+
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
+
+
+ @Scheduled(fixedRate = 5000)
+ public void reportCurrentTime() {
+ log.info("现在时间:" + dateFormat.format(new Date()));
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter7-1/src/main/resources/application.properties b/2.x/chapter7-1/src/main/resources/application.properties
new file mode 100644
index 00000000..e69de29b
diff --git a/2.x/chapter7-2/pom.xml b/2.x/chapter7-2/pom.xml
new file mode 100755
index 00000000..e1987da5
--- /dev/null
+++ b/2.x/chapter7-2/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+ com.didispace
+ chapter7-2
+ 0.0.1-SNAPSHOT
+ 使用Elastic Job实现定时任务
+
+
+ 1.8
+
+
+
+
+ org.apache.shardingsphere.elasticjob
+ elasticjob-lite-spring-boot-starter
+ 3.0.0
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter7-2/src/main/java/com/didispace/chapter72/Chapter72Application.java b/2.x/chapter7-2/src/main/java/com/didispace/chapter72/Chapter72Application.java
new file mode 100755
index 00000000..236357d8
--- /dev/null
+++ b/2.x/chapter7-2/src/main/java/com/didispace/chapter72/Chapter72Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter72;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter72Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter72Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter7-2/src/main/java/com/didispace/chapter72/MySimpleJob.java b/2.x/chapter7-2/src/main/java/com/didispace/chapter72/MySimpleJob.java
new file mode 100644
index 00000000..242a8168
--- /dev/null
+++ b/2.x/chapter7-2/src/main/java/com/didispace/chapter72/MySimpleJob.java
@@ -0,0 +1,17 @@
+package com.didispace.chapter72;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.api.ShardingContext;
+import org.apache.shardingsphere.elasticjob.simple.job.SimpleJob;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class MySimpleJob implements SimpleJob {
+
+ @Override
+ public void execute(ShardingContext context) {
+ log.info("MySimpleJob start : didispace.com {}", System.currentTimeMillis());
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter7-2/src/main/resources/application.properties b/2.x/chapter7-2/src/main/resources/application.properties
new file mode 100644
index 00000000..38bca408
--- /dev/null
+++ b/2.x/chapter7-2/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+
+elasticjob.reg-center.server-lists=localhost:2181
+elasticjob.reg-center.namespace=didispace
+
+elasticjob.jobs.my-simple-job.elastic-job-class=com.didispace.chapter72.MySimpleJob
+elasticjob.jobs.my-simple-job.cron=0/5 * * * * ?
+elasticjob.jobs.my-simple-job.sharding-total-count=1
diff --git a/2.x/chapter7-3/pom.xml b/2.x/chapter7-3/pom.xml
new file mode 100755
index 00000000..55d4ff9f
--- /dev/null
+++ b/2.x/chapter7-3/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+ com.didispace
+ chapter7-3
+ 0.0.1-SNAPSHOT
+ 使用Elastic Job的分片配置
+
+
+ 1.8
+
+
+
+
+ org.apache.shardingsphere.elasticjob
+ elasticjob-lite-spring-boot-starter
+ 3.0.0
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter7-3/src/main/java/com/didispace/chapter73/Chapter73Application.java b/2.x/chapter7-3/src/main/java/com/didispace/chapter73/Chapter73Application.java
new file mode 100755
index 00000000..5c62c3e6
--- /dev/null
+++ b/2.x/chapter7-3/src/main/java/com/didispace/chapter73/Chapter73Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter73;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter73Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter73Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter7-3/src/main/java/com/didispace/chapter73/MyShardingJob.java b/2.x/chapter7-3/src/main/java/com/didispace/chapter73/MyShardingJob.java
new file mode 100644
index 00000000..d1f535ae
--- /dev/null
+++ b/2.x/chapter7-3/src/main/java/com/didispace/chapter73/MyShardingJob.java
@@ -0,0 +1,28 @@
+package com.didispace.chapter73;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.api.ShardingContext;
+import org.apache.shardingsphere.elasticjob.simple.job.SimpleJob;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class MyShardingJob implements SimpleJob {
+
+ @Override
+ public void execute(ShardingContext context) {
+ // sharding-total-count=3,所以任务被分为三个分片
+ switch (context.getShardingItem()) {
+ case 0:
+ log.info("分片1:执行任务");
+ break;
+ case 1:
+ log.info("分片2:执行任务");
+ break;
+ case 2:
+ log.info("分片3:执行任务");
+ break;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter7-3/src/main/resources/application.properties b/2.x/chapter7-3/src/main/resources/application.properties
new file mode 100644
index 00000000..cb7d3cd8
--- /dev/null
+++ b/2.x/chapter7-3/src/main/resources/application.properties
@@ -0,0 +1,6 @@
+elasticjob.reg-center.server-lists=localhost:2181
+elasticjob.reg-center.namespace=didispace
+
+elasticjob.jobs.my-sharding-job.elastic-job-class=com.didispace.chapter73.MyShardingJob
+elasticjob.jobs.my-sharding-job.cron=0/5 * * * * ?
+elasticjob.jobs.my-sharding-job.sharding-total-count=3
diff --git a/2.x/chapter7-4/pom.xml b/2.x/chapter7-4/pom.xml
new file mode 100755
index 00000000..5bab3842
--- /dev/null
+++ b/2.x/chapter7-4/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+ com.didispace
+ chapter7-4
+ 0.0.1-SNAPSHOT
+ Elastic Job的错误处理策略
+
+
+ 1.8
+
+
+
+
+ org.apache.shardingsphere.elasticjob
+ elasticjob-lite-spring-boot-starter
+ 3.0.0
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter7-4/src/main/java/com/didispace/chapter74/Chapter74Application.java b/2.x/chapter7-4/src/main/java/com/didispace/chapter74/Chapter74Application.java
new file mode 100644
index 00000000..e2674e95
--- /dev/null
+++ b/2.x/chapter7-4/src/main/java/com/didispace/chapter74/Chapter74Application.java
@@ -0,0 +1,13 @@
+package com.didispace.chapter74;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Chapter74Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter74Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter7-4/src/main/java/com/didispace/chapter74/MySimpleJob.java b/2.x/chapter7-4/src/main/java/com/didispace/chapter74/MySimpleJob.java
new file mode 100644
index 00000000..4e651c3e
--- /dev/null
+++ b/2.x/chapter7-4/src/main/java/com/didispace/chapter74/MySimpleJob.java
@@ -0,0 +1,17 @@
+package com.didispace.chapter74;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.api.ShardingContext;
+import org.apache.shardingsphere.elasticjob.simple.job.SimpleJob;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class MySimpleJob implements SimpleJob {
+
+ @Override
+ public void execute(ShardingContext context) {
+ log.info("MySimpleJob start : didispace.com {}", System.currentTimeMillis());
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter7-4/src/main/resources/application.properties b/2.x/chapter7-4/src/main/resources/application.properties
new file mode 100644
index 00000000..16a59e0f
--- /dev/null
+++ b/2.x/chapter7-4/src/main/resources/application.properties
@@ -0,0 +1,8 @@
+spring.application.name=chapter74
+
+elasticjob.reg-center.server-lists=localhost:2181
+elasticjob.reg-center.namespace=${spring.application.name}
+
+elasticjob.jobs.my-simple-job.elastic-job-class=com.didispace.chapter74.MySimpleJob
+elasticjob.jobs.my-simple-job.cron=0/5 * * * * ?
+elasticjob.jobs.my-simple-job.sharding-total-count=1
diff --git a/2.x/chapter7-5/pom.xml b/2.x/chapter7-5/pom.xml
new file mode 100755
index 00000000..4ff53d56
--- /dev/null
+++ b/2.x/chapter7-5/pom.xml
@@ -0,0 +1,50 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+ com.didispace
+ chapter7-5
+ 0.0.1-SNAPSHOT
+ 使用@Async实现异步任务
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter7-5/src/main/java/com/didispace/chapter75/AsyncTasks.java b/2.x/chapter7-5/src/main/java/com/didispace/chapter75/AsyncTasks.java
new file mode 100644
index 00000000..e2f1be13
--- /dev/null
+++ b/2.x/chapter7-5/src/main/java/com/didispace/chapter75/AsyncTasks.java
@@ -0,0 +1,46 @@
+package com.didispace.chapter75;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+
+@Slf4j
+@Component
+public class AsyncTasks {
+
+ public static Random random = new Random();
+
+ @Async
+ public CompletableFuture doTaskOne() throws Exception {
+ log.info("开始做任务一");
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务一,耗时:" + (end - start) + "毫秒");
+ return CompletableFuture.completedFuture("任务一完成");
+ }
+
+ @Async
+ public CompletableFuture doTaskTwo() throws Exception {
+ log.info("开始做任务二");
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务二,耗时:" + (end - start) + "毫秒");
+ return CompletableFuture.completedFuture("任务二完成");
+ }
+
+ @Async
+ public CompletableFuture doTaskThree() throws Exception {
+ log.info("开始做任务三");
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务三,耗时:" + (end - start) + "毫秒");
+ return CompletableFuture.completedFuture("任务三完成");
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter7-5/src/main/java/com/didispace/chapter75/Chapter75Application.java b/2.x/chapter7-5/src/main/java/com/didispace/chapter75/Chapter75Application.java
new file mode 100644
index 00000000..e8aef549
--- /dev/null
+++ b/2.x/chapter7-5/src/main/java/com/didispace/chapter75/Chapter75Application.java
@@ -0,0 +1,15 @@
+package com.didispace.chapter75;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+@EnableAsync
+@SpringBootApplication
+public class Chapter75Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter75Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter7-5/src/main/resources/application.properties b/2.x/chapter7-5/src/main/resources/application.properties
new file mode 100644
index 00000000..e69de29b
diff --git a/2.x/chapter7-5/src/test/java/com/didispace/chapter75/Chapter75ApplicationTests.java b/2.x/chapter7-5/src/test/java/com/didispace/chapter75/Chapter75ApplicationTests.java
new file mode 100644
index 00000000..af32b972
--- /dev/null
+++ b/2.x/chapter7-5/src/test/java/com/didispace/chapter75/Chapter75ApplicationTests.java
@@ -0,0 +1,33 @@
+package com.didispace.chapter75;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+
+@Slf4j
+@SpringBootTest
+public class Chapter75ApplicationTests {
+
+ @Autowired
+ private AsyncTasks asyncTasks;
+
+ @Test
+ public void test() throws Exception {
+ long start = System.currentTimeMillis();
+
+ CompletableFuture task1 = asyncTasks.doTaskOne();
+ CompletableFuture task2 = asyncTasks.doTaskTwo();
+ CompletableFuture task3 = asyncTasks.doTaskThree();
+
+ CompletableFuture.allOf(task1, task2, task3).join();
+
+ long end = System.currentTimeMillis();
+
+ log.info("任务全部完成,总耗时:" + (end - start) + "毫秒");
+ }
+
+}
diff --git a/2.x/chapter7-6/pom.xml b/2.x/chapter7-6/pom.xml
new file mode 100755
index 00000000..c67956f5
--- /dev/null
+++ b/2.x/chapter7-6/pom.xml
@@ -0,0 +1,50 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+ com.didispace
+ chapter7-6
+ 0.0.1-SNAPSHOT
+ @Async异步任务的线程池配置
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter7-6/src/main/java/com/didispace/chapter76/AsyncTasks.java b/2.x/chapter7-6/src/main/java/com/didispace/chapter76/AsyncTasks.java
new file mode 100644
index 00000000..66a01d8e
--- /dev/null
+++ b/2.x/chapter7-6/src/main/java/com/didispace/chapter76/AsyncTasks.java
@@ -0,0 +1,47 @@
+package com.didispace.chapter76;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+
+@Slf4j
+@Component
+public class AsyncTasks {
+
+ public static Random random = new Random();
+
+ @Async
+ public CompletableFuture doTaskOne() throws Exception {
+ log.info("开始做任务一");
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务一,耗时:" + (end - start) + "毫秒");
+ return CompletableFuture.completedFuture("任务一完成");
+ }
+
+ @Async
+ public CompletableFuture doTaskTwo() throws Exception {
+ log.info("开始做任务二");
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务二,耗时:" + (end - start) + "毫秒");
+ return CompletableFuture.completedFuture("任务二完成");
+ }
+
+ @Async
+ public CompletableFuture doTaskThree() throws Exception {
+ log.info("开始做任务三");
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务三,耗时:" + (end - start) + "毫秒");
+ return CompletableFuture.completedFuture("任务三完成");
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter7-6/src/main/java/com/didispace/chapter76/Chapter76Application.java b/2.x/chapter7-6/src/main/java/com/didispace/chapter76/Chapter76Application.java
new file mode 100644
index 00000000..4f856eba
--- /dev/null
+++ b/2.x/chapter7-6/src/main/java/com/didispace/chapter76/Chapter76Application.java
@@ -0,0 +1,15 @@
+package com.didispace.chapter76;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+@EnableAsync
+@SpringBootApplication
+public class Chapter76Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter76Application.class, args);
+ }
+
+}
diff --git a/2.x/chapter7-6/src/main/resources/application.properties b/2.x/chapter7-6/src/main/resources/application.properties
new file mode 100644
index 00000000..070a4b71
--- /dev/null
+++ b/2.x/chapter7-6/src/main/resources/application.properties
@@ -0,0 +1,9 @@
+spring.task.execution.pool.core-size=2
+spring.task.execution.pool.max-size=5
+spring.task.execution.pool.queue-capacity=10
+spring.task.execution.pool.keep-alive=60s
+spring.task.execution.pool.allow-core-thread-timeout=true
+spring.task.execution.thread-name-prefix=task-
+
+spring.task.execution.shutdown.await-termination=false
+spring.task.execution.shutdown.await-termination-period=30s
\ No newline at end of file
diff --git a/2.x/chapter7-6/src/test/java/com/didispace/chapter76/Chapter76ApplicationTests.java b/2.x/chapter7-6/src/test/java/com/didispace/chapter76/Chapter76ApplicationTests.java
new file mode 100644
index 00000000..2a832502
--- /dev/null
+++ b/2.x/chapter7-6/src/test/java/com/didispace/chapter76/Chapter76ApplicationTests.java
@@ -0,0 +1,32 @@
+package com.didispace.chapter76;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.concurrent.CompletableFuture;
+
+@Slf4j
+@SpringBootTest
+public class Chapter76ApplicationTests {
+
+ @Autowired
+ private AsyncTasks asyncTasks;
+
+ @Test
+ public void test1() throws Exception {
+ long start = System.currentTimeMillis();
+
+ CompletableFuture task1 = asyncTasks.doTaskOne();
+ CompletableFuture task2 = asyncTasks.doTaskTwo();
+ CompletableFuture task3 = asyncTasks.doTaskThree();
+
+ CompletableFuture.allOf(task1, task2, task3).join();
+
+ long end = System.currentTimeMillis();
+
+ log.info("任务全部完成,总耗时:" + (end - start) + "毫秒");
+ }
+
+}
diff --git a/2.x/chapter7-7/pom.xml b/2.x/chapter7-7/pom.xml
new file mode 100755
index 00000000..2a69afe0
--- /dev/null
+++ b/2.x/chapter7-7/pom.xml
@@ -0,0 +1,50 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+ com.didispace
+ chapter7-7
+ 0.0.1-SNAPSHOT
+ 如何隔离@Async异步任务的线程池
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter7-7/src/main/java/com/didispace/chapter77/AsyncTasks.java b/2.x/chapter7-7/src/main/java/com/didispace/chapter77/AsyncTasks.java
new file mode 100644
index 00000000..90185dc8
--- /dev/null
+++ b/2.x/chapter7-7/src/main/java/com/didispace/chapter77/AsyncTasks.java
@@ -0,0 +1,36 @@
+package com.didispace.chapter77;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+
+@Slf4j
+@Component
+public class AsyncTasks {
+
+ public static Random random = new Random();
+
+ @Async("taskExecutor1")
+ public CompletableFuture doTaskOne(String taskNo) throws Exception {
+ log.info("开始任务:{}", taskNo);
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务:{},耗时:{} 毫秒", taskNo, end - start);
+ return CompletableFuture.completedFuture("任务完成");
+ }
+
+ @Async("taskExecutor2")
+ public CompletableFuture doTaskTwo(String taskNo) throws Exception {
+ log.info("开始任务:{}", taskNo);
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务:{},耗时:{} 毫秒", taskNo, end - start);
+ return CompletableFuture.completedFuture("任务完成");
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter7-7/src/main/java/com/didispace/chapter77/Chapter77Application.java b/2.x/chapter7-7/src/main/java/com/didispace/chapter77/Chapter77Application.java
new file mode 100644
index 00000000..e598f26d
--- /dev/null
+++ b/2.x/chapter7-7/src/main/java/com/didispace/chapter77/Chapter77Application.java
@@ -0,0 +1,55 @@
+package com.didispace.chapter77;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+@EnableAsync
+@SpringBootApplication
+public class Chapter77Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter77Application.class, args);
+ }
+
+ @EnableAsync
+ @Configuration
+ class TaskPoolConfig {
+
+ @Bean
+ public Executor taskExecutor1() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(2);
+ executor.setMaxPoolSize(2);
+ executor.setQueueCapacity(10);
+ executor.setKeepAliveSeconds(60);
+ executor.setThreadNamePrefix("executor-1-");
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ return executor;
+ }
+
+ @Bean
+ public Executor taskExecutor2() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(2);
+ executor.setMaxPoolSize(2);
+ executor.setQueueCapacity(10);
+ executor.setKeepAliveSeconds(60);
+ executor.setThreadNamePrefix("executor-2-");
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ return executor;
+ }
+
+ }
+
+}
diff --git a/2.x/chapter7-7/src/main/resources/application.properties b/2.x/chapter7-7/src/main/resources/application.properties
new file mode 100644
index 00000000..e69de29b
diff --git a/2.x/chapter7-7/src/test/java/com/didispace/chapter77/Chapter77ApplicationTests.java b/2.x/chapter7-7/src/test/java/com/didispace/chapter77/Chapter77ApplicationTests.java
new file mode 100644
index 00000000..d6479787
--- /dev/null
+++ b/2.x/chapter7-7/src/test/java/com/didispace/chapter77/Chapter77ApplicationTests.java
@@ -0,0 +1,40 @@
+package com.didispace.chapter77;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+
+@Slf4j
+@SpringBootTest
+public class Chapter77ApplicationTests {
+
+ @Autowired
+ private AsyncTasks asyncTasks;
+
+ @Test
+ public void test() throws Exception {
+ long start = System.currentTimeMillis();
+
+ // 线程池1
+ CompletableFuture task1 = asyncTasks.doTaskOne("1");
+ CompletableFuture task2 = asyncTasks.doTaskOne("2");
+ CompletableFuture task3 = asyncTasks.doTaskOne("3");
+
+ // 线程池2
+ CompletableFuture task4 = asyncTasks.doTaskTwo("4");
+ CompletableFuture task5 = asyncTasks.doTaskTwo("5");
+ CompletableFuture task6 = asyncTasks.doTaskTwo("6");
+
+ // 一起执行
+ CompletableFuture.allOf(task1, task2, task3, task4, task5, task6).join();
+
+ long end = System.currentTimeMillis();
+
+ log.info("任务全部完成,总耗时:" + (end - start) + "毫秒");
+ }
+
+}
diff --git a/2.x/chapter7-8/pom.xml b/2.x/chapter7-8/pom.xml
new file mode 100755
index 00000000..40158a94
--- /dev/null
+++ b/2.x/chapter7-8/pom.xml
@@ -0,0 +1,50 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+ com.didispace
+ chapter7-8
+ 0.0.1-SNAPSHOT
+ 为@Async异步任务线程池配置拒绝策略
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2.x/chapter7-8/src/main/java/com/didispace/chapter78/AsyncTasks.java b/2.x/chapter7-8/src/main/java/com/didispace/chapter78/AsyncTasks.java
new file mode 100644
index 00000000..5cb782f5
--- /dev/null
+++ b/2.x/chapter7-8/src/main/java/com/didispace/chapter78/AsyncTasks.java
@@ -0,0 +1,26 @@
+package com.didispace.chapter78;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+
+@Slf4j
+@Component
+public class AsyncTasks {
+
+ public static Random random = new Random();
+
+ @Async("taskExecutor1")
+ public CompletableFuture doTaskOne(String taskNo) throws Exception {
+ log.info("开始任务:{}", taskNo);
+ long start = System.currentTimeMillis();
+ Thread.sleep(random.nextInt(10000));
+ long end = System.currentTimeMillis();
+ log.info("完成任务:{},耗时:{} 毫秒", taskNo, end - start);
+ return CompletableFuture.completedFuture("任务完成");
+ }
+
+}
\ No newline at end of file
diff --git a/2.x/chapter7-8/src/main/java/com/didispace/chapter78/Chapter78Application.java b/2.x/chapter7-8/src/main/java/com/didispace/chapter78/Chapter78Application.java
new file mode 100644
index 00000000..f04169be
--- /dev/null
+++ b/2.x/chapter7-8/src/main/java/com/didispace/chapter78/Chapter78Application.java
@@ -0,0 +1,60 @@
+package com.didispace.chapter78;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+
+@EnableAsync
+@SpringBootApplication
+public class Chapter78Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter78Application.class, args);
+ }
+
+ @EnableAsync
+ @Configuration
+ class TaskPoolConfig {
+
+ @Bean
+ public Executor taskExecutor1() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(2);
+ executor.setMaxPoolSize(2);
+ executor.setQueueCapacity(2);
+ executor.setKeepAliveSeconds(60);
+ executor.setThreadNamePrefix("executor-1-");
+
+ /**配置拒绝策略**/
+
+ // AbortPolicy策略:默认策略,如果线程池队列满了丢掉这个任务并且抛出RejectedExecutionException异常。
+// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
+
+ // DiscardPolicy策略:如果线程池队列满了,会直接丢掉这个任务并且不会有任何异常。
+// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
+
+ // DiscardOldestPolicy策略:如果队列满了,会将最早进入队列的任务删掉腾出空间,再尝试加入队列。
+// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
+
+ // CallerRunsPolicy策略:如果添加到线程池失败,那么主线程会自己去执行该任务,不会等待线程池中的线程去执行。
+// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+
+ // 自定义策略
+// executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
+// @Override
+// public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
+//
+// }
+// });
+
+ return executor;
+ }
+
+ }
+
+}
diff --git a/2.x/chapter7-8/src/main/resources/application.properties b/2.x/chapter7-8/src/main/resources/application.properties
new file mode 100644
index 00000000..e69de29b
diff --git a/2.x/chapter7-8/src/test/java/com/didispace/chapter78/Chapter78ApplicationTests.java b/2.x/chapter7-8/src/test/java/com/didispace/chapter78/Chapter78ApplicationTests.java
new file mode 100644
index 00000000..6b9a3919
--- /dev/null
+++ b/2.x/chapter7-8/src/test/java/com/didispace/chapter78/Chapter78ApplicationTests.java
@@ -0,0 +1,61 @@
+package com.didispace.chapter78;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+
+@Slf4j
+@SpringBootTest
+public class Chapter78ApplicationTests {
+
+ @Autowired
+ private AsyncTasks asyncTasks;
+
+ @Test
+ public void test() throws Exception {
+ // 线程池配置:core-2,max-2,queue=2,可以容纳4个任务提交
+
+ long start = System.currentTimeMillis();
+
+ // 线程池1
+ CompletableFuture task1 = asyncTasks.doTaskOne("1");
+ CompletableFuture task2 = asyncTasks.doTaskOne("2");
+ CompletableFuture task3 = asyncTasks.doTaskOne("3");
+ CompletableFuture task4 = asyncTasks.doTaskOne("4");
+
+ // 一起执行
+ CompletableFuture.allOf(task1, task2, task3, task4).join();
+
+ long end = System.currentTimeMillis();
+
+ log.info("任务全部完成,总耗时:" + (end - start) + "毫秒");
+ }
+
+ @Test
+ public void test2() throws Exception {
+ // 线程池配置:core-2,max-2,queue=2,同时有5个任务,出现下面异常:
+ // org.springframework.core.task.TaskRejectedException: Executor [java.util.concurrent.ThreadPoolExecutor@59901c4d[Running, pool size = 2,
+ // active threads = 0, queued tasks = 2, completed tasks = 4]] did not accept task: java.util.concurrent.CompletableFuture$AsyncSupply@408e96d9
+
+ long start = System.currentTimeMillis();
+
+ // 线程池1
+ CompletableFuture task1 = asyncTasks.doTaskOne("1");
+ CompletableFuture task2 = asyncTasks.doTaskOne("2");
+ CompletableFuture task3 = asyncTasks.doTaskOne("3");
+ CompletableFuture task4 = asyncTasks.doTaskOne("4");
+ CompletableFuture task5 = asyncTasks.doTaskOne("5");
+
+ // 一起执行
+ CompletableFuture.allOf(task1, task2, task3, task4, task5).join();
+
+ long end = System.currentTimeMillis();
+
+ log.info("任务全部完成,总耗时:" + (end - start) + "毫秒");
+ }
+
+}
diff --git a/2.x/chapter8-1/pom.xml b/2.x/chapter8-1/pom.xml
new file mode 100644
index 00000000..d60616ec
--- /dev/null
+++ b/2.x/chapter8-1/pom.xml
@@ -0,0 +1,54 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.1
+
+
+
+ com.didispace
+ chapter8-1
+ 0.0.1-SNAPSHOT
+ 默认日志管理与Logback配置详解
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter8-1/src/main/java/com/didispace/chapter81/Chapter81Application.java b/2.x/chapter8-1/src/main/java/com/didispace/chapter81/Chapter81Application.java
new file mode 100644
index 00000000..a8fec0e0
--- /dev/null
+++ b/2.x/chapter8-1/src/main/java/com/didispace/chapter81/Chapter81Application.java
@@ -0,0 +1,26 @@
+package com.didispace.chapter81;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @blog https://blog.didispace.com
+ */
+@Slf4j
+@SpringBootApplication
+public class Chapter81Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter81Application.class, args);
+
+ log.error("Hello World");
+ log.warn("Hello World");
+ log.info("Hello World");
+ log.debug("Hello World");
+ log.trace("Hello World");
+ }
+
+}
diff --git a/2.x/chapter8-1/src/main/resources/application.properties b/2.x/chapter8-1/src/main/resources/application.properties
new file mode 100644
index 00000000..361847c5
--- /dev/null
+++ b/2.x/chapter8-1/src/main/resources/application.properties
@@ -0,0 +1,14 @@
+debug=true
+
+spring.output.ansi.enabled=detect
+
+logging.file.name=run.log
+logging.file.path=./
+
+logging.level.com.didispace=debug
+
+logging.logback.rollingpolicy.clean-history-on-start=false
+logging.logback.rollingpolicy.file-name-pattern=
+logging.logback.rollingpolicy.max-history=7
+logging.logback.rollingpolicy.max-file-size=10MB
+logging.logback.rollingpolicy.total-size-cap=0B
diff --git a/2.x/chapter8-2/pom.xml b/2.x/chapter8-2/pom.xml
new file mode 100644
index 00000000..eeda9143
--- /dev/null
+++ b/2.x/chapter8-2/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.1
+
+
+
+ com.didispace
+ chapter8-2
+ 0.0.1-SNAPSHOT
+ 使用log4j2记录日志
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter8-2/src/main/java/com/didispace/chapter82/Chapter82Application.java b/2.x/chapter8-2/src/main/java/com/didispace/chapter82/Chapter82Application.java
new file mode 100644
index 00000000..be62c0c2
--- /dev/null
+++ b/2.x/chapter8-2/src/main/java/com/didispace/chapter82/Chapter82Application.java
@@ -0,0 +1,26 @@
+package com.didispace.chapter82;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @blog https://blog.didispace.com
+ */
+@Slf4j
+@SpringBootApplication
+public class Chapter82Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter82Application.class, args);
+
+ log.error("Hello World");
+ log.warn("Hello World");
+ log.info("Hello World");
+ log.debug("Hello World");
+ log.trace("Hello World");
+ }
+
+}
diff --git a/2.x/chapter8-2/src/main/resources/application.properties b/2.x/chapter8-2/src/main/resources/application.properties
new file mode 100644
index 00000000..b642e6f9
--- /dev/null
+++ b/2.x/chapter8-2/src/main/resources/application.properties
@@ -0,0 +1,2 @@
+
+logging.config=classpath:log4j2.xml
\ No newline at end of file
diff --git a/2.x/chapter8-2/src/main/resources/log4j2.xml b/2.x/chapter8-2/src/main/resources/log4j2.xml
new file mode 100644
index 00000000..18ca1279
--- /dev/null
+++ b/2.x/chapter8-2/src/main/resources/log4j2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/2.x/chapter8-3/pom.xml b/2.x/chapter8-3/pom.xml
new file mode 100644
index 00000000..d6a578e8
--- /dev/null
+++ b/2.x/chapter8-3/pom.xml
@@ -0,0 +1,81 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.1
+
+
+
+ com.didispace
+ chapter8-3
+ 0.0.1-SNAPSHOT
+ 使用tinylog记录日志
+
+
+ UTF-8
+ 1.8
+ 2.4.1
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+
+ org.tinylog
+ tinylog-api
+ ${tinylog.version}
+
+
+ org.tinylog
+ tinylog-impl
+ ${tinylog.version}
+
+
+ org.tinylog
+ slf4j-tinylog
+ ${tinylog.version}
+
+
+ org.tinylog
+ jcl-tinylog
+ ${tinylog.version}
+
+
+ org.tinylog
+ log4j1.2-api
+ ${tinylog.version}
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2.x/chapter8-3/src/main/java/com/didispace/chapter83/Chapter83Application.java b/2.x/chapter8-3/src/main/java/com/didispace/chapter83/Chapter83Application.java
new file mode 100644
index 00000000..8a68d462
--- /dev/null
+++ b/2.x/chapter8-3/src/main/java/com/didispace/chapter83/Chapter83Application.java
@@ -0,0 +1,26 @@
+package com.didispace.chapter83;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @author 程序猿DD
+ * @version 1.0.0
+ * @blog https://blog.didispace.com
+ */
+@Slf4j
+@SpringBootApplication
+public class Chapter83Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Chapter83Application.class, args);
+
+ log.error("Hello World");
+ log.warn("Hello World");
+ log.info("Hello World");
+ log.debug("Hello World");
+ log.trace("Hello World");
+ }
+
+}
diff --git a/2.x/chapter8-3/src/main/resources/application.properties b/2.x/chapter8-3/src/main/resources/application.properties
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/2.x/chapter8-3/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/2.x/chapter8-3/src/main/resources/tinylog.properties b/2.x/chapter8-3/src/main/resources/tinylog.properties
new file mode 100644
index 00000000..9eb1b999
--- /dev/null
+++ b/2.x/chapter8-3/src/main/resources/tinylog.properties
@@ -0,0 +1,2 @@
+writer=console
+writer.format={date: HH:mm:ss.SSS} {level}: {message}
\ No newline at end of file
diff --git a/2.x/pom.xml b/2.x/pom.xml
new file mode 100644
index 00000000..f20e1714
--- /dev/null
+++ b/2.x/pom.xml
@@ -0,0 +1,94 @@
+
+
+ 4.0.0
+
+ com.didispace
+ 2.x
+ 2.0-SNAPSHOT
+ pom
+ 全网Star最多的Spring Boot基础教程
+
+
+
+ chapter1-1
+
+
+ chapter1-2
+ chapter1-3
+ chapter1-4
+ chapter1-5
+
+
+ chapter2-1
+ chapter2-2
+ chapter2-3
+ chapter2-4
+ chapter2-5
+ chapter2-6
+ chapter2-7
+ chapter2-8
+
+
+
+
+ chapter3-1
+ chapter3-2
+ chapter3-3
+ chapter3-4
+ chapter3-5
+ chapter3-6
+ chapter3-7
+ chapter3-8
+ chapter3-9
+ chapter3-10
+ chapter3-11
+ chapter3-12
+ chapter3-13
+
+
+
+
+
+ chapter4-1
+ chapter4-2
+ chapter4-3
+ chapter4-4
+ chapter4-5
+
+
+ chapter5-1
+ chapter5-2
+ chapter5-3
+ chapter5-4
+ chapter5-5
+
+
+
+ chapter6-1
+ chapter6-2
+ chapter6-3
+ chapter6-4
+
+
+
+ chapter7-1
+ chapter7-2
+ chapter7-3
+ chapter7-4
+ chapter7-5
+ chapter7-6
+ chapter7-7
+ chapter7-8
+
+
+
+ chapter8-1
+ chapter8-2
+ chapter8-3
+
+
+
+
+
+
diff --git a/README.md b/README.md
index 246c35d5..916c7fa4 100644
--- a/README.md
+++ b/README.md
@@ -1,71 +1,37 @@
# Spring Boot基础教程
-本项目内容为[《Spring Boot基础教程》](http://blog.didispace.com/Spring-Boot%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/)的程序样例。
-
**专题目标**:打造全网内容最全,比收费教程更好的Spring Boot免费教程!
**如何支持**:
+
1. 关注我的公众号”**程序猿DD**“
2. 点个`Star`并`Follow`我
3. 把该仓库分享给更多的朋友
-如果您对文字类教程不感冒或者想要通过综合案例学习Spring,那么给您推荐这个我觉得目前内容与价格最良心的视频课程:["玩转Spring全家桶"](https://time.geekbang.org/course/intro/100023501?code=d1se%2F7ugeBEyuU%2FIYp1ynfSZa6ulbGhhDK%2Fkpn3-lFc%3D)
+**加入社群**:如果你正在学习Spring Boot,不妨加入我们的[Spring技术交流群](https://blog.didispace.com/join-group-spring/index.html) ,一起成长
+
+**Spring社区**:如果您在学习过程中碰到问题,可以访问[SpringForAll社区](http://spring4all.com),描述你的问题,我们会尽快给你答复。当然,如果你想分享你的学习经验,也可以在这里发表你的文章
## 教程目录
-- [Spring Boot 1.x 版本教程](./1.x)
-- [Spring Boot 2.x 版本教程](./2.1.x)
+该教程自2016年连载至今,因内容较多,经历过多个版本的迭代。
-> **关注公众号:“程序猿DD”**,领取我整理的免费学习资料。
+为方便查看学习,这里重新做了整理,根据1.x版本和2.x版本做了区分汇总,后续还会继续跟进3.x版本!
-## 特别赞助商
+可以通过下面的链接,进入具体版本的教程目录:
-
+- [Spring Boot 2.x](./2.x)
+- [Spring Boot 1.x](./1.x)
-> 如果您也想赞助支持并出现在上表中的话,可以通过邮件联系我:`didi@didispace.com`
+> **关注公众号:“程序猿DD”**,领取我整理的免费学习资料。
## 推荐内容
- [我的博客](http://blog.didispace.com):分享平时学习和实践过的技术内容
+- [Spring Boot教程](https://blog.didispace.com/spring-boot-learning-2x/):全网Star最多的免费Spring Boot基础教程
+- [Spring Cloud教程](https://blog.didispace.com/spring-cloud-learning/):全网最早最全的免费Spring Cloud基础教程
- [知识星球](https://t.xiaomiquan.com/zfEiY3v):聊聊技术人的斜杠生活
-- [GitHub](https://github.com/dyc87112/SpringBoot-Learning):Star支持一下呗
-- [Gitee](https://gitee.com/didispace/SpringBoot-Learning):Star支持一下呗
-- [Spring问答社区](http://www.spring4all.com/):如果您有什么问题,可以去这里发帖
-- [Spring Boot基础教程](http://blog.didispace.com/Spring-Boot%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/):全网Star最多的免费Spring Boot基础教程
-- [Spring Cloud基础教程](http://blog.didispace.com/Spring-Cloud%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/):全网最早最全的免费Spring Cloud基础教程
-## 我的公众号
+**关注公众号,获得更多技术资讯**
diff --git a/README_zh.md b/README_zh.md
index ea69ea5f..f75927c3 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -1,69 +1,37 @@
# Spring Boot基础教程
-本项目内容为[《Spring Boot基础教程》](http://blog.didispace.com/Spring-Boot%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/)的程序样例。
-
**专题目标**:打造全网内容最全,比收费教程更好的Spring Boot免费教程!
**如何支持**:
+
1. 关注我的公众号”**程序猿DD**“
2. 点个`Star`并`Follow`我
3. 把该仓库分享给更多的朋友
-如果您对文字类教程不感冒或者想要通过综合案例学习Spring,那么给您推荐这个我觉得目前内容与价格最良心的视频课程:["玩转Spring全家桶"](https://time.geekbang.org/course/intro/100023501?code=d1se%2F7ugeBEyuU%2FIYp1ynfSZa6ulbGhhDK%2Fkpn3-lFc%3D)
+**加入社群**:如果你正在学习Spring Boot,不妨加入我们的[Spring技术交流群](https://blog.didispace.com/join-group-spring/index.html) ,一起成长
-## 教程目录
+**Spring社区**:如果您在学习过程中碰到问题,可以访问[SpringForAll社区](http://spring4all.com),描述你的问题,我们会尽快给你答复。当然,如果你想分享你的学习经验,也可以在这里发表你的文章
-- [Spring Boot 1.x 版本教程](./1.x)
-- [Spring Boot 2.1.x 版本教程](./2.1.x)
+## 教程目录
-> **关注公众号:“程序猿DD”**,领取我整理的免费学习资料。
+该教程自2016年连载至今,因内容较多,经历过多个版本的迭代。
-## 特别赞助商
+为方便查看学习,这里重新做了整理,根据1.x版本和2.x版本做了区分汇总。
-
+可以通过下面的链接,进入具体版本的教程目录:
-> 如果您也想赞助支持并出现在上表中的话,可以通过邮件联系我:`didi@didispace.com`
+- [Spring Boot 2.x](./2.x)
+- [Spring Boot 1.x](./1.x)
-- [阿里云:ECS云服务器2折起](https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=wxfqkr0o&utm_source=wxfqkr0o)
-- [腾讯云:轻松应对建站成本问题](https://cloud.tencent.com/redirect.php?redirect=1027&cps_key=f6a8af1297bfac40b9d10ffa1270029a&from=console)
+> **关注公众号:“程序猿DD”**,领取我整理的免费学习资料。
## 推荐内容
- [我的博客](http://blog.didispace.com):分享平时学习和实践过的技术内容
+- [Spring Boot教程](https://blog.didispace.com/spring-boot-learning-2x/):全网Star最多的免费Spring Boot基础教程
+- [Spring Cloud教程](https://blog.didispace.com/spring-cloud-learning/):全网最早最全的免费Spring Cloud基础教程
- [知识星球](https://t.xiaomiquan.com/zfEiY3v):聊聊技术人的斜杠生活
-- [GitHub](https://github.com/dyc87112/SpringBoot-Learning):Star支持一下呗
-- [Gitee](https://gitee.com/didispace/SpringBoot-Learning):Star支持一下呗
-- [Spring问答社区](http://www.spring4all.com/):如果您有什么问题,可以去这里发帖
-- [Spring Boot基础教程](http://blog.didispace.com/Spring-Boot%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/):全网Star最多的免费Spring Boot基础教程
-- [Spring Cloud基础教程](http://blog.didispace.com/Spring-Cloud%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/):全网最早最全的免费Spring Cloud基础教程
-## 我的公众号
+**关注公众号,获得更多技术资讯**
diff --git a/images/gitee/001.jpg b/images/gitee/001.jpg
new file mode 100644
index 00000000..01347f5e
Binary files /dev/null and b/images/gitee/001.jpg differ
diff --git a/images/gitee/002.jpg b/images/gitee/002.jpg
new file mode 100644
index 00000000..6bfd55a9
Binary files /dev/null and b/images/gitee/002.jpg differ
diff --git a/images/gitee/003.jpg b/images/gitee/003.jpg
new file mode 100644
index 00000000..16e904be
Binary files /dev/null and b/images/gitee/003.jpg differ
diff --git a/images/gitee/004.jpg b/images/gitee/004.jpg
new file mode 100644
index 00000000..de9a1f04
Binary files /dev/null and b/images/gitee/004.jpg differ
diff --git a/images/gitee/005.jpg b/images/gitee/005.jpg
new file mode 100644
index 00000000..60ae9470
Binary files /dev/null and b/images/gitee/005.jpg differ
diff --git a/images/github/001.jpg b/images/github/001.jpg
new file mode 100644
index 00000000..de9a1f04
Binary files /dev/null and b/images/github/001.jpg differ
diff --git a/images/github/002.jpg b/images/github/002.jpg
new file mode 100644
index 00000000..6bfd55a9
Binary files /dev/null and b/images/github/002.jpg differ
diff --git a/images/github/003.jpg b/images/github/003.jpg
new file mode 100644
index 00000000..60ae9470
Binary files /dev/null and b/images/github/003.jpg differ
diff --git a/images/github/004.jpg b/images/github/004.jpg
new file mode 100644
index 00000000..39cf81d2
Binary files /dev/null and b/images/github/004.jpg differ
diff --git a/images/github/005.jpg b/images/github/005.jpg
new file mode 100644
index 00000000..16e904be
Binary files /dev/null and b/images/github/005.jpg differ
diff --git a/images/weixin.jpg b/images/weixin.jpg
new file mode 100644
index 00000000..ccfef46f
Binary files /dev/null and b/images/weixin.jpg differ
diff --git a/pom.xml b/pom.xml
index bbb1474b..469fe5a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,6 +6,11 @@
com.didispace
SpringBoot-Learning
1.0-SNAPSHOT
+ pom
+
+
+ 2.x
+