SpringBoot 2.1.x整合Cache缓存技术相关示例

JSR107规范简述

  • Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry 和 Expiry
    • Caching Provider定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可以在运行期访问多个CachingProvider。
    • CacheManager定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有。
    • Cache是一个类似Map的数据结构并临时存储以Key为索引的值。一个Cache仅被一个CacheManager所拥有。
    • Entry是一个存储在Cache中的key-value对。
    • Expiry 每一个存储在Cache中的条目有一个定义的有效期。一旦超过这个时间,条目为过期的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置
      SpringBoot 2.1.x整合Cache缓存技术相关示例_第1张图片

Spring缓存抽象

  • Spring从3.1开始定义了org.springframework.cache.Cache
    和org.springframework.cache.CacheManager接口来统一不同的缓存技术、
    并支持使用JCache(JSR-107)注解简化我们开发。
  • Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;
  • Cache接口下Spring提供了各种xxxCache的实现;如RedisCache,EhCacheCache , ConcurrentMapCache等;
  • 每次调用需要缓存功能的方法时,Spring会检查检查指定参数的指定的目标方法是否已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。
  • 使用Spring缓存抽象时我们需要关注点
    • ①确定方法需要被缓存以及他们的缓存策略
    • ②从缓存中读取之前缓存存储的数据

Cache相关重要概念&缓存注解

注解 描述
Cache 缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、ConcurrentMapCache等
CacheManager 缓存管理器,管理各种缓存(Cache)组件
@Cacheable 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
@CacheEvict 清空缓存
@CachePut 保证方法被调用,又希望结果被缓存。
@EnableCaching 开启基于注解的缓存
keyGenerator 缓存数据时key生成策略
serialize 缓存数据时value序列化策略

@Cacheable/@CachePut/@CacheEvict 主要的参数

参数 描述 例子
value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 @Cacheable(value={”cache1”,”cache2”}
key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 @Cacheable(value=”testcache”,key=”#userName”)
condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存/清除缓存,在调用方法之前之后都能判断 @Cacheable(value=”testcache”,condition=”#userName.length()>2”)
allEntries(@CacheEvict ) 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 @CachEvict(value=”testcache”,allEntries=true)
beforeInvocation(@CacheEvict) 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存 @CachEvict(value=”testcache”,beforeInvocation=true)
unless(@CachePut/@Cacheable) 用于否决缓存的,不像condition,该表达式只在方法执行之后判断,此时可以拿到返回值result进行判断。条件为true不会缓存,fasle才缓存 @Cacheable(value=”testcache”,unless=”#result == null”)

Spring Cache代码相关

  • pom.xml
<dependencies>

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-cacheartifactId>
dependency>
<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
dependency>
dependencies>
  • 主启动类标注@EnableCaching

  • User.java

package com.hf.cache.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * @Copyright (C), 2016-2019 hf
 * @FileName: User
 * @Author: hf
 * @Date: 2019/9/29 0:53
 * @Description: User 实体
 */
@Getter
@Setter
@Accessors(chain = true)
@AllArgsConstructor
@ToString
public class User implements Serializable {

    //id
    private String id;

    //用户名
    private String name;

    //手机号
    private String phone;

    //邮箱
    private String email;

    //状态
    private boolean status;
}

  • UserService.java
package com.hf.cache.service;

import com.hf.cache.entity.User;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Copyright (C), 2016-2019 hf
 * @FileName: UserService
 * @Author: hf
 * @Date: 2019/9/29 0:57
 * @Description: 用户服务实现层
 */
@Service
public class UserService {

    static Map<String, User> map = new HashMap<>(12);
    static {
        map.put("liuyi", new User(UUID.randomUUID().toString().substring(0,7), "liuyi", "155********", "[email protected]", true));
        map.put("chenger", new User(UUID.randomUUID().toString().substring(0,7), "chenger", "166********", "[email protected]", true));
        map.put("zhangsan", new User(UUID.randomUUID().toString().substring(0,7), "zhangsan", "165********", "[email protected]", true));
        map.put("lisi", new User(UUID.randomUUID().toString().substring(0,7), "lisi", "178********", "[email protected]", true));
        map.put("wangwu", new User(UUID.randomUUID().toString().substring(0,7), "wangwu", "182********", "[email protected]", true));
    }


    /**
     * 功能描述:
     *  查询用户实体并缓存
     * 〈
     *  相关参数说明:
     *   cacheNames/value:指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;
     *
     *   key:缓存数据使用的key;可以用它来指定。默认是使用方法参数的值  1-方法的返回值
     *           编写SpEL; #i d;参数id的值   #a0  #p0  #root.args[0]
     *           getEmp[2]
     *
     *   keyGenerator:key的生成器;可以自己指定key的生成器的组件id
     *           key/keyGenerator:二选一使用;
     *
     *
     *   cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器
     *
     *   condition:指定符合条件的情况下才缓存;
     *           ,condition = "#id>0"
     *       condition = "#a0>1":第一个参数的值》1的时候才进行缓存
     *
     *   unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断
     *           unless = "#result == null"
     *           unless = "#a0==2":如果第一个参数的值是2,结果不缓存;
     *   sync:是否使用异步模式
     *
     * 〉
     *
     * @className: UserService
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/29 1:10
     * @param: [key]
     * @return: com.hf.cache.entity.User
     *
     */
    @Cacheable(value = {"user"},key = "#key",unless = "#result==null")
    public User getUser(String key) {
        System.out.println("查询key=【" + key + "】的用户");
        return map.get(key);
    }

    /**
     * 功能描述:
     * 〈
     *  更新用户信息
     *  @CachePut:既调用方法,又更新缓存数据;同步更新缓存
     * 〉
     *
     * @className: UserService
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/29 1:15
     * @param: [user]
     * @return: com.hf.cache.entity.User
     *
     */
    @CachePut(value = {"user"},key = "#result.name")
    public User updateUser(User user) {
        map.put(user.getName(), user);
        return user;
    }

    /**
     * 功能描述:
     * 〈
     * 删除用户
     * @CacheEvict:缓存清除
     *
     * key:指定要清除的数据
     * allEntries = true:指定清除这个缓存中所有的数据
     * beforeInvocation = false:缓存的清除是否在方法之前执行
     *     默认代表缓存清除操作是在方法执行之后执行;如果出现异常缓存就不会清除
     * beforeInvocation = true:
     *     代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除
     *
     * 〉
     *
     * @className: UserService
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/29 1:20
     * @param: [key]
     * @return: void
     *
     */
    @CacheEvict(value = {"user"},beforeInvocation = true)
    public void deleteUser(String key) {
        map.remove(key);

    }

    /**
     * 功能描述:
     * 〈
     * @Caching 定义复杂的缓存规则
     * 〉
     *
     * @className: UserService
     * @author: hf
     * @version: 1.0.0
     * @date: 2019/9/29 1:25
     * @param: [key]
     * @return: com.hf.cache.entity.User
     *
     */
    @Caching(
            cacheable = {
                    @Cacheable(value = "user",key="#key+1")
            },
            put = {
                    @CachePut(value = "user",key = "#result.id")
            }
    )
    public User getUserByKey(String key) {

        return map.get(key);
    }


}

  • UserController.java
package com.hf.cache.controller;

import com.hf.cache.entity.User;
import com.hf.cache.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

/**
 * @Copyright (C), 2016-2019 hf
 * @FileName: UserController
 * @Author: hf
 * @Date: 2019/9/29 1:32
 * @Description:
 */
@RestController
public class UserController {

    @Autowired
    UserService userService;

    @GetMapping("/get/{key}")
    public User get(@PathVariable String key) {

        return userService.getUser(key);
    }

    @GetMapping("/del/{key}")
    public String del(@PathVariable String key) {

        userService.deleteUser(key);
        return "Success";
    }

    @GetMapping("/upd/{key}")
    public User upd(@PathVariable String key) {
        User user = new User(UUID.randomUUID().toString(), key, "120000", "[email protected]", true);
        return userService.updateUser(user);
    }
}

你可能感兴趣的:(SpringBoot)