缓存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);

猜你喜欢

转载自www.cnblogs.com/lazyli/p/10804264.html