SpringBoot使用redis共享session

问题

  • 在集群环境中,session需要共享,此时可以借助中间件来操作。我们可以自己实现,通过cookie跟redis的组合来共享集群的session,之前也做过类似的操作https://github.com/yuyufeng1994/SessionShare
  • 在Spring中,已经提供了插件——spring-session-data-redis,本文就来记录下此方法的使用(基于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配置

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();
            }
        };
    }

}

拦截器层

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 {

    }
}

登录对象

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 + '\'' +
                '}';
    }
}

登录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 "退出成功";
    }


}

启动

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

调试

启动两个端口,8080、8081,会看到,在一个页面登录了,调到另一个页面也是登录的。可以打开cookie看下,session是同一个key,
这里写图片描述
然后,可以去redis中查看下对于的value
这里写图片描述

代码地址

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

猜你喜欢

转载自blog.csdn.net/qq_18860653/article/details/80002826
今日推荐