SpringBoot uses redis to share sessions

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,
write picture description here
and then you can go to redis to view the value for
write picture description here

code address

https://gitee.com/mryyf/sample-springboot-session-redis

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326087176&siteId=291194637