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*',查看缓存是否成功。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Spring Boot高级教程之使用Redis实现session共享
-
spring boot整合redis实现shiro的分布式session共享的方法
-
Spring Boot分布式系统实践【扩展1】shiro+redis实现session共享、simplesession反序列化失败的问题定位及反思改进
-
Spring boot + redis 实现session 共享管理
-
Spring boot(二)使用redis实现session共享
-
java | Spring Boot 与 Redis 实现 Cache 以及 Session 共享
-
Spring Boot 整合 Redis + Spring Session(实现 Session 共享)
-
Spring Boot使用Redis实现session共享
-
使用spring session redis实现共享session之后,httpsession监听失效 redisspringhttpsessionsessionSessionDestroyedEvent
-
Spring Boot分布式系统实践【扩展1】shiro+redis实现session共享、simplesession反序列化失败的问题定位及反思改进