Spring Boot高级教程之使用Redis实现session共享

Redis是一个缓存消息中间件及具有丰富特性的键值存储系统。Spring Boot为Jedis客户端库和由Spring Data Redis提供的基于Jedis客户端的抽象提供自动配置。spring-boot-starter-redis'Starter POM'为收集依赖提供一种便利的方式。

引入spring-boot-starter-redis,在pom.xml配置文件中增加配置如下(基于之前章节“Spring Boot 构建框架”中的pom.xml文件):

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-redis</artifactId>
</dependency>

可以注入一个自动配置的RedisConnectionFactory,StringRedisTemplate或普通的跟其他Spring Bean相同的RedisTemplate实例。默认情况下,这个实例将尝试使用localhost:6379连接Redis服务器。

@Component
public class MyBean {
  private StringRedisTemplate template;

  @Autowired
  public MyBean(StringRedisTemplate template) {
    this.template = template;
  }
  // ...
}

如果添加一个自己的任何自动配置类型的@Bean,它将替换默认的(除了RedisTemplate的情况,它是根据bean的名称'redisTemplate'而不是它的类型进行排除的)。如果在classpath路径下存在commons-pool2,默认会获得一个连接池工厂。

应用使用Redis案例

添加配置文件,配置内容如下:

# REDIS (RedisProperties)
# Redis服务器地址
spring.redis.host=192.168.0.58
# Redis服务器连接端口
spring.redis.port=6379
# 连接超时时间(毫秒)
spring.redis.timeout=0

redis配置类,具体代码如下:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; 

@Component
@ConfigurationProperties(prefix = "spring.redis")
public class RedisConn { 

  private String host; 

  private int port; 

  private int timeout; 

  public String getHost() {
    return host;
  } 

  public void setHost(String host) {
    this.host = host;
  } 

  public int getPort() {
    return port;
  } 

  public void setPort(int port) {
    this.port = port;
  } 

  public int getTimeout() {
    return timeout;
  } 

  public void setTimeout(int timeout) {
    this.timeout = timeout;
  } 

  @Override
  public String toString() {
    return "Redis [localhost=" + host + ", port=" + port + ", timeout=" + timeout + "]";
  } 

}

注意:在RedisConn类中注解@ConfigurationProperties(prefix = "spring.Redis")的作用是读取springboot的默认配置文件信息中以spring.redis开头的信息。

配置cache类

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map; 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
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.Jackson2JsonRedisSerializer;
import org.springframework.stereotype.Component; 

import com.cachemodle.RedisConn;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper; 

/**
*
* @author sandsa redis cache service
*
*/ 

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport { 

  @Autowired
  private RedisConn redisConn; 

  /**
  * 生产key的策略
  *
  * @return
  */ 

  @Bean
  @Override
  public KeyGenerator keyGenerator() {
    return new KeyGenerator() { 

      @Override
      public Object generate(Object target, Method method, Object... params) {
        StringBuilder sb = new StringBuilder();
        sb.append(target.getClass().getName());
        sb.append(method.getName());
        for (Object obj : params) {
          sb.append(obj.toString());
        }
        return sb.toString();
      }
    }; 

  } 

  /**
  * 管理缓存
  *
  * @param redisTemplate
  * @return
  */ 

  @SuppressWarnings("rawtypes")
  @Bean
  public CacheManager CacheManager(RedisTemplate redisTemplate) {
    RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
    // 设置cache过期时间,时间单位是秒
    rcm.setDefaultExpiration(60);
    Map<String, Long> map = new HashMap<String, Long>();
    map.put("test", 60L);
    rcm.setExpires(map);
    return rcm;
  } 

  /**
  * redis 数据库连接池
  * @return
  */ 

  @Bean
  public JedisConnectionFactory redisConnectionFactory() {
    JedisConnectionFactory factory = new JedisConnectionFactory();
    factory.setHostName(redisConn.getHost());
    factory.setPort(redisConn.getPort());
    factory.setTimeout(redisConn.getTimeout()); // 设置连接超时时间
    return factory;
  } 

  /**
  * redisTemplate配置
  *
  * @param factory
  * @return
  */
  @SuppressWarnings({ "rawtypes", "unchecked" })
  @Bean
  public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
    StringRedisTemplate template = new StringRedisTemplate(factory);
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(om);
    template.setValueSerializer(jackson2JsonRedisSerializer);
    template.afterPropertiesSet();
    return template;
  } 

}

分析:缓存类继承的是CachingConfigurerSupport,它把读取的配置文件信息的RedisConn类对象注入到这个类中。在这个类中keyGenerator()方法是key的生成策略,CacheManager()方法是缓存管理策略,redisConnectionFactory()是redis连接,redisTemplate()方法是redisTemplate配置信息,配置后使redis中能存储Java对象。

测试配置是否成功,实例:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class TestRedis {
  @Autowired
  private StringRedisTemplate stringRedisTemplate; // 处理字符串

  @Autowired
  private RedisTemplate redisTemplate; // 处理对象
  @Test
  public void test() throws Exception {
    stringRedisTemplate.opsForValue().set("yoodb", "123");
    Assert.assertEquals("123", stringRedisTemplate.opsForValue().get("yoodb"));
  }
}

简单封装的Redis工具类,代码如下:

import java.io.Serializable;
import java.util.Set;
import java.util.concurrent.TimeUnit; 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component; 

@Component
public class RedisUtils { 

  @SuppressWarnings("rawtypes")
  @Autowired
  private RedisTemplate redisTemplate; 

  /**
   * 批量删除对应的value
   *
   * @param keys
   */
  public void remove(final String... keys) {
    for (String key : keys) {
      remove(key);
    }
  } 

  /**
   * 批量删除key
   *
   * @param pattern
   */
  @SuppressWarnings("unchecked")
  public void removePattern(final String pattern) {
    Set<Serializable> keys = redisTemplate.keys(pattern);
    if (keys.size() > 0)
      redisTemplate.delete(keys);
  } 

  /**
   * 删除对应的value
   *
   * @param key
   */
  @SuppressWarnings("unchecked")
  public void remove(final String key) {
    if (exists(key)) {
      redisTemplate.delete(key);
    }
  } 

  /**
   * 判断缓存中是否有对应的value
   *
   * @param key
   * @return
   */
  @SuppressWarnings("unchecked")
  public boolean exists(final String key) {
    return redisTemplate.hasKey(key);
  } 

  /**
   * 读取缓存
   *
   * @param key
   * @return
   */
  @SuppressWarnings("unchecked")
  public Object get(final String key) {
    Object result = null;
    ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
    result = operations.get(key);
    return result;
  } 

  /**
   * 写入缓存
   *
   * @param key
   * @param value
   * @return
   */
  @SuppressWarnings("unchecked")
  public boolean set(final String key, Object value) {
    boolean result = false;
    try {
      ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
      operations.set(key, value);
      result = true;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  } 

  /**
   * 写入缓存
   *
   * @param key
   * @param value
   * @return
   */
  @SuppressWarnings("unchecked")
  public boolean set(final String key, Object value, Long expireTime) {
    boolean result = false;
    try {
      ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
      operations.set(key, value);
      redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
      result = true;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  } 

}

查询数据库时自动使用缓存,根据方法生成缓存,参考代码如下:

@Service
public class UserService {
 @Cacheable(value = "redis-key")
 public UserInfo getUserInfo(Long id, String sex, int age, String name) {
   System.out.println("无缓存时调用----数据库查询");
   return new UserInfo(id, sex, age, name);
 }
}

注意:value的值就是缓存到redis中的key,此key是需要自己在进行增加缓存信息时定义的key,用于标识唯一性的。

Session 共享

分布式系统中session共享有很多不错的解决方案,其中托管到缓存中是比较常见的方案之一,下面利用Session-spring-session-data-redis实现session共享。

引入依赖,在pom.xml配置文件中增加如下内容:

<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-data-redis</artifactId>
</dependency>

Session配置,具体代码如下:

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionConfig {
}

maxInactiveIntervalInSeconds: 设置Session失效时间,使用Redis Session之后,原Spring Boot的server.session.timeout属性不再生效。

测试实例,具体代码如下:

@RequestMapping("uid")
String uid(HttpSession session) {
UUID uid = (UUID) session.getAttribute("uid");
if (uid == null) {
uid = UUID.randomUUID();
}
session.setAttribute("uid", uid);
return session.getId();
}

登录redis服务端,输入命令keys 'session*',查看缓存是否成功。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • spring boot与redis 实现session共享教程

    如果大家对spring boot不是很了解,大家可以参考下面两篇文章. Spring Boot 快速入门教程 Spring Boot 快速入门指南 这次带来的是spring boot + redis 实现session共享的教程. 在spring boot的文档中,告诉我们添加@EnableRedisHttpSession来开启spring session支持,配置如下: @Configuration @EnableRedisHttpSession public class RedisSessi

  • 详解基于Spring Boot/Spring Session/Redis的分布式Session共享解决方案

    分布式Web网站一般都会碰到集群session共享问题,之前也做过一些Spring3的项目,当时解决这个问题做过两种方案,一是利用nginx,session交给nginx控制,但是这个需要额外工作较多:还有一种是利用一些tomcat上的插件,修改tomcat配置文件,让tomcat自己去把Session放到Redis/Memcached/DB中去.这两种各有优缺,也都能解决问题. 但是现在项目全线Spring Boot,并不自己维护Tomcat,而是由Spring去启动Tomcat.这样就会有一

  • 详解Spring-Boot集成Spring session并存入redis

    spring Session 提供了一套用于管理用户 session 信息的API和实现. Spring Session为企业级Java应用的session管理带来了革新,使得以下的功能更加容易实现: 编写可水平扩展的原生云应用. 将session所保存的状态卸载到特定的外部session存储中,如Redis或Apache Geode中,它们能够以独立于应用服务器的方式提供高质量的集群. 当用户使用WebSocket发送请求的时候,能够保持HttpSession处于活跃状态. 在非Web请求的处

  • 学习Spring-Session+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.cl

  • Spring Boot项目利用Redis实现session管理实例

    在现代网络服务中,session(会话)不得不说是非常重要也是一定要实现的概念,因此在web后台开发中,对session的管理和维护是必须要实现的组件.这篇文章主要是介绍如何在Spring Boot项目中加入redis来实现对session的存储与管理. 1. 利用Spring Initializr来新建一个spring boot项目 2. 在pom.xml中添加redis和session的相关依赖.项目生成的时候虽然也会自动生成父依赖,但是1.5.3版本的spring boot的redis相关

  • 利用Spring Session和redis对Session进行共享详解

    前言 我们在搭建完集群环境后,不得不考虑的一个问题就是用户访问产生的session如何处理. session的处理有很多种方法,详情见转载的上篇博客:集群/分布式环境下5种session处理策略 在这里我们讨论其中的第三种方法:session共享. redis集群做主从复制,利用redis数据库的最终一致性,将session信息存入redis中.当应用服务器发现session不在本机内存的时候,就去redis数据库中查找,因为redis数据库是独立于应用服务器的数据库,所以可以做到session

  • Spring Boot高级教程之使用Redis实现session共享

    Redis是一个缓存消息中间件及具有丰富特性的键值存储系统.Spring Boot为Jedis客户端库和由Spring Data Redis提供的基于Jedis客户端的抽象提供自动配置.spring-boot-starter-redis'Starter POM'为收集依赖提供一种便利的方式. 引入spring-boot-starter-redis,在pom.xml配置文件中增加配置如下(基于之前章节"Spring Boot 构建框架"中的pom.xml文件): <dependen

  • 多个SpringBoot项目采用redis实现Session共享功能

    有时我们可能有多个不同的Web应用,可以相互调用,这时如果每个应用都有自己的session,那用户跳转到另一个应用时就又需要登陆一次,这样会带来很不好的体验,因此我们需要在不同的应用中共享session.这里,我们采用redis来实现. 前置说明 由于只用到redis和springboot的整合,所以只能实现一个URL下的不同端口的应用之间的session共享,如果连应用名称都完全不同的两个应用要实现session共享,在这个基础上还需要使用到Nginx,这种方式我暂时还没有试过.(Spring

  • redis实现session共享的方法

    目录 引言 案例介绍 具体操作 引言 大厂很多项目都是部署到多台服务器上,这些服务器在各个地区都存在,当我们访问服务时虽然执行的是同一个服务,但是可能是不同服务器运行的: 在我学习项目时遇到这样一个登录情景,假设有如下三台服务器(如图),就使用session存放用户的登录信息,通过该信息可以判断用户是否登录: 假设本次登录是通过服务器01执行的,那么这次的登录session信息就存放到了内存01中:但是当我再次访问时却是服务器02执行操作,而登录session信息却在内存01中,服务器02无法获

  • SpringBoot+SpringSession+Redis实现session共享及唯一登录示例

    最近在学习springboot,session这个点一直困扰了我好久,今天把这些天踩的坑分享出来吧,希望能帮助更多的人. 一.pom.xml配置 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency>

  • Redis解决Session共享问题的方法详解

    企业项目中,一般都是将项目部署到多台服务器上,用nginx做负载均衡.这样可以减轻单台服务器的压力,不过这样也带来一些问题,例如之前单机部署的话,session存取都是直接了当的,因为请求就只到这一台服务器上,不需要考虑数据共享.接下来分别用8000和8001端口启动同一个项目,做一个简单演示: 测试接口代码: package com.wl.standard.controller; import cn.hutool.core.util.StrUtil; import com.wl.standar

  • Redis实现Session共享与单点登录

    首先,导包. 在pom.xml文件里面加入以下: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.session</g

  • Spring Boot 入门教程

    简介 相信很多人都接触spring框架很长时间了,每次搭建spring框架的时候都需要配置好多的jar.xml,做很多繁琐重复的配置,稍微不留神就会出现各种各样的问题,每次调试真的是香菇.蓝瘦啊. spring boot的出现帮助我们彻底解决了这些jar的依赖,只需要很少的配置就可以完成我们的开发工作,我们可以把自己的应用打包成jar,使用java -jar来运行spring web应用,spring boot集成了很多的web容器.今天给大家介绍一下spring Boot MVC,让我们学习一

  • Spring Boot实战教程之自动配置详解

    前言 大家应该都有所了解,随着Ruby.Groovy等动态语言的流行,相比较之下Java的开发显得格外笨重.繁多的配置.低下的开发效率.复杂的部署流程以及第三方技术集成难度大等问题一直被人们所诟病.随着Spring家族中的新星Spring Boot的诞生,这些问题都在逐渐被解决. 个人觉得Spring Boot中最重要的两个优势就是可以使用starter简化依赖配置和Spring的自动配置.下面这篇文章将给大家详细介绍Spring Boot自动配置的相关内容,话不多说,来一起看看详细的介绍. 使

  • Spring Boot高级教程之Spring Boot连接MySql数据库

    Spring Boot可以大大简化持久化任务,几乎不需要写SQL语句,在之前章节"Spring Boot 构建框架"中我们新建了一个Spring Boot应用程序,本章在原有的工程中与数据库建立连接. Spring Boot有两种方法与数据库建立连接,一种是使用JdbcTemplate,另一种集成Mybatis,下面分别为大家介绍一下如何集成和使用这两种方式. 1. 使用JdbcTemplate <dependency> <groupId>mysql</g

随机推荐