系列十、SpringBoot + MyBatis + Redis实现分布式缓存(基于注解方式)

一、概述

        上篇文章 系列九、SpringBoot + MyBatis + Redis实现分布式缓存 介绍了基于xml方式实现分布式缓存的效果,当前大家使用的技术栈基本是springboot+各种框架的组合,而springboot显著的一个特点就是去xml配置,那么在无xml配置的情形下,又该如何实现分布式缓存呢?请看下面的代码实战

二、代码实战

2.1、分布式缓存相关的注解

        基于注解方式的分布式缓存,主要涉及到如下几个注解:

        (1)@EnableCaching:一般标注在配置类上,表示开启Spring的缓存,如果不加此注解的话Spring自带的缓存将不生效;

        (2)@CacheConfig(cacheNames = "xxx"):一般标注在service类上,用于配置cache的名字,建议以当前service类的全路径名作为cache的名字;

        (3)@Cacheable:一般标识在service层的查询方法上,表示将一个方法的返回值缓存起来,  默认情况下,缓存的key就是方法的参数,缓存的value就是方法的返回值,如果查询 方法无参数,则会使用默认的key,即SimpleKey [];

        (4)@CachePut(key = "#department.id"):一般加在service层的更新方法上(update),当数据库中的数据更新后,缓存中的数据也要跟着更新,使用此注解,可以将方法的返回值 自动更新到已经存在的key上

        (5)@CacheEvict:一般加在service层的删除方法上,当数据库中的数据删除后,相关的缓存也会被删除,使用该注解的时候,也可以配置按照某种条件删除(某种条件:@CacheEvict注解中的条件,例如:value、cacheNames、key、keyGenerator...)

2.2、项目概览

系列十、SpringBoot + MyBatis + Redis实现分布式缓存(基于注解方式)_第1张图片

2.3、pom


	
	
		org.springframework.boot
		spring-boot-starter-web
	
	
		org.springframework.boot
		spring-boot-starter-test
		test
	
	
		org.springframework.boot
		spring-boot-devtools
	

	
	
		mysql
		mysql-connector-java
		8.0.26
	
	
		org.mybatis.spring.boot
		mybatis-spring-boot-starter
		2.3.1
	
	
		com.alibaba
		druid-spring-boot-starter
		1.1.10
	
	
		org.springframework.boot
		spring-boot-starter-data-redis
	

	
	
		org.projectlombok
		lombok
		1.18.30
	
	
		cn.hutool
		hutool-all
		5.8.21
	
	
		org.apache.commons
		commons-lang3
	
	
		org.apache.commons
		commons-collections4
		4.4
	
	
		com.alibaba.fastjson2
		fastjson2
		2.0.25
	

2.4、yml

server:
  port: 9999

spring:
  redis:
    host: 
    port: 6379
    database: 0
    password: 123456

  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/20231018_redis?useSSL=false&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT
    username: root
    password: 123456

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: org.stat.entity.model
  configuration:
    map-underscore-to-camel-case: true

logging:
  level:
    org:
      star:
        mapper: debug

2.5、主启动

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/12/10 12:44
 * @Description:
 *
 */
@MapperScan(basePackages = "org.star.mapper")
@SpringBootApplication
public class SpringbootRedisDistributeCacheAnnotationApplication {

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


}

2.6、MyRedisConfig

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/12/10 15:28
 * @Description:
 * @EnableCaching的作用:开启Spring的缓存,如果不加此注解的话Spring自带的缓存将不生效
 *
 */
@EnableCaching
@Configuration
public class MyRedisConfig {

    /**
     * RedisTemplate k v 序列化
     *
     * @param connectionFactory
     * @return
     */
    @Bean
    public RedisTemplate redisTemplate(LettuceConnectionFactory connectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);

        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                // 设置默认的超时时间为2小时
                .entryTtl(Duration.ofHours(2))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()))
                // 设置默认的缓存前缀
                .prefixCacheNameWith("REDIS_CACHE_");
        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }

}

2.7、DepartmentDO

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/12/10 12:48
 * @Description:
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ToString(callSuper = true)
public class DepartmentDO implements Serializable {
    /**
     * 编号
     */
    private Integer id;

    /**
     * 部门名称
     */
    private String departmentName;

}

2.8、DepartmentMapper.java

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/12/10 12:50
 * @Description:
 */
public interface DepartmentMapper {

    /**
     * 查询所有部门
     * @return
     */
    List listAllDepartment();

    /**
     * 根据id查询部门信息
     * @param id
     * @return
     */
    DepartmentDO getDepartmentById(Integer id);

    /**
     * 根据id和departmentName查询部门
     * @param id
     * @param departmentName
     * @return
     */
    DepartmentDO getDepartment(Integer id,String departmentName);

    /**
     * 更新Department
     * @param department
     * @return
     */
    int updateDepartment(DepartmentDO department);

    /**
     * 删除部门
     * @param id
     */
    void deleteDepartment(Integer id);
}

2.9、DepartmentMapper.xml





    

    

    

    
        update department set department_name = #{departmentName} where id = #{id}
        
            select id,department_name from department where id = #{id}
        
    

    
        delete from department where id = #{id}
    

2.10、DepartmentService

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/12/10 20:00
 * @Description:
 * 基于注解的分布式缓存,redis中key的生成规则:${prefixCacheNameWith} + "_" + ${cacheNames} + "_" + ${key}
 *      说明:prefixCacheNameWith为RedisCacheManager中配置的前缀
 *      举例:
 *          (1)listAllDepartment ===> REDIS_CACHE_org.star.service.DepartmentService::SimpleKey []
 *          (2)getDepartmentById ===> REDIS_CACHE_org.star.service.DepartmentService::1
 *          (3)getDepartment ===> REDIS_CACHE_org.star.service.DepartmentService::SimpleKey [1,研发部]
 *
 */
@Service
@CacheConfig(cacheNames = "org.star.service.DepartmentService")
public class DepartmentService {

    @Resource
    private DepartmentMapper departmentMapper;

    /**
     * @return
     * @Cacheable的作用:
     *      @Cacheable注解一般加在查询方法上,表示将一个方法的返回值缓存起来,
     * 默认情况下,缓存的key就是方法的参数,缓存的value就是方法的返回值,如果查询
     * 方法无参数,则会使用默认的key,即SimpleKey []
     */
    @Cacheable
    public List listAllDepartment() {
        List departments = departmentMapper.listAllDepartment();

        return departments;
    }

    /**
     * 对于只有一个参数的查询方法,其key位id对应的值
     * @param id
     * @return
     */
    @Cacheable
    public DepartmentDO getDepartmentById(Integer id) {
        return departmentMapper.getDepartmentById(id);
    }

    /**
     *
     * 对于有多个参数的查询方法,其key为所有的参数,如果想修改,可以单独指定,例如:@Cacheable(key = "#id")
     * @param id
     * @param departmentName
     * @return
     */
    @Cacheable
    public DepartmentDO getDepartment(Integer id,String departmentName) {
        return departmentMapper.getDepartment(id,departmentName);
    }

    /**
     * @CachePut作用:
     *      @CachePut注解一般加在更新方法上(update),当数据库中的数据更新后,缓存中的数据也要跟着更新,使用此注解,可以将方法的返回值
     *      自动更新到已经存在的key上,示例如下:
     * @param department
     * @return
     */
    @CachePut(key = "#department.id")
    public DepartmentDO updateDepartment(DepartmentDO department) {
        departmentMapper.updateDepartment(department);
        return department;
    }

    /**
     * @CacheEvict()作用:
     *      @CacheEvict()注解一般加在删除方法上,当数据库中的数据删除后,相关的缓存也会被删除,使用该注解的时候,也可以配置按照某种条件
     *      删除(某种条件:@CacheEvict注解中的条件,例如:value、cacheNames、key、keyGenerator...)
     * @param id
     */
    @CacheEvict
    public void deleteDepartment(Integer id) {
        departmentMapper.deleteDepartment(id);
    }

}

2.11、DepartmentServiceTest

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/12/10 20:07
 * @Description:
 */
@SpringBootTest
public class DepartmentServiceTest {

    @Resource
    private DepartmentService departmentService;

    @Test
    public void listAllDepartmentTest() {
        List departments1 = departmentService.listAllDepartment();
        System.out.println("departments1 = " + departments1);

        System.out.println("=============================");

        List departments2 = departmentService.listAllDepartment();
        System.out.println("departments2 = " + departments2);
    }

    @Test
    public void getDepartmentByIdTest() {
        DepartmentDO department1 = departmentService.getDepartmentById(1);
        System.out.println("department1 = " + department1);

        System.out.println("========================");
        DepartmentDO department2 = departmentService.getDepartmentById(1);
        System.out.println("department2 = " + department2);
    }

    @Test
    public void getDepartmentTest() {
        DepartmentDO department1 = departmentService.getDepartment(1, "研发部");
        System.out.println("department1 = " + department1);

        System.out.println("============================");

        DepartmentDO department2 = departmentService.getDepartment(1, "研发部");
        System.out.println("department2 = " + department2);
    }

    @Test
    public void updateDepartmentTest() {
        DepartmentDO department = new DepartmentDO().setDepartmentName("研发部444").setId(1);
        DepartmentDO updatedDepartment = departmentService.updateDepartment(department);
        System.out.println("updatedDepartment = " + updatedDepartment);
    }

    @Test
    public void deleteDepartmentTest() {
        departmentService.deleteDepartment(1);
    }

}

2.12、测试

2.12.1、listAllDepartmentTest

系列十、SpringBoot + MyBatis + Redis实现分布式缓存(基于注解方式)_第2张图片

系列十、SpringBoot + MyBatis + Redis实现分布式缓存(基于注解方式)_第3张图片

2.12.2、 getDepartmentByIdTest

系列十、SpringBoot + MyBatis + Redis实现分布式缓存(基于注解方式)_第4张图片

2.12.3、getDepartmentTest

2.12.4、 updateDepartmentTest

2.12.5、 deleteDepartmentTest

你可能感兴趣的:(SpringBoot系列,spring,boot,mybatis,缓存)