首页 > 编程 > Java > 正文

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

2019-11-26 11:03:08
字体:
来源:转载
供稿:网友

Redis是一个缓存消息中间件及具有丰富特性的键值存储系统。Spring BootJedis客户端库和由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>

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

@Componentpublic 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;   }  }

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

@Servicepublic 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 Bootserver.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*',查看缓存是否成功。

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表