SpringBoot 整合Redis 实战篇

一、解决数据乱码问题

在上篇文章中我们整合了redis,当我们存入一个对象时会发现redis中的数据存在乱码问题,这是jdk编码的问题
在这里插入图片描述

springboot整合redis时提供了两个模板工具类,StringRedisTemplate和RedisTemplate.

1.使用RedisTemplate时需要为key和value设置序列化

SpringBoot 整合Redis 实战篇_第1张图片

package com.lzq.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
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String ,Object> template = new RedisTemplate<>();
        StringRedisSerializer redisSerializer = new StringRedisSerializer();
        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.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(redisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化  filed value
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.setKeySerializer(redisSerializer);
        return template;
    }
}

2.测试

SpringBoot 整合Redis 实战篇_第2张图片
SpringBoot 整合Redis 实战篇_第3张图片

当我们配置好序列化文件之后就不需要转换类型或者在进行序列化操作,直接可以向redis中填入对象类型也不存在编码问题,方便了我们的编码操作

package com.lzq;


import com.lzq.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@SpringBootTest
class RedisSpringbootApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void contextLoads() {
        //对key进行序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //对value进行序列化
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("k1","v1");//存储的都是字符串类型,看到存放的数据乱码---对key进行序列化时采用的是默认的JDK序列化方式。要对应的类必须实现序列接口
        System.out.println(valueOperations.get("k1"));

        valueOperations.set("k31",new User("张三",28));
        Object user = valueOperations.get("k3");
        System.out.println(user);
    }

    @Test
    public void test03(){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("k22","v22");
        valueOperations.set("k23",new User("阿娇",18));
    }

}

二、 springboot使用redis集群模式

1.更改配置文件

在这里插入图片描述

2.打开redis集群模式

SpringBoot 整合Redis 实战篇_第4张图片
在这里插入图片描述

3.测试连接

SpringBoot 整合Redis 实战篇_第5张图片

  @Test
    public void test04(){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("kkk","vvv");
        Object kkk = valueOperations.get("kkk");
        System.out.println(kkk);
    }

三、使用redis作为缓存

SpringBoot 整合Redis 实战篇_第6张图片
Redis因为其自身高性能的数据读取能力,因此会经常被应用到缓存的场景中

1.连接数据库配置数据源

SpringBoot 整合Redis 实战篇_第7张图片

#redis?????--??
#spring.redis.host=192.168.179.129
#spring.redis.port=6379
# nginx??redis??
spring.redis.cluster.nodes=192.168.179.129:7001,192.168.179.129:7002,192.168.179.129:7003,192.168.179.129:7004,192.168.179.129:7005,192.168.179.129:7006


spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db2?serverTimezone=Asia/Shanghai&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456

SpringBoot 整合Redis 实战篇_第8张图片

2.实现单表操作的缓存

SpringBoot 整合Redis 实战篇_第9张图片

package com.lzq.service;

import com.lzq.dao.StudentDao;
import com.lzq.pojo.Student;
import javafx.scene.DepthTest;
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.concurrent.TimeUnit;

@Service
public class StudentService {
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private RedisTemplate redisTemplate;

    //查询操作
    public Student findByid(Integer id){
        //创建redis操作字符串对象
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //查看缓存是否存在该数据  有缓存则不需要对数据库进行操作
        Object o = valueOperations.get("student:" + id);
        //判断产看是否为空  并且为需要的student对象
        if (o!=null && o instanceof Student){
            return (Student) o;
        }
        //查看数据库
        Student student = studentDao.selectById(id);
        if (student!=null){
            //把查出的数据放到缓存中  key  value  过期时间 过期单位
            valueOperations.set("student:"+id,student,30, TimeUnit.HOURS);
        }
        return student;

    }

    //修改操作
    public Student update(Student student){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //先删除数据库中的缓存
        redisTemplate.delete("student:"+student.getSid());
        //再修改数据库中的数据
        studentDao.updateById(student);
        return student;
    }
    //添加操作
    public Student insert(Student student){
        studentDao.insert(student);
        return student;
    }
    //删除操作
    public int delete(int id){
        //先删除缓存数据
        redisTemplate.delete("student:"+id);
        //再对数据库进行操作
        int i = studentDao.deleteById(id);
        return i;
    }


}

思考: AOP—可以把一些非核心业务代码抽象----抽取为一个切面类@Aspect. 在结合一些注解完成相应的切面功能。 Spring框也能想到,Spring在3.0以后提高了缓存注解。可以帮你把功能抽取。

3.使用注解简化缓存操作

1)配置缓存配置

SpringBoot 整合Redis 实战篇_第10张图片

package com.lzq.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
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.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String ,Object> template = new RedisTemplate<>();
        StringRedisSerializer redisSerializer = new StringRedisSerializer();
        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.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(redisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化  filed value
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.setKeySerializer(redisSerializer);
        return template;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        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);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600)) //缓存过期10分钟 ---- 业务需求。
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//设置key的序列化方式
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) //设置value的序列化
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}

2)开启缓存注解

SpringBoot 整合Redis 实战篇_第11张图片

@EnableCaching//开启缓存注解驱动  也可以再配置类中添加

3)使用缓存注解

SpringBoot 整合Redis 实战篇_第12张图片

package com.lzq.service;

import com.lzq.dao.StudentDao;
import com.lzq.pojo.Student;
import javafx.scene.DepthTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class StudentService {
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private RedisTemplate redisTemplate;

    //查询操作
    public Student findByid(Integer id){
        //创建redis操作字符串对象
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //查看缓存是否存在该数据  有缓存则不需要对数据库进行操作
        Object o = valueOperations.get("student:" + id);
        //判断产看是否为空  并且为需要的student对象
        if (o!=null && o instanceof Student){
            return (Student) o;
        }
        //查看数据库
        Student student = studentDao.selectById(id);
        if (student!=null){
            //把查出的数据放到缓存中  key  value  过期时间 过期单位
            valueOperations.set("student:"+id,student,30, TimeUnit.HOURS);
        }
        return student;

    }

    //修改操作
    public Student update(Student student){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //先删除数据库中的缓存
        redisTemplate.delete("student:"+student.getSid());
        //再修改数据库中的数据
        studentDao.updateById(student);
        return student;
    }
    //添加操作
    public Student insert(Student student){
        studentDao.insert(student);
        return student;
    }
    //删除操作
    public int delete(int id){
        //先删除缓存数据
        redisTemplate.delete("student:"+id);
        //再对数据库进行操作
        int i = studentDao.deleteById(id);
        return i;
    }

    //查询操作

    //使用于查询的缓存注解: 缓存的名称叫做: cacheNames::key
    //先从缓存中找名字叫:cacheNames::key 如果存在,则方法不执行。如果不存在会执行方法,并把改方法的返回值作为缓存的值.
    //必须开启缓存注解驱动
    @Cacheable(cacheNames = "dept",key="#id")
    public Student findByid2(Integer id){
        //创建redis操作字符串对象
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //查看缓存是否存在该数据  有缓存则不需要对数据库进行操作
        Object o = valueOperations.get("student:" + id);
        //判断产看是否为空  并且为需要的student对象
        if (o!=null && o instanceof Student){
            return (Student) o;
        }
        //查看数据库
        Student student = studentDao.selectById(id);
        if (student!=null){
            //把查出的数据放到缓存中  key  value  过期时间 过期单位
            valueOperations.set("student:"+id,student,30, TimeUnit.HOURS);
        }
        return student;

    }

    //修改操作

    //先执行方法体,并把方法的返回结果作为缓存的值。修改缓存的值。
    @CachePut(cacheNames = "dept",key="#dept.id")
    public Student update2(Student student){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //先删除数据库中的缓存
        redisTemplate.delete("student:"+student.getSid());
        //再修改数据库中的数据
        studentDao.updateById(student);
        return student;
    }
    //添加操作
    public Student insert2(Student student){
        studentDao.insert(student);
        return student;
    }

    //删除操作

    //删除缓存再执行方法体
    @CacheEvict(cacheNames = "dept",key = "#id")
    public int delete2(int id){
        //先删除缓存数据
        redisTemplate.delete("student:"+id);
        //再对数据库进行操作
        int i = studentDao.deleteById(id);
        return i;
    }
    
}

你可能感兴趣的:(spring,boot,redis,bootstrap)