question
- In a cluster environment, sessions need to be shared, and middleware can be used to operate them. We can implement it ourselves and share the session of the cluster through the combination of cookies and redis. We have done similar operations before https://github.com/yuyufeng1994/SessionShare
- In Spring, a plug-in - spring-session-data-redis has been provided, this article will record the use of this method (based on SpringBoot)
pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
</dependencies>
redis configuration
RedisProperties .class
package top.yuyufeng.sample.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author yuyufeng
* @date 2018/4/19.
*/
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
private int database;
/**
* Redis服务器地址
*/
private String host;
/**
* Redis服务器连接端口
*/
private int port;
/**
* Redis服务器连接密码(默认为空)
*/
private String password;
/**
* 连接池最大连接数(使用负值表示没有限制)
*/
private int maxTotal;
/**
* 连接池最大阻塞等待时间(使用负值表示没有限制)
*/
private int maxWaitMillis;
/**
* 连接池中的最大空闲连接
*/
private int maxIdle;
/**
* 连接池中的最小空闲连接
*/
private int minIdle;
/**
* 连接超时时间(毫秒)
*/
private int timeout;
private boolean testOnBorrow;
private boolean testOnReturn;
//setters and getters
}
RedisConfig.class
package top.yuyufeng.sample.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import redis.clients.jedis.JedisPoolConfig;
import top.yuyufeng.sample.config.properties.RedisProperties;
import java.lang.reflect.Method;
@Configuration
@EnableCaching
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig extends CachingConfigurerSupport {
@Autowired
private RedisProperties properties;
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(new StringRedisSerializer());
return template;
}
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(new StringRedisSerializer());
return template;
}
@Bean
public RedisConnectionFactory connectionFactory() {
JedisConnectionFactory jedis = new JedisConnectionFactory();
jedis.setHostName(properties.getHost());
jedis.setPort(properties.getPort());
jedis.setPassword(properties.getPassword());
jedis.setDatabase(properties.getDatabase());
jedis.setPoolConfig(poolCofig());
// 初始化连接pool
jedis.afterPropertiesSet();
return jedis;
}
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager manager = new RedisCacheManager(redisTemplate);
return manager;
}
@Bean
public JedisPoolConfig poolCofig() {
JedisPoolConfig poolCofig = new JedisPoolConfig();
poolCofig.setMaxIdle(properties.getMaxIdle());
poolCofig.setMaxTotal(properties.getMaxTotal());
poolCofig.setMaxWaitMillis(properties.getMaxWaitMillis());
poolCofig.setTestOnBorrow(properties.isTestOnBorrow());
poolCofig.setTestOnReturn(properties.isTestOnReturn());
return poolCofig;
}
@Bean
@Override
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
StringBuilder builder = new StringBuilder();
builder.append(o.getClass().getName());
builder.append(method.getName());
for (Object obj : objects) {
if (obj != null) {
builder.append(obj.toString());
} else {
builder.append("null");
}
}
return builder.toString();
}
};
}
}
Interceptor layer
package top.yuyufeng.sample.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import top.yuyufeng.sample.vo.UserVO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author yuyufeng
* @date 2018/4/19.
*/
public class AuthorityInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
String uri = httpServletRequest.getRequestURI();
if (uri.equals("/info") || uri.equals("/login")) {
return true;
}
Object object = httpServletRequest.getSession().getAttribute("user");
System.out.println("user:" + object);
if (object == null) {
httpServletResponse.sendRedirect("/info");
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
login object
package top.yuyufeng.sample.vo;
/**
* @author yuyufeng
* @date 2018/4/19.
*/
public class UserVO {
private String userName;
private String userPassword;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
@Override
public String toString() {
return "UserVO{" +
"userName='" + userName + '\'' +
", userPassword='" + userPassword + '\'' +
'}';
}
}
login action
package top.yuyufeng.sample.web;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.yuyufeng.sample.vo.UserVO;
import javax.servlet.http.HttpServletRequest;
/**
* @author yuyufeng
* @date 2018/4/19.
*/
@RestController
public class LoginController {
@RequestMapping(value = "login")
String doLogin(HttpServletRequest request) {
UserVO user = new UserVO();
user.setUserName("yyf");
user.setUserPassword("12345");
System.out.println(user);
request.getSession().setAttribute("user", user.toString());
return "登录成功";
}
@RequestMapping(value = "quit")
String doQuit(HttpServletRequest request) {
request.getSession().removeAttribute("user");
return "退出成功";
}
}
start up
package top.yuyufeng.sample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import top.yuyufeng.sample.interceptor.AuthorityInterceptor;
/**
* @author yuyufeng
* @date 2018/4/19.
*/
@SpringBootApplication
@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 360) //maxInactiveIntervalInSeconds为SpringSession的过期时间(单位:秒)
public class Application extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthorityInterceptor());
}
}
application.yml
server:
port: 8080
spring:
session:
store-type: redis
redis:
database: 0
host: 127.0.0.1
port: 6379
password: 12345
maxTotal: 1000
maxWaitMillis: 5000
maxIdle: 500
minIdle: 0
timeout: 1000
debugging
Start two ports, 8080, 8081, you will see that you are logged in on one page, and you are also logged in when you switch to another page. You can open the cookie to see that the session is the same key,
and then you can go to redis to view the value for