Springboot——Redis的使用

在当今的软件开发领域,缓存技术是提升应用性能的关键手段之一。Redis 作为一款高性能的键值对存储数据库,凭借其出色的读写速度和丰富的数据结构,在缓存场景中得到了广泛应用。Spring Boot 作为一款简化 Spring 应用开发的框架,与 Redis 的集成可以让开发者轻松地在项目中使用 Redis 缓存。本文将详细介绍如何在 Spring Boot 项目中集成和使用 Redis。

项目搭建

首先在你的项目中引入redis的Maven依赖确保使用

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

在 application.properties 或 application.yml 中配置 Redis 连接信息。以下是 application.yml 的示例配置:

spring: 
   redis:
      database: 0           # Redis服务器数据库
      host: 127.0.0.1       # Redis服务器地址
      port: 6379            # Redis服务器连接端口
      password: 123456      # Redis服务器连接密码(默认为空)
      timeout: 6000         # Redis连接超时时间(毫秒)

Redis 基本操作

配置Redis的配置类

package com.lppaa.redisdemo.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.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
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.core.StringRedisTemplate;
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;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory){
        RedisSerializer<String> keyRedisSerializer = new StringRedisSerializer(); // redis的key序列化方式
        Jackson2JsonRedisSerializer valueRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); // redis的value的序列化

        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        valueRedisSerializer.setObjectMapper(om);

        //配置序列化(解决乱码的问题)
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ZERO) // 默认生存时间
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keyRedisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueRedisSerializer))
                .disableCachingNullValues();

        //缓存配置map
        Map<String,RedisCacheConfiguration> cacheConfigurationMap=new HashMap<>();
        //自定义缓存名,后面使用的@Cacheable的CacheName
        cacheConfigurationMap.put("myRedis",config);
//        cacheConfigurationMap.put("default",config);

        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .withInitialCacheConfigurations(cacheConfigurationMap)
                .build();

        return cacheManager;
    }


    @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;
    }

}
  • CacheManager方法:负责管理缓存的创建、获取和清理等操作。此方法对 Redis 缓存管理器进行了配置,具体步骤如下:
    • 序列化配置
      • 对 Redis 的键使用 StringRedisSerializer 进行序列化。
      • 对 Redis 的值使用 Jackson2JsonRedisSerializer 进行序列化,同时配置 ObjectMapper 以避免查询缓存时出现转换异常。
    • 缓存配置
      • 借助 RedisCacheConfiguration 配置默认的缓存策略,包含默认生存时间、键和值的序列化方式,并且禁止缓存空值。
      • 创建一个 Map 来存放自定义的缓存配置,这里定义了一个名为 "myRedis" 的缓存。
    • 缓存管理器构建
      • 利用 RedisCacheManager.builder 构建缓存管理器,设置默认缓存配置以及自定义的缓存配置。
  • redisTemplate方法:作用是在代码里对 Redis 进行操作

    • 采用 StringRedisTemplate 作为基础模板,它是 RedisTemplate 的子类,专门用于处理字符串类型的键和值。
    • 同样使用 Jackson2JsonRedisSerializer 对值进行序列化,并且配置 ObjectMapper 以防止查询缓存时出现转换异常。

编写服务层逻辑

EmployeeService接口类
public interface EmployeeService {

    List<Employee> findAll();

    Employee findById(Integer id);

    Employee update(Employee employee);

    Integer delete(Integer id);

}

EmployeeServiceImpl接口实现类

package com.lppaa.redisdemo.service.serviceImpl;

import com.lppaa.redisdemo.dao.EmployeeDao;
import com.lppaa.redisdemo.entity.Employee;
import com.lppaa.redisdemo.service.EmployeeService;
import io.swagger.models.auth.In;
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.stereotype.Service;

import java.util.Collections;
import java.util.Date;
import java.util.List;

@Service
public class EmployeeServiceImpl implements EmployeeService {
    @Autowired
    EmployeeDao employeeDao;

    @Override
    public List<Employee> findAll() {
        return employeeDao.findAll();
    }

    @Override
    @Cacheable(cacheNames = "myRedis" ,key = "T(com.lppaa.redisdemo.utils.MD5Utils).md5('EmployeeService_findById' + #id)" ,unless = "#result==null")
    public Employee findById(Integer id) {
        System.out.println("进入方法,去数据库查询");
        return employeeDao.findById(id);
    }

    @Override
    @CachePut(cacheNames = "myRedis", key = "T(com.lppaa.redisdemo.utils.MD5Utils).md5('EmployeeService_findById' + #employee.id)",condition = "#result != null")
    public Employee update(Employee employee) {
        employee.setTime(new Date());
        Integer ans = employeeDao.update(employee);
        if(ans>0)
            return employeeDao.findById(employee.getId());
        return null;//表示更新失败 结果为空 不存入缓存 结果不变
    }

    @Override
    @CacheEvict(cacheNames = "myRedis", key = "T(com.lppaa.redisdemo.utils.MD5Utils).md5('EmployeeService_findById' + #id)")
    public Integer delete(Integer id) {
        Integer s = employeeDao.delete(id);
        return s;
    }
}
@Cacheable 注解 
  • @Cacheable 注解:用于标记该方法的结果可以被缓存。
    • cacheNames = "myRedis":指定使用名为 myRedis 的缓存,这个缓存名称在 RedisConfig 类中配置。
    • key = "T(com.lppaa.redisdemo.utils.MD5Utils).md5('EmployeeService_findById' + #id)":使用 SpEL(Spring Expression Language)表达式生成缓存的键。这里调用 MD5Utils 类的 md5 方法对 "EmployeeService_findById" 和传入的 id 拼接后的字符串进行 MD5 加密,确保每个不同的 id 对应一个唯一的缓存键。
    • unless = "#result==null":表示如果方法的返回结果为 null,则不将结果存入缓存。
  • 当调用该方法时,Spring 会先检查缓存中是否存在对应的键,如果存在则直接返回缓存中的结果,否则执行方法体中的代码,从数据库中查询数据,并将结果存入缓存。
@CachePut 注解
  • @CachePut 注解:用于更新缓存。无论缓存中是否存在对应的键,都会执行方法体中的代码,并将方法的返回结果存入缓存。
    • cacheNames = "myRedis":指定使用名为 myRedis 的缓存。
    • key = "T(com.lppaa.redisdemo.utils.MD5Utils).md5('EmployeeService_findById' + #employee.id)":生成缓存的键,与 findById 方法使用相同的键生成策略。
    • condition = "#result != null":表示只有当方法的返回结果不为 null 时,才将结果存入缓存。
  • 该方法首先更新员工的时间戳,然后调用 EmployeeDao 的 update 方法更新数据库中的员工信息。如果更新成功,则再次查询数据库获取最新的员工信息并返回,同时更新缓存;如果更新失败,则返回 null,不更新缓存。
CacheEvict 注解
  • @CacheEvict 注解:用于从缓存中移除指定键的缓存项。
    • cacheNames = "myRedis":指定使用名为 myRedis 的缓存。
    • key = "T(com.lppaa.redisdemo.utils.MD5Utils).md5('EmployeeService_findById' + #id)":生成要移除的缓存键,与 findById 和 update 方法使用相同的键生成策略。
  • 该方法调用 EmployeeDao 的 delete 方法从数据库中删除指定 id 的员工信息,并从缓存中移除对应的缓存项。

编写控制层逻辑

package com.lppaa.redisdemo.controller;

import com.alibaba.fastjson.JSON;
import com.lppaa.redisdemo.entity.Employee;
import com.lppaa.redisdemo.entity.User;
import com.lppaa.redisdemo.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@RestController
@RequestMapping("/test")
public class RedisController {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RequestMapping("/aaa")
    public String testA(){
        User user = new User();
        user.setName("李四");
        user.setAge(20);
//        redisTemplate.opsForValue().set("user", JSON.toJSONString(user));
        //redisTemplate.opsForValue().set("ttt", user);
        stringRedisTemplate.opsForValue().set("qweirj", JSON.toJSONString(user));
        return "success";
    }

    @RequestMapping("/findbyid")
    @ResponseBody
    public Employee findbyId(Integer id){
        Employee employee = employeeService.findById(id);
        return employee;
    }

    @RequestMapping("/update")
    @ResponseBody
    public String update(Employee e){
        e.setTime(new Date());
        Employee byId = employeeService.update(e);
        if(byId != null)
            return "success";
        return "false";
    }

    @RequestMapping("/delete")
    @ResponseBody
    public String dete(Integer id){
        Integer s = employeeService.delete(id);
        if(s == 1)
            return "success";
        return "false";

    }
}

最后打开Redis即可进行使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值