SpringCache快速入门

文章目录

  • SpringCache缓存框架
    • 简介
    • 使用
      • 加入依赖
      • 配置文件
  • SpringCache常用注解
    • @Cacheable
    • @CachePut
    • @CacheEvict
    • @Caching
    • @CacheConfig
  • SpringBoot+MyBatisPlus+H2+SpringCache+Redis整合使用
    • 依赖引入
    • h2,初始化SQL脚本
    • yml配置
    • 主启动类
    • CacheConfig类
    • KeyGenerator
    • Entity类
    • Mapper
    • Service
    • Controller

SpringCache缓存框架

简介

  • 官方地址https://spring.io/guides/gs/caching/
  • 提供基本的Cache抽象,方便切换各种底层Cache,如Redis,caffeine
  • 提供类似@Transactional注解事务的方式,类实现Cache
  • 提供事务回滚时自动回滚缓存
  • 核心
    • Cache接口,缓存操作的API
    • CacheManager管理各类缓存,有多个缓存框架的实现

使用

加入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>2.5.3</version>
</dependency>

配置文件

选择缓存类型

spring:
  cache:
    type: redis

SpringBoot启动类开启缓存注解

@EnableCaching

SpringCache常用注解

@Cacheable

  • value、cacheNames:两个等同的参数(cacheNames为Spring 4新增,作为value的别名),用于指定缓存存储的集合名。由于Spring 4中新增了@CacheConfig,因此在Spring 3中原本必须有的value属性,也成为非必需项了
  • key:缓存对象存储在Map集合中的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:@Cacheable(key = “#p0”):使用函数第一个参数作为缓存的key值,更多关于SpEL表达式的详细内容可参考官方文档
  • condition:缓存对象的条件,非必需,也需使用SpEL表达式,只有满足表达式条件的内容才会被缓存,比如:@Cacheable(key = “#p0”, condition = “#p0.length() < 3”),表示只有当第一个参数的长度小于3的时候才会被缓存,
  • unless:另外一个缓存条件参数,非必需,需使用SpEL表达式。它不同于condition参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断的,所以它可以通过对result进行判断。
  • keyGenerator:用于指定key生成器,非必需。若需要指定一个自定义的key生成器,我们需要去实现org.springframework.cache.interceptor.KeyGenerator接口,并使用该参数来指定。需要注意的是:该参数与key是互斥的
  • cacheManager:用于指定使用哪个缓存管理器,非必需。只有当有多个时才需要使用
  • cacheResolver:用于指定使用那个缓存解析器,非必需。需通过org.springframework.cache.interceptor.CacheResolver接口来实现自己的缓存解析器,并用该参数指定。

@CachePut

@CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用

@CacheEvict

@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空,主要用作删除

@Caching

有时候我们可能组合多个Cache注解使用;比如用户新增成功后,我们要添加id–>user;username—>user;email—>user的缓存;此时就需要@Caching组合多个注解标签了。

@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.username"),
@CachePut(value = "user", key = "#user.email")
})
public User save(User user) {
}

@CacheConfig

所有的@Cacheable()里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了, 所以,有了@CacheConfig这个配置,@CacheConfig is a class-level annotation that allows to share the cache names,如果你在你的方法写别的名字,那么依然以方法的名字为准。

@CacheConfig是一个类级别的注解

SpringBoot+MyBatisPlus+H2+SpringCache+Redis整合使用

依赖引入

<parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-parentartifactId>
    <version>2.5.3version>
    <relativePath/> 
parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-redisartifactId>
    dependency>

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-cacheartifactId>
        <version>2.5.3version>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>com.baomidougroupId>
        <artifactId>mybatis-plus-boot-starterartifactId>
        <version>3.4.3.4version>
    dependency>
    
    <dependency>
        <groupId>com.h2databasegroupId>
        <artifactId>h2artifactId>
        <scope>runtimescope>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
dependencies>

h3,初始化SQL脚本

data-h2.sql

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');

INSERT INTO user2 (id, name, age) VALUES
(1, 'Jone', 18),
(2, 'Jack', 20),
(3, 'Tom', 28),
(4, 'Sandy', 21),
(5, 'Billie', 24);

schema-h2.sql

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
   id BIGINT(20) NOT NULL COMMENT '主键ID',
   name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
   age INT(11) NULL DEFAULT NULL COMMENT '年龄',
   email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
   PRIMARY KEY (id)
);

CREATE TABLE user2
(
   id BIGINT(20) NOT NULL COMMENT '主键ID',
   name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
   age INT(11) NULL DEFAULT NULL COMMENT '年龄',
   PRIMARY KEY (id)
);

yml配置

spring:
  cache:
    type: redis
    #H2配置
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:test
    username: root
    password: test
    #H2初始化
  sql:
    init:
      #表结构
      schema-locations: classpath:db/schema-h2.sql
      #表数据
      data-locations: classpath:db/data-h2.sql
  redis:
        host: Redis地址
        password: Redis密码
        database: 0

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志

主启动类

@SpringBootApplication
@MapperScan("com.peppa.springcache.mapper")
@ComponentScan("com.peppa")
@EnableCaching
public class SpringCacheTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCacheTestApplication.class, args);
    }

}

CacheConfig类

其中配置了RedisCacheManager

@Configuration
public class CacheConfig {
    @Bean
    @Primary
    public RedisCacheManager cacheManager1Hour(RedisConnectionFactory connectionFactory){
        RedisCacheConfiguration config=instanceConfig(3600L);
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
    }

    @Bean
    public RedisCacheManager cacheManager1Min(RedisConnectionFactory connectionFactory){
        RedisCacheConfiguration config=instanceConfig(60L);
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
    }

    private RedisCacheConfiguration instanceConfig(Long ttl){
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());
        //去掉各种@JsonSerialize的注解的解析
        objectMapper.configure(MapperFeature.USE_ANNOTATIONS,false);
        //只针对非空值进行序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //将类型序列化到属性json字符串中
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(ttl))
                .disableCachingNullValues()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
    }
}

/*
        自定义缓存Key规则
     */
    @Bean
    public KeyGenerator springCacheCustomeKeyGenerator(){
        return new KeyGenerator(){
            @override
            public Object generate(Object o,Method method,Object... objects){
                retrun o.getClass().getSimpleName()+"_"
                        +method.getName()+"_"
                        + StringUtils.arrayToDelimitedString(objects,"_");
            }
        }
    }

KeyGenerator

Entity类

User

@Data
@Builder
//一定要序列化,Redis存储必须序列化实体类
public class User implements Serializable {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

Mapper

@Mapper
public interface UserMapper extends BaseMapper<User> {

}

Service

@Service
public class UserService {
    @Autowired
    UserMapper userMapper;

   @Cacheable(value = {"user"},key = "#root.methodName",cacheManager = "cacheManager1Min")
    public List<User> select(){
        List<User> users = userMapper.selectList(null);
        return users;
    }

    @CachePut(value = {"user"},key = "#root.args[0]")
    public User insert(Long id){
        User user = User.builder().id(id).build();
        int insert = userMapper.insert(user);
        return user;
    }

    @Cacheable(value = {"user"},keyGenerator="springCacheCustomeKeyGenerator")
    public User selectOne(Long id){
        User user = userMapper.selectById(id);
        return user;
    }

    @CacheEvict(value = {"user"},key = "#root.args[0]")
    public int delete(Long id){

        int insert = userMapper.deleteById(id);
        return insert;
    }
}

Controller

你可能感兴趣的:(框架,缓存,redis,java)