diff --git a/README.md b/README.md
index b89ec6e3..afab8fd2 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
# Web 开发
* [《芋道 Spring Boot SpringMVC 入门》](http://www.iocoder.cn/Spring-Boot/SpringMVC/?github) 对应 [lab-23](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-23) 。
+* [《芋道 Spring Boot 分布式 Session 入门》](http://www.iocoder.cn/Spring-Boot/Distributed-Session/?github) 对应 [lab-26](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-26) 。
* [《芋道 Spring Boot API 接口文档 Swagger 入门》](http://www.iocoder.cn/Spring-Boot/Swagger/?github) 对应 [lab-24](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-24) 。
* [《芋道 Spring Boot 参数校验 Validation 入门》](http://www.iocoder.cn/Spring-Boot/Validation/?github) 对应 [lab-22](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-22) 。
* [《芋道 Spring Boot WebSocket 入门》](http://www.iocoder.cn/Spring-Boot/WebSocket/?github) 对应 [lab-25](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-25) 。
diff --git a/lab-26/lab-26-distributed-session-01/pom.xml b/lab-26/lab-26-distributed-session-01/pom.xml
index 8fa4df7d..8ea463c2 100644
--- a/lab-26/lab-26-distributed-session-01/pom.xml
+++ b/lab-26/lab-26-distributed-session-01/pom.xml
@@ -19,6 +19,30 @@
spring-boot-starter-web
+
+
+ org.springframework.session
+ spring-session-data-redis
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ io.lettuce
+ lettuce-core
+
+
+
+
+
+ redis.clients
+ jedis
+
+
diff --git a/lab-26/lab-26-distributed-session-01/src/main/java/cn/iocoder/springboot/lab26/distributedsession/config/SessionConfiguration.java b/lab-26/lab-26-distributed-session-01/src/main/java/cn/iocoder/springboot/lab26/distributedsession/config/SessionConfiguration.java
new file mode 100644
index 00000000..50d10150
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-01/src/main/java/cn/iocoder/springboot/lab26/distributedsession/config/SessionConfiguration.java
@@ -0,0 +1,27 @@
+package cn.iocoder.springboot.lab26.distributedsession.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.session.data.redis.RedisOperationsSessionRepository;
+import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
+import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration;
+
+@Configuration
+@EnableRedisHttpSession // 自动化配置 Spring Session 使用 Redis 作为数据源
+public class SessionConfiguration {
+
+ /**
+ * 创建 {@link RedisOperationsSessionRepository} 使用的 RedisSerializer Bean 。
+ *
+ * 具体可以看看 {@link RedisHttpSessionConfiguration#setDefaultRedisSerializer(RedisSerializer)} 方法,
+ * 它会引入名字为 "springSessionDefaultRedisSerializer" 的 Bean 。
+ *
+ * @return RedisSerializer Bean
+ */
+ @Bean(name = "springSessionDefaultRedisSerializer")
+ public RedisSerializer springSessionDefaultRedisSerializer() {
+ return RedisSerializer.json();
+ }
+
+}
diff --git a/lab-26/lab-26-distributed-session-01/src/main/resources/application.yaml b/lab-26/lab-26-distributed-session-01/src/main/resources/application.yaml
new file mode 100644
index 00000000..6f683b2a
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-01/src/main/resources/application.yaml
@@ -0,0 +1,15 @@
+spring:
+ # 对应 RedisProperties 类
+ redis:
+ host: 127.0.0.1
+ port: 6379
+ password: # Redis 服务器密码,默认为空。生产中,一定要设置 Redis 密码!
+ database: 0 # Redis 数据库号,默认为 0 。
+ timeout: 0 # Redis 连接超时时间,单位:毫秒。
+ # 对应 RedisProperties.Jedis 内部类
+ jedis:
+ pool:
+ max-active: 8 # 连接池最大连接数,默认为 8 。使用负数表示没有限制。
+ max-idle: 8 # 默认连接数最大空闲的连接数,默认为 8 。使用负数表示没有限制。
+ min-idle: 0 # 默认连接池最小空闲的连接数,默认为 0 。允许设置 0 和 正数。
+ max-wait: -1 # 连接池最大阻塞等待时间,单位:毫秒。默认为 -1 ,表示不限制。
diff --git a/lab-26/lab-26-distributed-session-02/pom.xml b/lab-26/lab-26-distributed-session-02/pom.xml
new file mode 100644
index 00000000..9539b3d5
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-02/pom.xml
@@ -0,0 +1,36 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.10.RELEASE
+
+
+ 4.0.0
+
+ lab-26-distributed-session-02
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.session
+ spring-session-data-mongodb
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+
+
+
+
+
diff --git a/lab-26/lab-26-distributed-session-02/src/main/java/cn/iocoder/springboot/lab26/distributedsession/Application.java b/lab-26/lab-26-distributed-session-02/src/main/java/cn/iocoder/springboot/lab26/distributedsession/Application.java
new file mode 100644
index 00000000..f05e963d
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-02/src/main/java/cn/iocoder/springboot/lab26/distributedsession/Application.java
@@ -0,0 +1,13 @@
+package cn.iocoder.springboot.lab26.distributedsession;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/lab-26/lab-26-distributed-session-02/src/main/java/cn/iocoder/springboot/lab26/distributedsession/config/SessionConfiguration.java b/lab-26/lab-26-distributed-session-02/src/main/java/cn/iocoder/springboot/lab26/distributedsession/config/SessionConfiguration.java
new file mode 100644
index 00000000..ed9936db
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-02/src/main/java/cn/iocoder/springboot/lab26/distributedsession/config/SessionConfiguration.java
@@ -0,0 +1,18 @@
+package cn.iocoder.springboot.lab26.distributedsession.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
+import org.springframework.session.data.mongo.JacksonMongoSessionConverter;
+import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession;
+
+@Configuration
+@EnableMongoHttpSession // 自动化配置 Spring Session 使用 MongoDB 作为数据源
+public class SessionConfiguration {
+
+ @Bean
+ public AbstractMongoSessionConverter mongoSessionConverter() {
+ return new JacksonMongoSessionConverter();
+ }
+
+}
diff --git a/lab-26/lab-26-distributed-session-02/src/main/java/cn/iocoder/springboot/lab26/distributedsession/controller/SessionController.java b/lab-26/lab-26-distributed-session-02/src/main/java/cn/iocoder/springboot/lab26/distributedsession/controller/SessionController.java
new file mode 100644
index 00000000..c5f72139
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-02/src/main/java/cn/iocoder/springboot/lab26/distributedsession/controller/SessionController.java
@@ -0,0 +1,38 @@
+package cn.iocoder.springboot.lab26.distributedsession.controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpSession;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/session")
+public class SessionController {
+
+ @GetMapping("/set") // 其实 PostMapping 更合适,单纯为了方便
+ public void set(HttpSession session,
+ @RequestParam("key") String key,
+ @RequestParam("value") String value) {
+ session.setAttribute(key, value);
+ }
+
+ @GetMapping("/get_all")
+ public Map getAll(HttpSession session) {
+ Map result = new HashMap<>();
+ // 遍历
+ for (Enumeration enumeration = session.getAttributeNames();
+ enumeration.hasMoreElements();) {
+ String key = enumeration.nextElement();
+ Object value = session.getAttribute(key);
+ result.put(key, value);
+ }
+ // 返回
+ return result;
+ }
+
+}
diff --git a/lab-26/lab-26-distributed-session-02/src/main/resources/application.yaml b/lab-26/lab-26-distributed-session-02/src/main/resources/application.yaml
new file mode 100644
index 00000000..9d5d76f0
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-02/src/main/resources/application.yaml
@@ -0,0 +1,18 @@
+spring:
+ data:
+ # MongoDB 配置项,对应 MongoProperties 类
+ mongodb:
+ host: 127.0.0.1
+ port: 27017
+ database: yourdatabase
+ username: test01
+ password: password01
+ # 上述属性,也可以只配置 uri
+
+logging:
+ level:
+ org:
+ springframework:
+ data:
+ mongodb:
+ core: DEBUG # 打印 mongodb 操作的具体语句。生产环境下,不建议开启。
diff --git a/lab-26/lab-26-distributed-session-springsecurity/pom.xml b/lab-26/lab-26-distributed-session-springsecurity/pom.xml
new file mode 100644
index 00000000..7c390b67
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-springsecurity/pom.xml
@@ -0,0 +1,54 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.10.RELEASE
+
+
+ 4.0.0
+
+ lab-26-distributed-session-springsecurity
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.session
+ spring-session-data-redis
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ io.lettuce
+ lettuce-core
+
+
+
+
+
+ redis.clients
+ jedis
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+
+
diff --git a/lab-26/lab-26-distributed-session-springsecurity/src/main/java/cn/iocoder/springboot/lab26/distributedsession/Application.java b/lab-26/lab-26-distributed-session-springsecurity/src/main/java/cn/iocoder/springboot/lab26/distributedsession/Application.java
new file mode 100644
index 00000000..f05e963d
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-springsecurity/src/main/java/cn/iocoder/springboot/lab26/distributedsession/Application.java
@@ -0,0 +1,13 @@
+package cn.iocoder.springboot.lab26.distributedsession;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/lab-26/lab-26-distributed-session-springsecurity/src/main/java/cn/iocoder/springboot/lab26/distributedsession/config/SessionConfiguration.java b/lab-26/lab-26-distributed-session-springsecurity/src/main/java/cn/iocoder/springboot/lab26/distributedsession/config/SessionConfiguration.java
new file mode 100644
index 00000000..f1b3ddd6
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-springsecurity/src/main/java/cn/iocoder/springboot/lab26/distributedsession/config/SessionConfiguration.java
@@ -0,0 +1,10 @@
+package cn.iocoder.springboot.lab26.distributedsession.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
+
+@Configuration
+@EnableRedisHttpSession // 自动化配置 Spring Session 使用 Redis 作为数据源
+public class SessionConfiguration {
+
+}
diff --git a/lab-26/lab-26-distributed-session-springsecurity/src/main/java/cn/iocoder/springboot/lab26/distributedsession/controller/SessionController.java b/lab-26/lab-26-distributed-session-springsecurity/src/main/java/cn/iocoder/springboot/lab26/distributedsession/controller/SessionController.java
new file mode 100644
index 00000000..ff269c77
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-springsecurity/src/main/java/cn/iocoder/springboot/lab26/distributedsession/controller/SessionController.java
@@ -0,0 +1,46 @@
+package cn.iocoder.springboot.lab26.distributedsession.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.session.FindByIndexNameSessionRepository;
+import org.springframework.session.Session;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+@RestController
+@RequestMapping("/session")
+public class SessionController {
+
+ @Autowired
+ private FindByIndexNameSessionRepository sessionRepository;
+
+ @GetMapping("/list")
+ public Map list(@RequestParam("username") String username) {
+ return sessionRepository.findByPrincipalName(username);
+ }
+
+// @GetMapping("/set") // 其实 PostMapping 更合适,单纯为了方便
+// public void set(HttpSession session,
+// @RequestParam("key") String key,
+// @RequestParam("value") String value) {
+// session.setAttribute(key, value);
+// }
+//
+// @GetMapping("/get_all")
+// public Map getAll(HttpSession session) {
+// Map result = new HashMap<>();
+// // 遍历
+// for (Enumeration enumeration = session.getAttributeNames();
+// enumeration.hasMoreElements();) {
+// String key = enumeration.nextElement();
+// Object value = session.getAttribute(key);
+// result.put(key, value);
+// }
+// // 返回
+// return result;
+// }
+
+}
diff --git a/lab-26/lab-26-distributed-session-springsecurity/src/main/resources/application.yaml b/lab-26/lab-26-distributed-session-springsecurity/src/main/resources/application.yaml
new file mode 100644
index 00000000..52aa5ea3
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-springsecurity/src/main/resources/application.yaml
@@ -0,0 +1,20 @@
+spring:
+ # 对应 RedisProperties 类
+ redis:
+ host: 127.0.0.1
+ port: 6379
+ password: # Redis 服务器密码,默认为空。生产中,一定要设置 Redis 密码!
+ database: 0 # Redis 数据库号,默认为 0 。
+ timeout: 0 # Redis 连接超时时间,单位:毫秒。
+ # 对应 RedisProperties.Jedis 内部类
+ jedis:
+ pool:
+ max-active: 8 # 连接池最大连接数,默认为 8 。使用负数表示没有限制。
+ max-idle: 8 # 默认连接数最大空闲的连接数,默认为 8 。使用负数表示没有限制。
+ min-idle: 0 # 默认连接池最小空闲的连接数,默认为 0 。允许设置 0 和 正数。
+ max-wait: -1 # 连接池最大阻塞等待时间,单位:毫秒。默认为 -1 ,表示不限制。
+ # 对应 SecurityProperties 类
+ security:
+ user: # 配置内存中,可登陆的用户名和密码
+ name: yudaoyuanma
+ password: nicai
diff --git a/lab-26/lab-26-distributed-session-springsecurity/target/classes/META-INF/lab-26-distributed-session-01.kotlin_module b/lab-26/lab-26-distributed-session-springsecurity/target/classes/META-INF/lab-26-distributed-session-01.kotlin_module
new file mode 100644
index 00000000..2983af70
Binary files /dev/null and b/lab-26/lab-26-distributed-session-springsecurity/target/classes/META-INF/lab-26-distributed-session-01.kotlin_module differ
diff --git a/lab-26/lab-26-distributed-session-springsecurity/target/classes/application.yaml b/lab-26/lab-26-distributed-session-springsecurity/target/classes/application.yaml
new file mode 100644
index 00000000..52aa5ea3
--- /dev/null
+++ b/lab-26/lab-26-distributed-session-springsecurity/target/classes/application.yaml
@@ -0,0 +1,20 @@
+spring:
+ # 对应 RedisProperties 类
+ redis:
+ host: 127.0.0.1
+ port: 6379
+ password: # Redis 服务器密码,默认为空。生产中,一定要设置 Redis 密码!
+ database: 0 # Redis 数据库号,默认为 0 。
+ timeout: 0 # Redis 连接超时时间,单位:毫秒。
+ # 对应 RedisProperties.Jedis 内部类
+ jedis:
+ pool:
+ max-active: 8 # 连接池最大连接数,默认为 8 。使用负数表示没有限制。
+ max-idle: 8 # 默认连接数最大空闲的连接数,默认为 8 。使用负数表示没有限制。
+ min-idle: 0 # 默认连接池最小空闲的连接数,默认为 0 。允许设置 0 和 正数。
+ max-wait: -1 # 连接池最大阻塞等待时间,单位:毫秒。默认为 -1 ,表示不限制。
+ # 对应 SecurityProperties 类
+ security:
+ user: # 配置内存中,可登陆的用户名和密码
+ name: yudaoyuanma
+ password: nicai
diff --git a/lab-26/pom.xml b/lab-26/pom.xml
index f4646e5d..7fe6debc 100644
--- a/lab-26/pom.xml
+++ b/lab-26/pom.xml
@@ -13,6 +13,8 @@
pom
lab-26-distributed-session-01
+ lab-26-distributed-session-02
+ lab-26-distributed-session-springsecurity
diff --git a/pom.xml b/pom.xml
index cb24d3b9..17804293 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,6 +34,7 @@
lab-23
lab-24
lab-25
+ lab-26