⑴ spring boot + redis 实现session共享分析
HttpSession是由servelet容器进行管理的。而我们常用的应用容器有 Tomcat/Jetty等, 这些容器的HttpSession都是存放在对应的应用容器的岩弯内存中,在分布式集群的环境下,通常我们使用Nginx或者LVS、Zuul等进行反向代理和负载均衡,因此用户请求是由一组提供相同服务的应用来进行处理,而用户最终请求到的服务由Nginx和LVS、Zuul进行确定。
那么问题就来了,我们怎样保证多个相同的应用共享同一份session数据?对于这种问题Spring为我们提供了Spring Session进行管理我们的HttpSession。项目地址: http://projects.spring.io/spring-session/
1.添加Spring session的包,而Spring session 是将HttpSession存放在Redis中,因此启唯需要添加Redis的包。我们这里是用了悄枣培Spring boot进行配置Rdies。
2.使用@EnableRedisHttpSession注解进行配置启用使用Spring session。
3.配置我们的Redis链接,我们这里使用的是Spring Boot作为基础进行配置,因此我们只需要在YML或者Properties配置文件添加Redis的配置即可。
4.创建请求的控制器来进行确定我们是否启用Session 共享。
5.将当前的工程拷贝一份.
通过上面请求显示的结果我们可以看出使用的是同一个Seesion,我们也可以查看下存在Redis中的Session。我这里使用RDM进行查看,我们还可以查看Session的属性。从图可以看出我们存进入的url属性。
我们从启动Spring Session的配置注解@EnableRedisHttpSession开始。
1.我们可以通过@EnableRedisHttpSession可以知道,Spring Session是通过RedisHttpSessionConfiguration类进行配置的。
2.我们在RedisHttpSessionConfiguration类种的注释可以知道,该类是用于创建一个过滤SessionRepositoryFilter。
3.探究下SessionRepositoryFilter类是在哪里创建创建过程作用。
(1)哪里创建:
通过搜索RedisHttpSessionConfiguration发现SessionRepositoryFilter的创建不是在RedisHttpSessionConfiguration,而是在父类中创建。
(2)SessionRepositoryFilter创建过程:
这里我们可以总结下:
Redis确保链接的情况下。
1.创建sessionRedisTemplate
2.创建
3.创建SessionRepositoryFilter
(3)SessionRepositoryFilter的作用:
SessionRepositoryFilter的主要作用接管Seession的管理。我们可以从下面几个点知道为什么?
4.我们研究下是怎样接管Session?
(1)存储Session的过程
当调用SessionRepositoryFilter.this.sessionRepository.save(session)完毕后,会判断当前的SessionId是否与请求的中的Cookie中SessionId一致,若不一致的情况下会调用onNewSession()方法,我们可以通过配置类的可以看到使用的是
CookieHttpSessionStrategy();
从CookieHttpSessionStrategy.onNewSession()方法可以看到是将SessionId写到Cookie中。
(2)获取Session的过程
我们根据源码的分析可以知道:
1.Spring Session 是通过SessionRepositoryFilter过滤器进行拦截,然后通过继承HttpServletRequestWrapper进行管理Session。
2.Spring Session 为我们提供了3中存放的策略而每种策略提供对应的注解启动。分别为:
(1)NoSql形式的MongoDb:@EnableMongoHttpSession
(2)持久化形式的JDBC:@EnableJdbcHttpSession
(3)缓存形式的Redis:@EnableRedisHttpSession
3.Spring Session 共享Session过程:
(1)先过程过滤器存储将SessionID存放到本地的Cookie 和Redis中。
如果本地没有启用Cookie的情况下,Spring Session也就不能使用。
(2)获取Session的时候,先从请求中获取Session,Session不为空的情况下直接返回Session,若当前的Session为空的情况下,从Cookie中获取SessionId,判断SessionId不为空,再从Redis中获取Session,若从Redis中获取到的Session不为空将Session存放到请求中,再返回Session,如果从Redis中获取的Session为空,再创建新的Session并且添加到请求中,后返回Session。
⑵ springboot--redis配置
基于spring.version:4.x;
4.2.4.RELEASE
不同spring版本敏枯世对应的redis版本也不一败慎样,配置桥肢类也会不同。
添加pom:
redis参数配置:RedisConfig.class
redis配置类:RedisConfiguration.class
redis工具类:redisUtils.class
示例使用
⑶ 3分钟搞定springboot整合redis
不多说直接上代码:
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 添加jedis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!--spring2.0集成redis所需common-pool2-->
<!-- 必须加上,jedis依赖此 -->
<dependency>
<groupId>org.apache.commons<枯卖/groupId>
<artifactId>commons-pool2</artifactId>
<version>2.5.0</version>
</dependency>
<!-- 将作为Redis对象序列化器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
#Matser的ip地址
redis.hostName=172.16.44.148
#端口号
redis.port=6379
#如果有密码
redis.password=
#客户端超时时间单位是毫秒 默认是2000
redis.timeout=10000
#最大空闲数
redis.maxIdle=300
#连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal
#redis.maxActive=600
#控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性
redis.maxTotal=1000
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
redis.maxWaitMillis=1000
#连接的最小空闲卖没时间没配逗 默认1800000毫秒(30分钟)
redis.minEvictableIdleTimeMillis=300000
#每次释放连接的最大数目,默认3
redis.numTestsPerEvictionRun=1024
#逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
redis.timeBetweenEvictionRunsMillis=30000
#是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
redis.testOnBorrow=true
#在空闲时检查有效性, 默认false
redis.testWhileIdle=true
package com.junsi.demo.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
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.serializer.;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.junsi.demo.utils.RedisUtil;
import redis.clients.jedis.JedisPoolConfig;
/**
* Redis配置类
* @author pzx
* 2019年6月8日
*/
@Configuration
@PropertySource("classpath:redis.properties")
public class RedisConfig {
@Value("${redis.maxIdle}")
private Integer maxIdle;
@Value("${redis.maxTotal}")
private Integer maxTotal;
@Value("${redis.maxWaitMillis}")
private Integer maxWaitMillis;
@Value("${redis.minEvictableIdleTimeMillis}")
private Integer minEvictableIdleTimeMillis;
@Value("${redis.numTestsPerEvictionRun}")
private Integer numTestsPerEvictionRun;
@Value("${redis.timeBetweenEvictionRunsMillis}")
private long timeBetweenEvictionRunsMillis;
@Value("${redis.testOnBorrow}")
private boolean testOnBorrow;
@Value("${redis.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.redis.cluster.nodes}")
private String clusterNodes;
@Value("${spring.redis.cluster.max-redirects}")
private Integer mmaxRedirectsac;
/**
* JedisPoolConfig 连接池
* @return
*/
@Bean
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 最大空闲数
jedisPoolConfig.setMaxIdle(maxIdle);
// 连接池的最大数据库连接数
jedisPoolConfig.setMaxTotal(maxTotal);
// 最大建立连接等待时间
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
// 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
jedisPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
// 每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
jedisPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
// 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
jedisPoolConfig.(timeBetweenEvictionRunsMillis);
// 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
jedisPoolConfig.setTestOnBorrow(testOnBorrow);
// 在空闲时检查有效性, 默认false
jedisPoolConfig.setTestWhileIdle(testWhileIdle);
return jedisPoolConfig;
}
/**
* @param jedisPoolConfig
* @return
*/
@Bean
public JedisConnectionFactory JedisConnectionFactory(JedisPoolConfig jedisPoolConfig){
JedisConnectionFactory JedisConnectionFactory = new JedisConnectionFactory(jedisPoolConfig);
//连接池
JedisConnectionFactory.setPoolConfig(jedisPoolConfig);
//IP地址
JedisConnectionFactory.setHostName("172.16.44.148");
//端口号
JedisConnectionFactory.setPort(6379);
//如果Redis设置有密码
//JedisConnectionFactory.setPassword(password);
//客户端超时时间单位是毫秒
JedisConnectionFactory.setTimeout(5000);
return JedisConnectionFactory;
}
/**
* 实例化 RedisTemplate 对象
*
* @return
*/
@Bean
public RedisTemplate<String, Object> functionDomainRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
initDomainRedisTemplate(redisTemplate, redisConnectionFactory);
return redisTemplate;
}
/**
* 设置数据存入 redis 的序列化方式,并开启事务
*
* @param redisTemplate
* @param factory
*/
private void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) {
//如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new ());
redisTemplate.setValueSerializer(new ());
// 开启事务
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.setConnectionFactory(factory);
}
@Bean(name = "redisUtil")
public RedisUtil redisUtil(RedisTemplate<String, Object> redisTemplate) {
RedisUtil redisUtil = new RedisUtil();
redisUtil.setRedisTemplate(redisTemplate);
return redisUtil;
}
}
⑷ windows环境下Redis+Spring缓存实例
一、Redis了解
1.1、Redis介绍:
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis数据库完全在内存中,使用磁盘仅用于持久性。相比许多键值数据存储,Redis拥有一套较为丰富的数据类型。Redis可以将数据复制到任意数量的从服务器。
1.2、Redis优点:
(1)异常快速:Redis的速度非常快,每秒能执行约11万集合,每秒约81000+条记录。
(2)支持丰富的数据类型:Redis支持最大多数开发人员已经知道像列表,集合,有序集合,散列数据类型。这使得它非常容易解决各种各样的问题,因为我们知道哪些问题是可以处理通过它的数据类型更好。
(3)操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。
(4)多功能实用工具:Redis是一个多实用的工具,可以在多个用例如缓存,消息,队列使用(Redis原生支持发布/订阅),任何短暂的数据,应用程序,如Web应用程序会话,网页命中计数等。
1.3、Redis缺点:
(1)单线程
(2)耗内存
二、64位windows下Redis安装
Redis官方是不支持windows的,但是Microsoft Open Tech group 在 GitHub上开发了一个Win64的版本,下载地址:https://github.com/MSOpenTech/redis/releases。注意只支持64位哈。
小宝鸽是下载了Redis-x64-3.0.500.msi进行安装。安装过程中全部采取默认即可。
安装完成之后可能已经帮你开启了Redis对应的服务,博主的就是如此。查看资源管理如下,说明已经开启:
已经开启了对应服务的,我们让它保持,下面例子需要用到。如果没有开启的.,我们命令开启,进入Redis的安装目录(博主的是C:Program FilesRedis),然后如下命令开启:
redis-server redis.windows.conf
OK,下面我们进行实例。
三、详细实例
本工程采用的环境:Eclipse + maven + spring + junit
3.1、添加相关依赖(spring+junit+redis依赖),pom.xml:
4.0.0 com.luo redis_project 0.0.1-SNAPSHOT 3.2.8.RELEASE 4.10 org.springframework spring-core ${spring.version} org.springframework spring-webmvc ${spring.version} org.springframework spring-context ${spring.version} org.springframework spring-context-support ${spring.version} org.springframework spring-aop ${spring.version} org.springframework spring-aspects ${spring.version} org.springframework spring-tx ${spring.version} org.springframework spring-jdbc ${spring.version} org.springframework spring-web ${spring.version} junit junit ${junit.version} test org.springframework spring-test ${spring.version} test org.springframework.data spring-data-redis 1.6.1.RELEASE redis.clients jedis 2.7.3
3.2、spring配置文件application.xml:
<"1.0" encoding="UTF-8"> classpath:properties/*.properties
3.3、Redis配置参数,redis.properties:
#redis中心#绑定的主机地址redis.host=127.0.0.1#指定Redis监听端口,默认端口为6379redis.port=6379#授权密码(本例子没有使用)redis.password=123456 #最大空闲数:空闲链接数大于maxIdle时,将进行回收redis.maxIdle=100 #最大连接数:能够同时建立的“最大链接个数”redis.maxActive=300 #最大等待时间:单位msredis.maxWait=1000 #使用连接时,检测连接是否成功 redis.testOnBorrow=true#当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能redis.timeout=10000
3.4、添加接口及对应实现RedisTestService.java和RedisTestServiceImpl.java:
package com.luo.service; public interface RedisTestService { public String getTimestamp(String param);}
package com.luo.service.impl; import org.springframework.stereotype.Service;import com.luo.service.RedisTestService; @Servicepublic class RedisTestServiceImpl implements RedisTestService { public String getTimestamp(String param) { Long timestamp = System.currentTimeMillis(); return timestamp.toString(); } }
3.5、本例采用spring aop切面方式进行缓存,配置已在上面spring配置文件中,对应实现为MethodCacheInterceptor.java:
package com.luo.redis.cache; import java.io.Serializable;import java.util.concurrent.TimeUnit;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ValueOperations; public class MethodCacheInterceptor implements MethodInterceptor { private RedisTemplate redisTemplate; private Long defaultCacheExpireTime = 10l; // 缓存默认的过期时间,这里设置了10秒 public Object invoke(MethodInvocation invocation) throws Throwable { Object value = null; String targetName = invocation.getThis().getClass().getName(); String methodName = invocation.getMethod().getName(); Object[] arguments = invocation.getArguments(); String key = getCacheKey(targetName, methodName, arguments); try { // 判断是否有缓存 if (exists(key)) { return getCache(key); } // 写入缓存 value = invocation.proceed(); if (value != null) { final String tkey = key; final Object tvalue = value; new Thread(new Runnable() { public void run() { setCache(tkey, tvalue, defaultCacheExpireTime); } }).start(); } } catch (Exception e) { e.printStackTrace(); if (value == null) { return invocation.proceed(); } } return value; } /** * 创建缓存key * * @param targetName * @param methodName * @param arguments */ private String getCacheKey(String targetName, String methodName, Object[] arguments) { StringBuffer sbu = new StringBuffer(); sbu.append(targetName).append("_").append(methodName); if ((arguments != null) && (arguments.length != 0)) { for (int i = 0; i < arguments.length; i++) { sbu.append("_").append(arguments[i]); } } return sbu.toString(); } /** * 判断缓存中是否有对应的value * * @param key * @return */ public boolean exists(final String key) { return redisTemplate.hasKey(key); } /** * 读取缓存 * * @param key * @return */ public Object getCache(final String key) { Object result = null; ValueOperations operations = redisTemplate .opsForValue(); result = operations.get(key); return result; } /** * 写入缓存 * * @param key * @param value * @return */ public boolean setCache(final String key, Object value, Long expireTime) { boolean result = false; try { ValueOperations operations = redisTemplate .opsForValue(); operations.set(key, value); redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } public void setRedisTemplate( RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; }}
3.6、单元测试相关类:
package com.luo.baseTest; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; //指定bean注入的配置文件 @ContextConfiguration(locations = { "classpath:application.xml" }) //使用标准的JUnit @RunWith注释来告诉JUnit使用Spring TestRunner @RunWith(SpringJUnit4ClassRunner.class) public class SpringTestCase extends { }
package com.luo.service; import org.junit.Test;import org.springframework.beans.factory.annotation.Autowired; import com.luo.baseTest.SpringTestCase; public class RedisTestServiceTest extends SpringTestCase { @Autowired private RedisTestService redisTestService; @Test public void getTimestampTest() throws InterruptedException{ System.out.println("第一次调用:" + redisTestService.getTimestamp("param")); Thread.sleep(2000); System.out.println("2秒之后调用:" + redisTestService.getTimestamp("param")); Thread.sleep(11000); System.out.println("再过11秒之后调用:" + redisTestService.getTimestamp("param")); } }
3.7、运行结果:
四、源码下载:redis-project().rar
以上就是本文的全部内容,希望对大家的学习有所帮助。
⑸ 怎么看spring-bootspring-data-redis
spring boot对常用的数据库支持外,对nosql 数据库也进行了封装自动化。
redis介绍
Redis是目前业界使用最广泛的内存数据存储。相比memcached,Redis支持更丰富的数据结构,例如hashes, lists,
sets等,同时支持数据持久化。除此之外,Redis还提供一些类数据库的特性,比如事务,HA,主从库。可以说Redis兼具了缓存系统和数据库的一些特性,因此有着丰富的应用场景。本文介绍Redis在Spring
Boot中两个典型的应用场景。
如何使用
1、引入 spring-boot-starter-redis
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
2、添加配置文件
# REDIS (RedisProperties)
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=192.168.0.58
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
3、添加cache的配置类
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
@Bean
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();
}
};
}
@SuppressWarnings("rawtypes")
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
//设置缓存过期时间
//rcm.setDefaultExpiration(60);//秒
return rcm;
}
@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;
}
}
3、好了,接下来就可以直接使用了
@RunWith(SpringJUnit4ClassRunner.class)
@(Application.class)
public class TestRedis {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate redisTemplate;
@Test
public void test() throws Exception {
stringRedisTemplate.opsForValue().set("aaa", "111");
Assert.assertEquals("111", stringRedisTemplate.opsForValue().get("aaa"));
}
@Test
public void testObj() throws Exception {
User user=new User("[email protected]", "aa", "aa123456", "aa","123");
ValueOperations<String, User> operations=redisTemplate.opsForValue();
operations.set("com.neox", user);
operations.set("com.neo.f", user,1,TimeUnit.SECONDS);
Thread.sleep(1000);
//redisTemplate.delete("com.neo.f");
boolean exists=redisTemplate.hasKey("com.neo.f");
if(exists){
System.out.println("exists is true");
}else{
System.out.println("exists is false");
}
// Assert.assertEquals("aa", operations.get("com.neo.f").getUserName());
}
}
以上都是手动使用的方式,如何在查找数据库的时候自动使用缓存呢,看下面;
4、自动根据方法生成缓存
@RequestMapping("/getUser")
@Cacheable(value="user-key")
public User getUser() {
User user=userRepository.findByUserName("aa");
System.out.println("若下面没出现“无缓存的时候调用”字样且能打印出数据表示测试成功");
return user;
}
其中value的值就是缓存到redis中的key
⑹ Spring cloud 配置 Redis 单实例项目
使用centOS安装 redis 5.0.5版本,通过spring cloud配置中心设置配置服务
服务器地址 192.168.56.150
redis 安装目录在 /root/redis-5.0.5目录中,修改配置文件redis.conf
配置完成启动redis服蠢键举务
设置完成,重启配置中心服务亮拦
-在order项目工程中,新建一个接口类如带碧:
访问接口 http://127.0.0.1:8010/order/redis
集成的配置完成
⑺ 【原创】Springboot Redis配置总结( 基于spring-boot-data-redis-stater )
本配置方法主要基于各组件都低于目前市面最新版本的组件测试。
本配置方法主弊源要租桥态基于各组件都低于目前市消此面最新版本的组件测试。
⑻ 如何在spring配置文件中配置jedis连接池主从redis
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd"
default-lazy-init="false">
<!-- 连接池配置. -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 连接池中最大连接数。高版本:maxTotal,低版本:maxActive -->
<property name="maxTotal" value="8" />
<!-- 连接池中最大空闲的连接数. -->
<property name="maxIdle" value="4" />
<!-- 连接池中最少空闲的连接数. -->
<property name="minIdle" value="1" />
<!-- 当连接池誉拍资源耗尽时,调用者最大阻塞的时间,超时将跑出异常。单位,毫秒数;默认为-1.表示永不超时。高版本:maxWaitMillis,低版本:maxWait -->
<property name="maxWaitMillis" value="5000" />
<!-- 连接空闲的最小时间,达到此值后空闲连接将可能会被移除。负值(-1)表示不移除. -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<!-- 对于“空闲链接”检测线程而言,每次检测的链接资源的个数。默认为3 -->
<property name="numTestsPerEvictionRun" value="3" />
<!-- “空闲链接”检测线程,检测的周期,毫秒数。如果为负值,表示不运让巧行“检测线程”。默认为-1. -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- testOnBorrow:向调用者输出“链接”资源时,是否检测是有有效,如果无效则从连接池坦虚键中移除,并尝试获取继续获取。默认为false。建议保持默认值. -->
<!-- testOnReturn:向连接池“归还”链接时,是否检测“链接”对象的有效性。默认为false
⑼ Spring Boot如何整合Redis
Spring Boot是目前非常流行的Java Web开发框架,Redis是非关系型数据库的一种,以键值对的形式存储。Spring对Redis的支持是通过Spring Data Redis来实现的,给我们提供了RedisTemplate和StringRedisTemplate两种模板来操作数据。Spring Boot框架也提供了对Redis的支持,下面我们来讲一下Spring Boot框架整合Redis的步骤。
IntelliJ IDEA
Spring Boot整合Redis我们需要添加依赖的jar包,spring-boot-starter-data-redis中包含spring和redis相关的jar包,jedis作为redis的客户端也需要添加到工程中,Spring Boot的版本信息在父pom中已指定,子模块中的spring相关的jar包无需另外指定。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.0-m1</version>
</dependency>
Spring Boot会根据application.properties中的配置对Redis的属性进行自动配置,并注入到RedisProperties类中。在application.properties配置文件中这些属性都是以spring.redis为前缀的,值得注意的是在Spring Boot 1.5.x版本中默认的Redis客户端是jedis,因此在配置文件中无需指定,如下图所示。
Spring Boot 1.5.x版本的整合配置网上可以搜索大量的文章,然而Spring Boot 2.x版本的整合资料却非常少,甚至提供的配置不能正常使用,因此本文主要讲解Spring Boot 2.x整合Redis以及Redis的使用情况。spring-boot 2.x版本有jedis和lettuce两种客户端,因此我们必须要去指定使用哪一种客户端,两个客户端的配置如下图所示,本文使用的是Jedis客户端连接池,具体的配置如下。
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=xylx1.t!@#
# 配置jedis连接池
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1ms
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=5000ms
由配置我们可以看到spring-boot 2.x版本时间设置需要加单位ms,因为参数的类型为Duration。另外spring.redis.timeout尽量不要配置0,否则可能会出现io.lettuce.core.RedisCommandTimeoutException: Command timed out超时错误。
配置文件编辑完成后,我们开始编写代码实现Redis数据的存储和读取。我们创建一个RedisUtil工具类,该类使用@Component注解表示交由Spring管理,StringRedisTemplate是Spring提供的,可以使用@Autowired注解直接注入,接下来便可以书写存和取的代码了。
@Component
public class RedisUtil {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 存字符串
* @param key 缓存键
* @param value 缓存值
* @param expireTime 过期时间(s)
*/
public void setString(String key, String value, int expireTime){
ValueOperations<String, String> ops = redisTemplate.opsForValue();
if (expireTime != 0) {
ops.set(key, value, expireTime, TimeUnit.SECONDS);
} else {
ops.set(key,value);
}
}
/**
* 取字符串
* @param key 缓存键
* @return 缓存值
*/
public String getString(String key){
ValueOperations<String, String> ops = this.redisTemplate.opsForValue();
return ops.get(key);
}
接下来我们编写Controller层代码去调用RedisUtil工具类,实现数据的存储和读取,代码比较简单可以参考下图。若想验证Redis是否可用,还需要编写启动类,如下图所示。
由上图可看到我们编写了一个post请求用于存储字符串,get请求用于取出字符串。启动类通过main方法启动应用,接下来我们使用postman去模拟浏览器调用post和get请求,由下图可以看到Redis存储的数据成功被取出。
接下来我们介绍Jedis,这是一个封装了Redis的客户端,在Spring Boot整合Redis的基础上,可以提供更简单的API操作。因此我们需要配置JedisPool的Bean,代码如下,其中@Configuration注解表明这是一个配置类,我们在该类中注入RedisProperties,并且使用@Bean注解指定JedisPool。
@Configuration
public class RedisConfiguration {
@Autowired
private RedisProperties properties;
@Bean
public JedisPool getJedisPool(){
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(properties.getJedis().getPool().getMaxIdle());
config.setMaxTotal(properties.getJedis().getPool().getMaxActive());
config.setMaxWaitMillis(properties.getJedis().getPool().getMaxWait().toMillis());
JedisPool pool = new JedisPool(config,properties.getHost(),
properties.getPort(),100,
properties.getPassword(), properties.getDatabase());
return pool;
}
}
接下来我们编辑JedisUtil工具类,通过SpringBoot容器的@Component注解来自动创建,并且注入JedisPool,使用jedisPool.getResource()方法来获取Jedis,并最终实现操作redis数据库,其代码如下。
@Component
public class JedisUtil {
@Autowired
JedisPool jedisPool;
//获取key的value值
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String str = "";
try {
str = jedis.get(key);
} finally {
try {
jedis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return str;
}
public String set(String key, String value) {
Jedis jedis = jedisPool.getResource();
String str = "";
try {
str = jedis.set(key, value);
} finally {
try {
jedis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return str;
}
}
JedisUtil工具类编写完成后,我们修改之前的RedisController,并注入JedisUtil,代码如下图所示。然后再用postman分别调用post和get接口,我们可以看到成功取到了新的key的value值。
在Spring Boot整合Redis前本机需安装Redis,另外可以使用RedisDesktopManager这个Redis这个桌面管理工具查看Redis中的数据。
⑽ SpringBoot整合SpringSeesion实现Redis缓存
使用Spring Boot开发项目时我们经常需要存储Session,因为Session中会存一些用户信息或者登录信息。传统的web服务是将session存储在内存中的,一旦服务挂了,session也就消失了,这时候我们就需要将session存储起来,而Redis就是用来缓存seesion的一种非关系型数据库,我们可以通过配置或者注解的方式将Spring Boot和Redis整合。而在分布式系统中又会涉及到session共享的问题,多个服务同时部署时session需要共享,Spring Session可以帮助我们实现这一功能。将Spring Session集成到Spring Boot框架中并使用Redis进行缓存是目前非常流行的解决方案,接下来就跟着我一起学习吧。
IntelliJ IDEA
首先我们创建一个Spring Boot 2.x的项目,在application.properties配置文件中添加Redis的配置,Spring和Redis的整合可以参考我其他的文章,此处不再详解。我们设置服务端口server.port为8080端口用于启动第一个服务。
接下来我们需要在pom文件中添加spring-boot-starter-data-redis和spring-session-data-redis这两个依赖,spring-boot-starter-data-redis用于整合Spring Boot和Redis,spring-session-data-redis集成了spring-session和spring-data-redis,提供了session与redis的整合方案。
接下来我们创建一个配置类RedisSessionConfig,这个类使用@Configuration注解表明这是一个配置类。在这个类上我们同时添加注解@EnableRedisHttpSession,表示开启Redis的Session管理。如果需要设置失效时间可以使用@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)表示一小时后失效。若同时需要设置Redis的命名空间则使用@EnableRedisHttpSession(maxInactiveIntervalInSeconds=3600, redisNamespace="{spring.session.redis.namespace}") ,其中{spring.session.redis.namespace}表示从配置文件中读取这个命名空间。
配置完成后我们写一个测试类SessionController,在这个类中我们写两个方法,一个方法用于往session中存数据,一个用于从session中取数据,代码如下图所示,我们存取请求的url。启动类非常简单,一般都是通用的,我们创建一个名为SpringbootApplication的启动类,使用main方法启动。
接下来我们使用Postman分别请求上面两个接口,先请求存数据接口,再请求取数据接口,结果如下图所示,我们可以看到数据已从redis中取出。另外需要注意sessionId的值,这是session共享的关键。
为了验证两个服务是否共享了session,我们修改项目的配置文件,将服务端口server.port改为8090,然后再启动服务。此时我们不必在请求存数据的接口,只需要修改请求端口号再一次请求取数据的接口即可。由下图可以看到两次请求的sessionId值相同,实现了session的共享。
以上我们完成了SpringBoot整合SpringSeesion实现Redis缓存的功能,在此我们还要推荐一个Redis的可视化工具RedisDesktopManager,我们可以配置Redis数据库的连接,然后便可以非常直观地查看到存储到Redis中的session了,如下图所示,session的命名空间是share,正是从配置文件中读取到的。
如果Redis服务器是很多项目共用的,非常建议配置命名空间,否则同时打开多个项目的浏览器页面可能会导致session错乱的现象。