一、spring+redis+session
1、添加依赖
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
2、配置
spring-mvc.xml:
<bean id="redisHttpSessionConfiguration"
class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
<property name="maxInactiveIntervalInSeconds" value="600"/>
</bean>
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="100" />
<property name="maxIdle" value="10" />
</bean>
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
<property name="hostName" value="${redis_hostname}"/>
<property name="port" value="${redis_port}"/>
<property name="password" value="${redis_pwd}" />
<property name="timeout" value="3000"/>
<property name="usePool" value="true"/>
<property name="poolConfig" ref="jedisPoolConfig"/>
</bean>
web.xml添加拦截器:
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3、使用spring-session
只要使用标准的servlet api调用session,在底层就会通过Spring Session得到的,并且会存储到Redis或其他你所选择的数据源中。
这里是我写的一个demo:
/**
*/
@Controller
@RequestMapping(value = "index")
public class IndexController {
private final Gson gson = new GsonBuilder().setDateFormat("yyyyMMddHHmmss").create();
@RequestMapping(value = "login")
public String login(HttpServletRequest request, String username){
request.getSession().setAttribute("user", gson.toJson(new User(username,"123456")));
return "login";
}
@RequestMapping(value = "index")
public String index(HttpServletRequest request, Model model){
User user = gson.fromJson(request.getSession().getAttribute("user").toString(), User.class);
model.addAttribute("user", user);
return "index";
}
}
index.jsp:
第一个tomcat
<html>
<body>
<h2>Hello World!</h2>
<p>${user.username}</p>
</body>
</html>
第二个tomcat
<html>
<body>
<h2>Hello World! i am the second!</h2>
<p>${user.username}</p>
</body>
</html>
测试
这里利用上一篇nginx负载配置的两个tomcat来测试。
首先访问 http://192.168.99.100/feng/index/login.htm?username=nginx
来触发生成session。
查看redis,发现session已经保存到redis。
访问 http://192.168.99.100/feng/index/index.htm
来读取session, 并刷新多次。
发现在负载的情况下读取session没问题,并且是同一个session,成功实现负载+session共享!
二、springboot+redis+session
1:导包:
-
<parent>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-parent</artifactId>
-
<version>2.0.2.RELEASE</version>
-
</parent>
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-web</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.session</groupId>
-
<artifactId>spring-session-data-redis</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-data-redis</artifactId>
-
</dependency>
-
</dependencies>
2:配置redis信息, 并开启redis(在这里我是根据我自己的电脑配置的):
-
spring.redis.host=127.0.0.1
-
spring.redis.port=6379
3:配置启动类:
-
@SpringBootApplication
-
@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 3600) //spring在多长时间后强制使redis中的session失效,默认是1800.(单位/秒)
-
public class DemoApplication {
-
public static void main(String[] args) {
-
SpringApplication.run(DemoApplication.class, args);
-
}
-
}
4:写登录Controller测试: 成功!
-
package com.example.demo.controller;
-
import com.example.demo.pojo.User;
-
import com.example.demo.util.FoilResult;
-
import org.springframework.stereotype.Controller;
-
import org.springframework.web.bind.annotation.PostMapping;
-
import org.springframework.web.bind.annotation.ResponseBody;
-
import javax.servlet.http.HttpSession;
-
@Controller
-
public class AgentController {
-
@PostMapping(value = "login")
-
@ResponseBody
-
public FoilResult login(HttpSession session) {
-
System.out.println("===============登录成功===============");
-
User user = new User();
-
user.setName("luan");
-
session.setAttribute("admin",user);
-
return FoilResult.ok();
-
}
-
@PostMapping(value = "logout")
-
@ResponseBody
-
public FoilResult logout(HttpSession session) {
-
System.out.println("============退出系统=============");
-
System.out.println(session.getId());
-
session.removeAttribute("admin");
-
session.invalidate();
-
return FoilResult.ok();
-
}
-
@PostMapping(value = "get")
-
@ResponseBody
-
public String get(HttpSession session) {
-
User user = (User)session.getAttribute("admin");
-
return user.getName();
-
}
-
}
登录成功后,session就保存到到了redis中,可查看key值为spring:session:sessions进行查看.
退出后,redis中的session失效.
如果不自动退出,到了"过程3"中配置的@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 3600) 时间后,redis中的session也会自动失效.
至此,就完成了reids共享session的效果!!!
注 : 在此过程中也可能会有一些版本坑的:
问题 : 启动报错:
-
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
-
2018-05-23 16:01:50.573 ERROR 12308 --- [ main] o.s.boot.SpringApplication : Application run failed
-
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'enableRedisKeyspaceNotificationsInitializer' defined in class path resource [org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.springframework.data.redis.connection.RedisConnection.getConfig(Ljava/lang/String;)Ljava/util/List;
-
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1706) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:579) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
-
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
-
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
-
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
-
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
-
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
-
at com.example.demo.DemoApplication.main(DemoApplication.java:14) [classes/:na]
-
Caused by: java.lang.NoSuchMethodError: org.springframework.data.redis.connection.RedisConnection.getConfig(Ljava/lang/String;)Ljava/util/List;
-
at org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction.getNotifyOptions(ConfigureNotifyKeyspaceEventsAction.java:74) ~[spring-session-1.3.2.RELEASE.jar:na]
-
at org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction.configure(ConfigureNotifyKeyspaceEventsAction.java:55) ~[spring-session-1.3.2.RELEASE.jar:na]
-
at org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration$EnableRedisKeyspaceNotificationsInitializer.afterPropertiesSet(RedisHttpSessionConfiguration.java:251) ~[spring-session-1.3.2.RELEASE.jar:na]
-
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1765) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1702) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE]
-
... 16 common frames omitted
可能原因 : spring-session-data-redis版本问题:(我的是这个原因!)
-
<dependency>
-
<groupId>org.springframework.session</groupId>
-
<artifactId>spring-session-data-redis</artifactId>
-
<version>1.3.2.RELEASE</version>
-
</dependency>
解决 : 版本改为2.0.3
-
<dependency>
-
<groupId>org.springframework.session</groupId>
-
<artifactId>spring-session-data-redis</artifactId>
-
<version>1.3.2.RELEASE</version>
-
</dependency>
注 : 这里可能会出现一个ajax跨域访问无法携带cookie的问题(我在这里出现了), 我的已经解决, 请参考:https://blog.csdn.net/luan666/article/details/80429869