1.session是什么
当用户在前端发起请求时,服务器会为当前用户建立一个session,服务器将sessionId回写给客户端,只要用户浏览器不关闭,再次请求服务器时,将sessionId传给服务器,
服务器会根据sessionId找到与之对应的session为其服务。
如果是分布式部署时,session存储在服务器端,下次用户请求过来,通过负载均衡,可能会分发到其他服务器节点;所以,需要解决session一致性的问题,
使用redis来实现分布式session,个人理解是将session存放到redis中,每次请求过来时,会从redis读取session信息
2.代码实现
①.maven需要引入的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> </dependency>
②.配置文件指定redis的ip和端口
spring.redis.host=172.18.66.45
spring.redis.port=6379
③.httpSession配置
package com.session.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; //maxInactiveIntervalInSeconds设置session有效时间,单位是秒;默认是30分钟 @EnableRedisHttpSession(maxInactiveIntervalInSeconds=180) public class SessionConfig { @Value("${spring.redis.host}") private String hostName; @Value("${spring.redis.port}") private int port; @Bean public JedisConnectionFactory connectionFactory() { JedisConnectionFactory connectionFactory = new JedisConnectionFactory(); connectionFactory.setPort(port); connectionFactory.setHostName(hostName); System.out.println("获取到的hostName是:"+hostName + ",port :"+port); return connectionFactory; } }
再实现一个controller,就可以模拟实际业务场景写session、根据session校验用户是否登录
package com.session.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class SessionController { //模拟第一次登陆时,保存session @RequestMapping(value="/login") public String login(HttpServletRequest request) { HttpSession session = request.getSession(); String str = (String) session.getAttribute("userInfo"); if(str == null || "".equals(str)) { session.setAttribute("userInfo", "mpy test session"); return "用户登录成功-success"; }else{ return "session中存在数据,用户已登录"; } } /*该方法模式登陆之后,调用业务接口
*在实际的业务场景中,可以使用拦截器,对每次请求进行判断,校验用户是否登录、session是否过期
*/ @RequestMapping(value="/getSession") public String getSession(HttpServletRequest request) { HttpSession session = request.getSession(); String str = (String) session.getAttribute("userInfo"); if(str == null || "".equals(str)) { return "session中没有数据,请登录"; }else{ //已登录用户,进行其他业务代码的处理 System.out.println("session中的属性是:"+str); return str; } } @RequestMapping(value="/logout") public String logout(HttpServletRequest request) { HttpSession session = request.getSession(); String str = (String) session.getAttribute("userInfo"); if(str != null && "".equals(str)) { session.invalidate(); } return "退出成功"; } }
@EnableRedisHttpSession和spring-session的实现原理还有待研究学习
具体的代码,已经上传至GitHub,https://github.com/mapy95/spring-session.git