diff --git a/pom.xml b/pom.xml index 487cf7e..5551683 100644 --- a/pom.xml +++ b/pom.xml @@ -35,6 +35,7 @@ spring-boot-demo-swagger spring-boot-demo-swagger-beauty spring-boot-demo-rbac-security + spring-boot-demo-session spring-boot-demo-websocket spring-boot-demo-websocket-socketio spring-boot-demo-war diff --git a/spring-boot-demo-session/.gitignore b/spring-boot-demo-session/.gitignore new file mode 100644 index 0000000..82eca33 --- /dev/null +++ b/spring-boot-demo-session/.gitignore @@ -0,0 +1,25 @@ +/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/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ \ No newline at end of file diff --git a/spring-boot-demo-session/README.md b/spring-boot-demo-session/README.md new file mode 100644 index 0000000..0f3aa5c --- /dev/null +++ b/spring-boot-demo-session/README.md @@ -0,0 +1,126 @@ +# spring-boot-demo-session + +> 此 demo 主要演示了 Spring Boot 如何通过 Spring Session 实现Session共享、重启程序Session不失效。 + +## pom.xml + +```xml + + + 4.0.0 + + spring-boot-demo-session + 1.0.0-SNAPSHOT + + spring-boot-demo-session + Demo project for Spring Boot + + + com.xkcoding + spring-boot-demo + 1.0.0-SNAPSHOT + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.session + spring-session-data-redis + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.apache.commons + commons-pool2 + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.springframework.boot + spring-boot-starter-test + test + + + + cn.hutool + hutool-all + + + + + spring-boot-demo-session + + + org.springframework.boot + spring-boot-maven-plugin + + + + + +``` + +## application.yml + +```yaml +server: + port: 8080 + servlet: + context-path: /demo +spring: + session: + store-type: redis + redis: + flush-mode: immediate + namespace: "spring:session" + redis: + host: localhost + port: 6379 + # 连接超时时间(记得添加单位,Duration) + timeout: 10000ms + # Redis默认情况下有16个分片,这里配置具体使用的分片 + # database: 0 + lettuce: + pool: + # 连接池最大连接数(使用负值表示没有限制) 默认 8 + max-active: 8 + # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1 + max-wait: -1ms + # 连接池中的最大空闲连接 默认 8 + max-idle: 8 + # 连接池中的最小空闲连接 默认 0 + min-idle: 0 +``` + +## 测试 + +> 测试 重启程序,Session 不失效的场景 + +1. 打开浏览器,访问首页:http://localhost:8080/demo/page/index +2. 最开始未登录,所以会跳转到登录页:http://localhost:8080/demo/page/login?redirect=true 然后点击登录按钮 +3. 登录之后,跳转回首页,此时可以看到首页显示token信息。 +4. 重启程序。不关闭浏览器,直接刷新首页,此时不跳转到登录页。测试成功! + +## 参考 + +- Spring Session 官方文档:https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-redis.html#updating-dependencies \ No newline at end of file diff --git a/spring-boot-demo-session/pom.xml b/spring-boot-demo-session/pom.xml new file mode 100644 index 0000000..356765f --- /dev/null +++ b/spring-boot-demo-session/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + + spring-boot-demo-session + 1.0.0-SNAPSHOT + + spring-boot-demo-session + Demo project for Spring Boot + + + com.xkcoding + spring-boot-demo + 1.0.0-SNAPSHOT + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.session + spring-session-data-redis + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.apache.commons + commons-pool2 + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.springframework.boot + spring-boot-starter-test + test + + + + cn.hutool + hutool-all + + + + + spring-boot-demo-session + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot-demo-session/src/main/java/com/xkcoding/session/SpringBootDemoSessionApplication.java b/spring-boot-demo-session/src/main/java/com/xkcoding/session/SpringBootDemoSessionApplication.java new file mode 100644 index 0000000..2834699 --- /dev/null +++ b/spring-boot-demo-session/src/main/java/com/xkcoding/session/SpringBootDemoSessionApplication.java @@ -0,0 +1,27 @@ +package com.xkcoding.session; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + *

+ * 启动类 + *

+ * + * @package: com.xkcoding.session + * @description: 启动类 + * @author: yangkai.shen + * @date: Created in 2018-12-19 19:35 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@SpringBootApplication +public class SpringBootDemoSessionApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootDemoSessionApplication.class, args); + } + +} + diff --git a/spring-boot-demo-session/src/main/java/com/xkcoding/session/config/WebMvcConfig.java b/spring-boot-demo-session/src/main/java/com/xkcoding/session/config/WebMvcConfig.java new file mode 100644 index 0000000..2528935 --- /dev/null +++ b/spring-boot-demo-session/src/main/java/com/xkcoding/session/config/WebMvcConfig.java @@ -0,0 +1,39 @@ +package com.xkcoding.session.config; + +import com.xkcoding.session.interceptor.SessionInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + *

+ * WebMvc 配置类 + *

+ * + * @package: com.xkcoding.session.config + * @description: WebMvc 配置类 + * @author: yangkai.shen + * @date: Created in 2018-12-19 19:50 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@Configuration +public class WebMvcConfig implements WebMvcConfigurer { + @Autowired + private SessionInterceptor sessionInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + InterceptorRegistration sessionInterceptorRegistry = registry.addInterceptor(sessionInterceptor); + // 排除不需要拦截的路径 + sessionInterceptorRegistry.excludePathPatterns("/page/login"); + sessionInterceptorRegistry.excludePathPatterns("/page/doLogin"); + sessionInterceptorRegistry.excludePathPatterns("/error"); + + // 需要拦截的路径 + sessionInterceptorRegistry.addPathPatterns("/**"); + } +} diff --git a/spring-boot-demo-session/src/main/java/com/xkcoding/session/constants/Consts.java b/spring-boot-demo-session/src/main/java/com/xkcoding/session/constants/Consts.java new file mode 100644 index 0000000..38cf8f3 --- /dev/null +++ b/spring-boot-demo-session/src/main/java/com/xkcoding/session/constants/Consts.java @@ -0,0 +1,21 @@ +package com.xkcoding.session.constants; + +/** + *

+ * 常量池 + *

+ * + * @package: com.xkcoding.session.constants + * @description: 常量池 + * @author: yangkai.shen + * @date: Created in 2018-12-19 19:42 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +public interface Consts { + /** + * session保存的key + */ + String SESSION_KEY = "key:session:token"; +} diff --git a/spring-boot-demo-session/src/main/java/com/xkcoding/session/controller/PageController.java b/spring-boot-demo-session/src/main/java/com/xkcoding/session/controller/PageController.java new file mode 100644 index 0000000..d6b4756 --- /dev/null +++ b/spring-boot-demo-session/src/main/java/com/xkcoding/session/controller/PageController.java @@ -0,0 +1,67 @@ +package com.xkcoding.session.controller; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import com.xkcoding.session.constants.Consts; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +/** + *

+ * 页面跳转 Controller + *

+ * + * @package: com.xkcoding.session.controller + * @description: 页面跳转 Controller + * @author: yangkai.shen + * @date: Created in 2018-12-19 19:57 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@Controller +@RequestMapping("/page") +public class PageController { + /** + * 跳转到 首页 + * + * @param request 请求 + */ + @GetMapping("/index") + public ModelAndView index(HttpServletRequest request) { + ModelAndView mv = new ModelAndView(); + + String token = (String) request.getSession().getAttribute(Consts.SESSION_KEY); + mv.setViewName("index"); + mv.addObject("token", token); + return mv; + } + + /** + * 跳转到 登录页 + * + * @param redirect 是否是跳转回来的 + */ + @GetMapping("/login") + public ModelAndView login(Boolean redirect) { + ModelAndView mv = new ModelAndView(); + + if (ObjectUtil.isNotNull(redirect) && ObjectUtil.equal(true, redirect)) { + mv.addObject("message", "请先登录!"); + } + mv.setViewName("login"); + return mv; + } + + @GetMapping("/doLogin") + public String doLogin(HttpSession session) { + session.setAttribute(Consts.SESSION_KEY, IdUtil.fastUUID()); + + return "redirect:/page/index"; + } +} diff --git a/spring-boot-demo-session/src/main/java/com/xkcoding/session/interceptor/SessionInterceptor.java b/spring-boot-demo-session/src/main/java/com/xkcoding/session/interceptor/SessionInterceptor.java new file mode 100644 index 0000000..c797655 --- /dev/null +++ b/spring-boot-demo-session/src/main/java/com/xkcoding/session/interceptor/SessionInterceptor.java @@ -0,0 +1,37 @@ +package com.xkcoding.session.interceptor; + +import com.xkcoding.session.constants.Consts; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +/** + *

+ * 校验Session的拦截器 + *

+ * + * @package: com.xkcoding.session.interceptor + * @description: 校验Session的拦截器 + * @author: yangkai.shen + * @date: Created in 2018-12-19 19:40 + * @copyright: Copyright (c) 2018 + * @version: V1.0 + * @modified: yangkai.shen + */ +@Component +public class SessionInterceptor extends HandlerInterceptorAdapter { + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + HttpSession session = request.getSession(); + if (session.getAttribute(Consts.SESSION_KEY) != null) { + return true; + } + // 跳转到登录页 + String url = "/page/login?redirect=true"; + response.sendRedirect(request.getContextPath() + url); + return false; + } +} diff --git a/spring-boot-demo-session/src/main/resources/application.yml b/spring-boot-demo-session/src/main/resources/application.yml new file mode 100644 index 0000000..c0da8e6 --- /dev/null +++ b/spring-boot-demo-session/src/main/resources/application.yml @@ -0,0 +1,27 @@ +server: + port: 8080 + servlet: + context-path: /demo +spring: + session: + store-type: redis + redis: + flush-mode: immediate + namespace: "spring:session" + redis: + host: localhost + port: 6379 + # 连接超时时间(记得添加单位,Duration) + timeout: 10000ms + # Redis默认情况下有16个分片,这里配置具体使用的分片 + # database: 0 + lettuce: + pool: + # 连接池最大连接数(使用负值表示没有限制) 默认 8 + max-active: 8 + # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1 + max-wait: -1ms + # 连接池中的最大空闲连接 默认 8 + max-idle: 8 + # 连接池中的最小空闲连接 默认 0 + min-idle: 0 \ No newline at end of file diff --git a/spring-boot-demo-session/src/main/resources/templates/index.html b/spring-boot-demo-session/src/main/resources/templates/index.html new file mode 100644 index 0000000..843cf73 --- /dev/null +++ b/spring-boot-demo-session/src/main/resources/templates/index.html @@ -0,0 +1,10 @@ + + + + + spring-boot-demo-session + + +token的值:

+ + \ No newline at end of file diff --git a/spring-boot-demo-session/src/main/resources/templates/login.html b/spring-boot-demo-session/src/main/resources/templates/login.html new file mode 100644 index 0000000..3cb98a7 --- /dev/null +++ b/spring-boot-demo-session/src/main/resources/templates/login.html @@ -0,0 +1,12 @@ + + + + + spring-boot-demo-session + + +

+ + + + \ No newline at end of file diff --git a/spring-boot-demo-session/src/test/java/com/xkcoding/session/SpringBootDemoSessionApplicationTests.java b/spring-boot-demo-session/src/test/java/com/xkcoding/session/SpringBootDemoSessionApplicationTests.java new file mode 100644 index 0000000..65d3fbb --- /dev/null +++ b/spring-boot-demo-session/src/test/java/com/xkcoding/session/SpringBootDemoSessionApplicationTests.java @@ -0,0 +1,17 @@ +package com.xkcoding.session; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SpringBootDemoSessionApplicationTests { + + @Test + public void contextLoads() { + } + +} +