缓存springboot整合redis01
Posted lazyli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了缓存springboot整合redis01相关的知识,希望对你有一定的参考价值。
eclipse创建springboot要注意,基本的包名一定要与java中的包名一致,这样才能找到springgboot主程序的入口;
主程序是在com.lazy.cache;那么test的包也要是com.lazy.cache
src/main/java
com.lazy.cache
CacheApplication.java
src/test/java
com.lazy.cahche
UserTest.java
----
注:#开启mybatis驼峰命名,数据字段名与属性名不一致,如:t_id,tId;需要开启这个,不然查询的结果为null
mybatis.configuration.map-underscore-to-camel-case=true
--------------
springboot知识点:
springboot-cache(缓存):
需要引入springboot缓存依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
--------------
1、开启基于注解的缓存,在主程序入口类上面,使用注解@EnableCaching
MapperScan("com.lazy.cache.mapper")//扫描mapper接口
@SpringBootApplication
@EnableCaching
public class CacheApplication {
public static void main(String[] args) {
SpringApplication.run(CacheApplication.class, args);
}
}
2、标注缓存注解(需要的缓存的方法上,将方法返回结果放入缓存中)
@Cacheable 对方法中的返回结果放入缓存中
/**
* @Cacheable(key-value的形式)
* 有几个属性:
* cacheNames/value指定缓存组件的名字,员工放在emp组件中,里面可以放入多个key-value
* key:缓存中的key名字,默认是方法参数的值,比如这里的id=1,那么key就是1;可以知道SpEL表达式指定key值
* #root.args[0]是取方法参数第一个参数等价于#id
自定义key(名为getEmployeeById[id]): key="#root.method.name+‘[‘+#id+‘]‘";方法名加参数的形式
自定义key生成器,
* keyGenerator:key的生成器
* key/keyGenerator二选一
* cacheManager:指定缓存管理器
* condition:指定符合条件的情况下进行缓存
* condition="#id>0"
* unless:符合条件的不缓存,与condition相反
* #result可以取到结果的返回值
* sync:缓存是否使用异步
*/
@Cacheable(cacheNames={"emp"})
public Employee getEmployeeById(Integer id) {
System.out.println("查询"+id+"号信息");
Employee employee = employeeMapper.getEmployeeById(id);
return employee;
}
原理:
1、自动配置类:CacheAutoConfiguration
2、缓存的配置类:默认redis
运行流程:
1、方法运行之前,先去查询cache,按照指定的cacheNames指定的名字获取缓存,第一次获取缓存(是为null)会先创建缓存(名为emp,这里的key是默认id)
2、去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;key是按照某种策略生成的;默认是使用keyGenerator生成的,
3、没有查到缓存就调用目标方法
4、将目标方法返回结果,放进缓存中
@Cacheable标注的方法执行之前先检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,如果没有就进入目标方法中,到数据库中查询;数据库查询的结果返回,会将该结果放入到缓存中,下次在进行这个key查询,也会先到缓存中查询,缓存中存在这个key,就直接返回这个结果,不进入方法中。
注:配置前面的直接运行,会出现异常(找不到端口).但开启redis后,可以正常运行。看视频,都能正常运行,也没开rdeis,这是什么原因,还有这样cache的数据是存储在哪里的。版本问题,在1.5springboot版本默认的是SimpleCacheConfiguration,而在2.1版本是默认的是RedisCacheConfiguration缓存生效。所以在缓存需要打开redis服务端,在配置文件配置debug=true;可以看到容器启动加载了多少类。上面的是错误的,默认的还是SimpleCacheConfiguration,造成的原因是导入了redis的starter,它会启动redis的,如果没有导入redis的starter默认的还是SimpleCacheConfiguration。
--------------
@CachePut修改了某数据,更新缓存,同步缓存
/**
* @CachePut执行时机:是先执行目标方法,然后将方法的返回结果,更新到缓存中
* key="#employee.id"可以用key="#result.id"
* 属性基本相同
*/
@CachePut(value="emp",key="#employee.id")
public Employee updateEmployee(Employee employee) {
System.out.println("更新员工:"+employee);
employeeMapper.updateEmployee(employee);
return employee;
}
@CacheEvict清除缓存
/**
* 删除缓存
* allEntries默认是false,
* @CacheEvict(value="emp",allEntries=true)")清除emp组件中所有缓存
* beforeInvocation默认是false,清除缓存在方法之后执行。
* 设置为true,可以在方法前执行,尽管方法中出现异常也可以清除数据库
*/
@CacheEvict(value="emp",key="#id",allEntries=true)
public void DeleteEmployee(Integer id) {
System.out.println("将缓存中的数据清除!,这里并没有把数据库中的数据删除");
}
----------
/**
* 组合成复杂的缓存,
* @Cacheable(value="emp",key="#lastName")执行目标方法前
* @CachePut(value="emp",key="#result.id"),
* 将执行方法后以key="#result.id",key="#result.email存入缓存中
* @param lastName
* @return
* 出现异常信息
*/
/*@Caching(
cacheable = {
@Cacheable(value="emp",key="#lastName")
},
put = {
@CachePut(value="emp",key="#result.id"),
@CachePut(value="emp",key="#result.email")
}
)*/
public Employee getEmpByLastName(String lastName) {
Employee employee = employeeMapper.getEmpByLastName(lastName);
return employee;
}
springboot整合redis
1、使用docker安装redis,这里使用widows版本,可以在redis官方文档中有详细的信息
2、引入redis的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
3、在配置文件中配置redis(不需要指定端口,默认的是6379)
spring.redis.host=127.0.0.1
public class RedisTest {
@Autowired
private EmployeeMapper employeeMapper;
@Autowired
private StringRedisTemplate stringRedisTemplate;//key-value是字符串形式
@Autowired
private RedisTemplate redisTemplate;//key-value是Object-Object的形式
@Autowired
private RedisTemplate<Object, Employee> empRedisTemplate;//自定义的redis模板,以json序列化
/**
* 以stringRedisTemplate操作redis
* redis可以存储五种类型的数据结构,String类型,hash类型,set,list,zset
* stringRedisTemplate.opsForValue()是操作String类型的
* stringRedisTemplate.opsForHash()是操作hash类型
* stringRedisTemplate.opsForSet()是操作Set类型
* stringRedisTemplate.opsForZSet()是操作ZSet类型
* stringRedisTemplate.opsForList()是操List类型
*/
@Test
public void demoRedis(){
//向redis中添加一个string类型的数据
//stringRedisTemplate.opsForValue().append("msg", "hello");
//获取redis中的元素
//String msg = stringRedisTemplate.opsForValue().get("msg");
//System.out.println(msg);
//添加一个list数据,是从左边插入的,
//stringRedisTemplate.opsForList().leftPush("mylist", "first");
//stringRedisTemplate.opsForList().leftPush("mylist", "second");
//获取list的数据
String result = stringRedisTemplate.opsForList().leftPop("mylist");
System.out.println(result);
}
/**
* 使用redisTemplate操作存储对象
*/
@Test
public void testRedis(){
Employee employee = employeeMapper.getEmployeeById(1);
//这里存放到redis是jdk序列化的数据,不是像json的数据类型
//如果要对象在redis中以json数据呈现,需要设置配置类,序列化(使用json Serializable)
//redisTemplate.opsForValue().set("emp01", employee);
empRedisTemplate.opsForValue().set("emp01", employee);
}
}
----------------
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object,Employee> empRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
template.setConnectionFactory(redisConnectionFactory);
//设置序号化形式,以json
Jackson2JsonRedisSerializer<Employee> serializer = new Jackson2JsonRedisSerializer<>(Employee.class);
template.setDefaultSerializer(serializer);
return template;
}
}
上面的是测试:现在在项目中运用,保存对象时,还是默认的jdk序列化。要保存json的话:
1、引入redis的starter,cacheMananger变为RedisCacheManager
2、默认创建的RedisCacheManager操作redis的时候使用的是RedisTemplate<Object,Object>,
3、RedisTemplate<Object,Object>默认使用是JDK序列化,
4、自定义CacheMananger,
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
@Autowired
private EmployeeMapper employeeMapper;
@Autowired
private StringRedisTemplate stringRedisTemplate;//key-value是字符串形式
@Autowired
private RedisTemplate redisTemplate;//key-value是Object-Object的形式
//@Autowired
//private RedisTemplate<Object, Employee> empRedisTemplate;//自定义的redis模板,以json序列化
/**
* 以stringRedisTemplate操作redis
* redis可以存储五种类型的数据结构,String类型,hash类型,set,list,zset
* stringRedisTemplate.opsForValue()是操作String类型的
* stringRedisTemplate.opsForHash()是操作hash类型
* stringRedisTemplate.opsForSet()是操作Set类型
* stringRedisTemplate.opsForZSet()是操作ZSet类型
* stringRedisTemplate.opsForList()是操List类型
*/
@Test
public void demoRedis(){
//向redis中添加一个string类型的数据
//stringRedisTemplate.opsForValue().append("msg", "hello");
//获取redis中的元素
//String msg = stringRedisTemplate.opsForValue().get("msg");
//System.out.println(msg);
//添加一个list数据,是从左边插入的,
//stringRedisTemplate.opsForList().leftPush("mylist", "first");
//stringRedisTemplate.opsForList().leftPush("mylist", "second");
//获取list的数据
String result = stringRedisTemplate.opsForList().leftPop("mylist");
System.out.println(result);
}
/**
* 使用redisTemplate操作存储对象
*/
@Test
public void testRedis(){
Employee employee = employeeMapper.getEmployeeById(1);
//这里存放到redis是jdk序列化的数据,不是像json的数据类型
//如果要对象在redis中以json数据呈现,需要设置配置类,序列化(使用json Serializable)
//redisTemplate.opsForValue().set("emp01", employee);
redisTemplate.opsForValue().set("emp01", employee);
}
}
------------
@Configuration
public class MyRedisConfig {
/**
* 直接使用模板操作redis需要这样设置
* @param redisConnectionFactory
* @return
* @throws UnknownHostException
*/
@Bean
public RedisTemplate<Object,Employee> empRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
template.setConnectionFactory(redisConnectionFactory);
//设置序号化形式,以json
Jackson2JsonRedisSerializer<Employee> serializer = new Jackson2JsonRedisSerializer<>(Employee.class);
template.setDefaultSerializer(serializer);
return template;
}
/**
* 这是在项目中,将对象存入redis中以json形式,
*,2.x版本没有new RedisCacheManager(RedisTemplate)构造方法
* 使用这个的话new RedisCacheManager(RedisTemplate),
* 在项目中需要给每个存储对象都写RedisTemplate<Object,Object);
* 下面这个设置可以通用
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
//初始化一个RedisCacheWriter
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer();
RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.
SerializationPair.fromSerializer(jsonSerializer);
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(pair);
return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
}
/**
* 缓存管理器
*/
/* @Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
//初始化一个RedisCacheWriter
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
//设置CacheManager的值序列化方式为json序列化
RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer();
RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair
.fromSerializer(jsonSerializer);
RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(pair);
//设置默认超过期时间是30秒
defaultCacheConfig.entryTtl(Duration.ofSeconds(30));
//初始化RedisCacheManager
return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
}*/
}
注:可以使用两种方法进行redis缓存,一种是注入RedisTemplate模板操作,这种操作比较复杂,但比较灵活,在程序指定的位置进行放入。
第二种方式使用注解方式,@Cachalbe,等等
----------
不使用注解:
注入缓存管理器
Cache dept = deptCacheManager.getCache("dept");//dept是上面注解的@Cacheable(value="dept")形式
dept.put("dept:1",department);
以上是关于缓存springboot整合redis01的主要内容,如果未能解决你的问题,请参考以下文章