Bootstrap

SpringBoot结合Redis Desktop Manager使用Redis缓存

@Cacheable缓存注解:

@Service
@CacheConfig(cacheNames = "person") //将cacheNames抽取出来
public class PersonService {
    @Autowired
    PersonDao personDao;
 
 
     /*1. @Cacheable的几个属性详解:
      *       cacheNames/value:指定缓存组件的名字
      *       key:缓存数据使用的key,可以用它来指定。默认使用方法参数的值,一般不需要指定
      *       keyGenerator:作用和key一样,二选一
      *       cacheManager和cacheResolver作用相同:指定缓存管理器,二选一
      *       condition:指定符合条件才缓存,比如:condition="#id>3"
      *                   也就是说传入的参数id>3才缓存数据
      *      unless:否定缓存,当unless为true时不缓存,可以获取方法结果进行判断
      *      sync:是否使用异步模式*/
     //@Cacheable(cacheNames= "person")
     //@Cacheable(cacheNames= "person",key="#id",condition="#id>3")
     @Cacheable(key="#id")
     public Person queryPersonById(Integer id){
        System.out.println("查询"+id+"号员工信息");
        Person person=new Person();
        person.setId(id);
        return personDao.query(person);
    }
 
    /**
     * @CachePut:即调用方法,又更新缓存数据
     * 修改了数据库中的数据,同时又更新了缓存
     *
     *运行时机:
     * 1.先调用目标方法
     * 2.将目标方法返回的结果缓存起来
     *
     * 测试步骤:
     * 1.查询1号的个人信息
     * 2.以后查询还是之前的结果
     * 3.更新1号的个人信息
     * 4.查询一号员工返回的结果是什么?
     *     应该是更新后的员工
     *     但只更新了数据库,但没有更新缓存是什么原因?
     * 5.如何解决缓存和数据库同步更新?
     * 这样写:@CachePut(cacheNames = "person",key = "#person.id")
     *         @CachePut(cacheNames = "person",key = "#result.id")
     */
    @CachePut(key = "#result.id")
    public Person updatePerson(Person person){
        System.out.println("修改"+person.getId()+"号员工信息");
        personDao.update(person);
        return person;
 
    }
    /**
     * @CacheEvict:清除缓存
     *    1.key:指定要清除缓存中的某条数据
     *    2.allEntries=true:删除缓存中的所有数据
     *    beforeInvocation=false:默认是在方法之后执行清除缓存
     *    3.beforeInvocation=true:现在是在方法执行之前执行清除缓存,
     *                          作用是:只清除缓存、不删除数据库数据
     */
    //@CacheEvict(cacheNames = "person",key = "#id")
    @CacheEvict(cacheNames = "person",allEntries=true)
    public void deletePerson(Integer id){
        System.out.println("删除"+id+"号个人信息");
        //删除数据库数据的同时删除缓存数据
        //personDao.delete(id);
 
        /**
         * beforeInvocation=true
         * 使用在方法之前执行的好处:
         * 1.如果方法出现异常,缓存依旧会被删除
         */
        //int a=1/0;
    }
    /**
     *   @Caching是 @Cacheable、@CachePut、@CacheEvict注解的组合
     *   以下注解的含义:
     *   1.当使用指定名字查询数据库后,数据保存到缓存
     *   2.现在使用id、age就会直接查询缓存,而不是查询数据库
     */
    @Caching(
            cacheable = {@Cacheable(key="#name")},
            put={ @CachePut(key = "#result.id"),
                  @CachePut(key = "#result.age")
                }
    )
    public Person queryPersonByName(String name){
        System.out.println("查询的姓名:"+name);
        return personDao.queryByName(name);
    }
}

使用Redis缓存:
ServiceImpl类

package com.szh.springboot_redis.service.impl;

import com.szh.springboot_redis.mapper.StudentMapper;
import com.szh.springboot_redis.pojo.Students;
import com.szh.springboot_redis.service.StudentService;
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.Service;
import java.util.List;


@Service
public class StudnetServiceImpl implements StudentService {

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 查询所有信息
     */
    @Override
    public List<Students> findAllStudnet() {
        String key = "student";
        ValueOperations<String, List<Students>> operations = redisTemplate.opsForValue();
        // 缓存存在
        boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            List<Students> students = operations.get(key);
            return students;
        }else {
            // 从 DB 中获取城市信息
            List<Students> students = studentMapper.findAllStudnet();
            // 插入缓存
            operations.set(key, students);
            return students;
        }
    }
    /**
     * 根据id查询信息
     */
    @Override
    public Students findStudentById(Integer id) {
        String key = "city_" + id;
        ValueOperations<String, Students> operations = redisTemplate.opsForValue();
        // 缓存存在
        boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            Students students = operations.get(key);
            return students;
        }else {
        // 从 DB 中获取城市信息
        Students students = studentMapper.findStudentById(id);
        // 插入缓存
        operations.set(key, students);
        return students;
        }
    }
    /**
     * 删除指定信息
     */
    @Override
    public int delStudent(Integer id) {
        int ret = studentMapper.delStudent(id);
        // 缓存存在,删除缓存
        String key = "studnet_" + id;
        boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            redisTemplate.delete(key);
        }
        return ret;
    }
    /**
     * 修改指定信息
     */
    @Override
    public int updateStudent(Students students) {
        int ret = studentMapper.updateStudent(students);

        // 缓存存在,删除缓存
        String key = "students_" + students.getSid();
        boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            redisTemplate.delete(key);
        }
        return ret;
    }
}

修改springboot中redis配置中的修改RedisTemplate 默认的序列化规则,将缓存序列化。
配置config文件
RedisConfig.java类:

package com.szh.springboot_redis.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig{
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(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);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

当缓存不是对象时:
就直接自动注入StringRedisTemplate然后调用属性方法

	@Autowired
    private StringRedisTemplate StringRedisTemplate;//K-V操作字符串
    @Autowired
    private RedisTemplate redisTemplate;//K-V都是对象
    
    StringRedisTemplate.opsForValue();//操作字符串
    StringRedisTemplate.opsForList();//操作集合
	public String test(){
	//给redis中保存数据
        StringRedisTemplate.opsForValue().append("msg","hello");//存入字符串
        StringRedisTemplate.opsForValue().get("msg");//从缓存中获取值
        StringRedisTemplate.opsForList().leftPush("mylist","1");//存入集合
        StringRedisTemplate.opsForList().leftPush("mylist","2");
        //测试保存对象
        //默认如果保存对象,使用jdk序列化机制,序列化后的数据保存到redis中
        //RedisTemplate.opsForValue().set("emp-01",Object);注意要序列化
        /*1、将数据以json的方式保存
        redisTemplate默认的序列化规则;改变默认的序列化规则
         */
        redisTemplate.opsForValue().set("Student",Object);
	}
;