在當今的軟件開發領域,緩存技術是提升應用性能的關鍵手段之一。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 {@Beanpublic 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();//緩存配置mapMap<String,RedisCacheConfiguration> cacheConfigurationMap=new HashMap<>();//自定義緩存名,后面使用的@Cacheable的CacheNamecacheConfigurationMap.put("myRedis",config);
// cacheConfigurationMap.put("default",config);RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).withInitialCacheConfigurations(cacheConfigurationMap).build();return cacheManager;}@Beanpublic 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
?以避免查詢緩存時出現轉換異常。
- 對 Redis 的鍵使用?
- 緩存配置:
- 借助?
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 {@AutowiredEmployeeDao employeeDao;@Overridepublic 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 {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate EmployeeService employeeService;@Autowiredprivate 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")@ResponseBodypublic Employee findbyId(Integer id){Employee employee = employeeService.findById(id);return employee;}@RequestMapping("/update")@ResponseBodypublic String update(Employee e){e.setTime(new Date());Employee byId = employeeService.update(e);if(byId != null)return "success";return "false";}@RequestMapping("/delete")@ResponseBodypublic String dete(Integer id){Integer s = employeeService.delete(id);if(s == 1)return "success";return "false";}
}
最后打開Redis即可進行使用。