上篇文章 系列九、SpringBoot + MyBatis + Redis实现分布式缓存 介绍了基于xml方式实现分布式缓存的效果,当前大家使用的技术栈基本是springboot+各种框架的组合,而springboot显著的一个特点就是去xml配置,那么在无xml配置的情形下,又该如何实现分布式缓存呢?请看下面的代码实战
基于注解方式的分布式缓存,主要涉及到如下几个注解:
(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...)
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
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
/**
* @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);
}
}
/**
* @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
/**
* @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;
}
/**
* @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);
}
update department set department_name = #{departmentName} where id = #{id}
select id,department_name from department where id = #{id}
delete from department where id = #{id}
/**
* @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);
}
}
/**
* @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);
}
}