在springboot中兩種方式使用緩存,一種是直接通過 RedisTemplate 來使用,另一種是使用 Spring Cache 集成 Redis(也就是註解的方式)。
RedisTemplate 方式不作說明,詳細說明實現一下註解方式。
核心三個註解:
-
@Cachable
-
@CachePut
-
@CacheEvict
1.@Cachable
根據方法的請求參數對其結果進行緩存:
-
Key:緩存的 Key,可以爲空,如果指定要按照 SPEL 表達式編寫,如果不指定,則按照方法的所有參數進行組合。
-
Value:緩存的名稱。
-
Condition:緩存的條件,可以爲空,使用 SPEL 編寫,返回 true 或者 false,只有爲 true 才進行緩存。
寫法:
@Cacheable(value = "user", key = "#id",condition="#id>1")
public User get(Integer id) {
對應關係:
針對這一句話進行一次比較:根據方法的請求參數對其結果進行緩存。
@Cacheable(value = "user", key = "#id",condition="#id>1")
@Override
public User get(Integer id) {
logger.info("進入get方法,當前獲取對象:{}", userDao.selectById(id)==null?null:userDao.selectById(id).toString());
return userDao.selectById(id);
}
@Cacheable(value = "test", key = "#id",condition="#id>1")
@Override
public String getString(Integer id) {
logger.info("進入get方法,當前獲取對象:{}", userDao.selectById(id)==null?null:userDao.selectById(id).toString());
return userDao.selectById(id).getUsername();
}
一個方法返回的是對象,一個方法返回的是字符串。
redis中存儲結果:一個存的是字符串,一個存的是對象。(沒有進行反序列化處理,大致能看出來不同就行了)
2.@CachePut
根據方法的請求參數對其結果進行緩存:
-
Key:緩存的 Key,可以爲空,如果指定要按照 SPEL 表達式編寫,如果不指定,則按照方法的所有參數進行組合。
-
Value:緩存的名稱。
-
Condition:緩存的條件,可以爲空,使用 SPEL 編寫,返回 true 或者 false,只有爲 true 才進行緩存。
和@Cachable不同的是,@CachePut這個註解可以確保方法被執行,同時方法的返回值也被記錄到緩存中。
@Cacheable當重複使用相同參數調用方法的時候,方法本身不會被調用執行,即方法本身被略過了,取而代之的是方法的結果直接從緩存中找到並返回了。
3.@CacheEvict
根據條件對緩存進行清空:
-
Key:緩存的 Key,可以爲空,如果指定要按照 SPEL 表達式編寫,如果不指定,則按照方法的所有參數進行組合。
-
Value:緩存的名稱。
-
Condition:緩存的條件,可以爲空,使用 SPEL 編寫,返回 true 或者 false,只有爲 true 才進行緩存。
-
allEntries:是否清空所有緩存內容,缺省爲 false,如果指定爲 true,則方法調用後將立即清空所有緩存。
-
beforeInvocation:是否在方法執行前就清空,缺省爲 false,如果指定爲 true,則在方法還沒有執行的時候就清空緩存。缺省情況下,如果方法執行拋出異常,則不會清空緩存。
理論知識結束,實踐一下:
maven依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
user實體類:這裏必須要序列化,不然進行緩存時會出錯。
public class User implements Serializable {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
service和dao跳過,直接貼impl代碼:註解使用都在這裏面
@Service
public class RedisServiceImpl implements IRedisService {
public static Logger logger = LogManager.getLogger(RedisServiceImpl.class);
@Autowired
private UserDao userDao;
@CachePut(value ="user", key = "#user.id")
@Override
public User save(User user) {
userDao.insert(user);
logger.info("進入save方法,當前存儲對象:{}", user.toString());
return user;
}
@CacheEvict(value="user", key = "#id")
@Override
public void delete(int id) {
userDao.deleteById(id);
logger.info("進入delete方法,刪除成功");
}
@Cacheable(value = "user", key = "#id",condition="#id>1")
@Override
public User get(Integer id) {
logger.info("進入get方法,當前獲取對象:{}", userDao.selectById(id)==null?null:userDao.selectById(id).toString());
return userDao.selectById(id);
}
@Cacheable(value = "test", key = "#id",condition="#id>1")
@Override
public String getString(Integer id) {
logger.info("進入get方法,當前獲取對象:{}", userDao.selectById(id)==null?null:userDao.selectById(id).toString());
return userDao.selectById(id).getUsername();
}
}
最後是controller:使用的mp,不是重點,隨便造點數據即可。
@RestController
@RequestMapping("redis")
public class RedisController {
public static Logger logger = LogManager.getLogger(RedisController.class);
@Autowired
private IRedisService redisService;
@GetMapping("/add")
public void add() {
User user = new User();
user.setId(3);
user.setUsername("abc");
user.setPassword("abc");
redisService.save(user);
logger.info("添加的用戶信息:{}", user.toString());
}
@GetMapping("/delete")
public void delete() {
redisService.delete(3);
}
@GetMapping("/get/{id}")
public void get(@PathVariable("id") String idStr) throws Exception {
if (StringUtils.isBlank(idStr)) {
throw new Exception("id爲空");
}
Integer id = Integer.parseInt(idStr);
User user = redisService.get(id);
logger.info("獲取的用戶信息:{}", user.toString());
}
@GetMapping("/getString/{id}")
public void getString(@PathVariable("id") String idStr) throws Exception {
if (StringUtils.isBlank(idStr)) {
throw new Exception("id爲空");
}
Integer id = Integer.parseInt(idStr);
redisService.getString(id);
}
}
啓動類上必須要開啓註解:
@SpringBootApplication
@EnableCaching
public class ChuanApplication {
public static void main(String[] args) {
SpringApplication.run(ChuanApplication.class, args);
}
}
完成,進行接口測試。