版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zxd1435513775/article/details/85091793
一、基本项目搭建
测试项目是基于SpringBoot+Mybatis+Maven;

1、搭建基本环境,具体步骤如下:
(1)、新建数据库,导入数据库文件,创建出department和employee表;

(2)、创建SpringBoot-cache工程,选择具体模块,如下图;

(3)、在pom.xml文件中,加入cache依赖

<!-- https://mvnrepository.com/artifact/javax.cache/cache-api -->
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
<version>1.0.0</version>
</dependency>
1
2
3
4
5
6
(4)、创建JavaBean封装数据,以Employee表为例;

public class Employee {

private Integer id;
private String lastName;
private String email;
private Integer gender; //性别 1男 0女
private Integer dId;

//setter、getter方法略
}
1
2
3
4
5
6
7
8
9
10
(5)、在配置文件中,配置数据库;

//配置项目对外访问路径
server.servlet.context-path=/cache

//配置数据源
spring.datasource.url=jdbc:mysql://192.168.1.106:3307/mybatis
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

//开启驼峰命名
mybatis.configuration.map-underscore-to-camel-case=true

//打开操作数据库的日志
logging.level.com.scorpios.cache.mapper=debug
1
2
3
4
5
6
7
8
9
10
11
12
13
14
(6)、整合Mybatis操作数据;

@Mapper
public interface EmployeeMapper {

//查
@Select("select * from employee where id = #{id}")
public Employee getEmpById(Integer id);

//增
@Insert("insert into employee (lastName,email,gender,did) values ( #{lastName},#{email},#{gender},#{dId})")
public void addEmp(Employee emp);

//删
@Delete("delete from employee where id = #{id}")
public void delEmpById(Integer id);

//改
@Update("update employee set lastName=#{lastName},email=#{email},gender=#{gender},did=#{dId} where id=#{id}")
public void updateEmp(Employee emp);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(7)、配置扫描Mapper包;

@MapperScan("com.scorpios.cache.mapper") //配置扫描mapper包
@SpringBootApplication
public class SpringbootCacheApplication {

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

}
1
2
3
4
5
6
7
8
9
(8)、测试访问:http://localhost:8080/cache/emp/1

多次访问,控制台输出:

二、快速体验Cache使用
1、想要使用Cache缓存,首先了解关于Cache的注解,并需要开启缓存注解:@EnableCaching

开启缓存功能的注解

@EnableCaching //开启缓存注解
@MapperScan("com.scorpios.cache.mapper")
@SpringBootApplication
public class SpringbootCacheApplication {

public static void main(String[] args) {
SpringApplication.run(SpringbootCacheApplication.class, args);
}
}
1
2
3
4
5
6
7
8
9
2、@Cacheable注解使用和说明
编写Service层,调用Dao层,并在Service层,对操作Dao层的数据进行缓存

@Service
public class EmployeeService {

@Autowired
EmployeeMapper employeeMapper;

@Cacheable(cacheNames = "emp",key = "#root.args[0]")
public Employee getEmpById(Integer id){
System.out.println("查询"+id+"号员工");
Employee emp = employeeMapper.getEmpById(id);
System.out.println(emp);
return emp;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
(1)、测试结果
多次发送请求,控制台只显示查询了一次数据库操作,缓存成功。

(2)、@Cacheable参数具体说明
@Cacheable:将方法的运行结果缓存,以后再要相同的数据,直接从缓存中获取,不用调用方法;

cacheNames/value:指定缓存组件的名字,将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;
例如:@Cacheable(cacheNames = {}"emp","dept"},key = "#root.args[0]")

key:可以用它来指定缓存数据使用的key,默认是使用方法参数的值;(也可以指定自己的生成策略)

keyGenerator:key的生成器;可以自己指定key的生成器的组件id;key/keyGenerator:二选一使用;

cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器;

condition:指定符合条件的情况下才缓存;
例如:@Cacheable(cacheNames = {}"emp","dept"},key = "#root.args[0]",condition="#root.args[0]>0")

unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断;

sync:是否使用异步模式;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(3)、指定自己的key生成策略和key的SPEL表达式的说明:

@Cacheable(cacheNames = "emp",keyGenerator = "myKeyGenerator")
public Employee getEmpById(Integer id){
System.out.println("查询"+id+"号员工");
Employee emp = employeeMapper.getEmpById(id);
System.out.println(emp);
return emp;
}
1
2
3
4
5
6
7
自定义自己的key生成策略

@Configuration
public class MyCacheConfig {

@Bean("myKeyGenerator")
public KeyGenerator keyGenerator(){

return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {

return method.getName()+Arrays.asList(params).toString();
}
};

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(4)、@Cacheable运行流程

1、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;
(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。

2、去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;
key是按照某种策略生成的;默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key;
SimpleKeyGenerator生成key的默认策略:
如果没有参数:key=new SimpleKey();
如果有一个参数:key=参数的值
如果有多个参数:key=new SimpleKey(params);

3、没有查到缓存就调用目标方法;

4、将目标方法返回的结果,放进缓存中;
1
2
3
4
5
6
7
8
9
10
11
12
13
3、@CachePut注解使用和说明
作用:在目标方法调用之后,将目标方法的执行结果放入缓存,既调用方法,又更新缓存数据;

(1)、测试代码:

@CachePut(cacheNames = "emp",key = "#result.id")//key需要注意
public Employee updateEmp(Employee employee){
System.out.println("更新的员工信息:"+employee);
employeeMapper.updateEmp(employee);
return employee;
}
1
2
3
4
5
6
7
(2)、测试结果:
发送更新用户信息请求:

控制台输出:

发送查询请求后,控制台并没有任何输出,说明是从缓存中拿的数据:

(3)、重要说明:

@CachePut(cacheNames = "emp",key = "#result.id")//key需要注意
1
如果我们在使用@CachePut注解时,不指定key,这会使用方法的默认参数,这样的话,与@Cacheable注解的key不一致,导致,我们更新过后,再次查询信息时,并不会得到缓存信息。这主要是以为key不一致导致的,需要注意。

4、@CacheEvit注解使用和说明
作用:缓存清除
(1)、测试代码:

@CacheEvict(cacheNames = "emp",key ="#root.args[0]")
public void deleteEmp(Integer id){

//模拟删除
System.out.println("删除数据,员工id为:" +id );

}
1
2
3
4
5
6
7
(2)、测试结果:
第一次查询id为1的员工,控制台打印查询数据库请求,第二次查询则不会去查询数据库;
然后发送删除id为1的员工请求,控制台打印,删除信息;
最后再次发送查询id为1的员工,控制台再次打印查询数据库的SQL。
表明之前的缓存已清除

(3)、@CachePut参数说明:

key:指定要清除的数据;

allEntries=true;指定清除这个缓存中所有的数据;

beforeInvocation=false;缓存的清除是否在方法之前执行
默认代表缓存清除操作是在方法之后执行;如果出现异常缓存就不会清除

beforeInvocation=true:
代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除
1
2
3
4
5
6
7
8
9
4、@Caching注解使用和说明
可以指定多个缓存规则,下面是@Caching的源码

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Caching {

Cacheable[] cacheable() default {};

CachePut[] put() default {};

CacheEvict[] evict() default {};

}
1
2
3
4
5
6
7
8
9
10
11
12
13
示例代码:

@Caching(
cacheable = {
@Cacheable(cacheNames = "emp",key = "#lastName")
},

put = {
@CachePut(cacheNames = "emp",key="#result.id"),
@CachePut(cacheNames = "emp",key="#result.email")
}
)
public Employee getEmpByNames(String lastName){

}
1
2
3
4
5
6
7
8
9
10
11
12
13
4、@CacheConfig注解使用和说明
可以在类上加上次注解,用于指定类级别的公共缓存属性,例如使用公共缓存名字和id的生成策略

@CacheConfig(cacheNames = "emp")
@Service
public class EmployeeService {

}

1
2
3
4
5
6
7
三、SpringBoot整合Redis作为缓存
在我们没有配置使用其他缓存中间件时,SpringBoot默认使用的是ConcurrentMapCacheManager,然后用这个Manager来创建ConcurrentMapCache,并将数据保存在ConcurrentMap<Object,Object>中;下图是SpringBoot支持的缓存配置。

但在实际的开发中,我们经常会使用一些缓存中间件,如:Redis、MemCached、eheache等;

1、安装Redis:安装Redis可以参考前面文章的RabbitMQ和ElasticSearch,用Docker安装比较方便,启动起来后,用客户端连接上Redis,如下图:

2、Redis整合步骤:
(1)、引入Redis的starter

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
1
2
3
4
(2)、在application.properties文件中配置Redis

spring.redis.host=192.168.1.106
1
(3)、启动Redis,并用客户端连接:

3、测试普通字符串代码:

RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootCacheApplicationTests {

@Autowired
RedisTemplate redisTemplate; //k-v都是对象

@Autowired
StringRedisTemplate stringRedisTemplate; //操作k-v都是字符串

@Test
public void testRedis(){
//给Redis中保存数据
stringRedisTemplate.opsForValue().append("msg","helloworld");

//从Redis中取数据
String msg = stringRedisTemplate.opsForValue().get("msg");
System.out.println("msg from redis:"+msg);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(1)、测试结果:
往Redis中写数据

从Redis中读数据:

(2)、说明:
Redis常见的五大数据类型:String(字符串)、list(列表)、set(集合)、hash(散列)、ZSet(有序集合)

stringRedisTemplate.opsForValue() 操作String字符串
stringRedisTemplate.opsForList() 操作list列表
stringRedisTemplate.opsForSet() 操作Set集合
stringRedisTemplate.opsForHash() 操作Hash散列
stringRedisTemplate.opsForZSet 操作Zset有序集合
1
2
3
4
5
4、测试存储对象:

@Test
public void testRedis(){
//给Redis中保存数据
redisTemplate.opsForValue().set("emp",employeeMapper.getEmpById(1));
}
1
2
3
4
5
(1)、测试结果:
往Redis中写数据,会发现是一堆字节码

(2)、自定义序列化器

@Configuration
public class MyRedisConfig {

@Bean
public RedisTemplate<Object, Employee> myRedisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Employee> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
//设置自定义序列化器
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<Employee>(Employee.class);

template.setDefaultSerializer(serializer);
return template;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(3)、测试代码,需要自动注入自己的序列化器:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootCacheApplicationTests {

@Autowired
EmployeeMapper employeeMapper;

@Autowired
RedisTemplate myRedisTemplate; //自定义的序列化器

@Test
public void testRedis(){
//给Redis中保存数据
myRedisTemplate.opsForValue().set("emp",employeeMapper.getEmpById(1));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(4)、测试结果:

四、小结
1、想要使用缓存,需要先开启缓存注解@EnableCaching;

2、熟练对@Cacheable、@CachePut、@CacheEvict、@Caching注解的使用,特别是属性的使用;
3、SpringBoot整合Redis作为缓存;
---------------------
作者:止步前行
来源:CSDN
原文:https://blog.csdn.net/zxd1435513775/article/details/85091793
版权声明:本文为博主原创文章,转载请附上博文链接!

springBoot cache操作2的更多相关文章

  1. 使用Django.core.cache操作Memcached导致性能不稳定的分析过程

    使用Django.core.cache操作Memcached导致性能不稳定的分析过程 最近测试一项目,用到了Nginx缓存服务,那可真是快啊!2Gb带宽都轻易耗尽. 不过Api接口无法简单使用Ngin ...

  2. 命令学习_IPCONFIG: DNS cache操作

    IPCONFIG: DNS cache操作 Windows会将解析到的DNS信息缓存,这个机制可以加速重复的域名访问.从DNS Server返回的DNS Response消息中带有"Time ...

  3. SpringBoot应用操作Rabbitmq(fanout广播高级操作)

    一.广播模式fanout.不需要指定路由key. 注:与topic和direct区别是:fanout广播模式会两个队列同时发送相同的消息,并非由交换器转发到某一个队列 二.实战(广播模式) 1.引入m ...

  4. SpringBoot应用操作Rabbitmq(topic交换器高级操作)

    一.topic交换器为主题交换器,可以根据路由key模糊匹配 实现模型图 二.实战 1.引入maven <dependency> <groupId>org.springfram ...

  5. SpringBoot应用操作Rabbitmq(direct高级操作)

    一.首先声明完成任务架构,通过direct订阅/发布的模式进行生产消费. a.消息生产指定交换器和路由key b.消费者绑定交换器,路由key和队列的关系(集群监控收到的消息不重复) 二.实战演练 1 ...

  6. SpringBoot应用操作Rabbitmq

    记录RabbitMQ的简单应用 1.springboot项目中引入maven包,也是springboot官方的插件 <dependency> <groupId>org.spri ...

  7. SpringBoot Cache 深入

    这上一篇文章中我们熟悉了SpringBoot Cache的基本使用,接下来我们看下它的执行流程 CacheAutoConfiguration 自动装配类 根据图中标注,看到它引用了CachingCon ...

  8. SpringBoot 结合 Spring Cache 操作 Redis 实现数据缓存

    系统环境: Redis 版本:5.0.7 SpringBoot 版本:2.2.2.RELEASE 参考地址: Redus 官方网址:https://redis.io/ 博文示例项目 Github 地址 ...

  9. SpringBoot——Cache使用原理及Redis整合

    前言及核心概念介绍 前言 本篇主要介绍SpringBoot2.x 中 Cahe 的原理及几个主要注解,以及整合 Redis 作为缓存的步骤 核心概念 先来看看核心接口的作用及关系图: CachingP ...

随机推荐

  1. jemter 使用if控制器,选择需要的内容

    背景:需要根据人员传入的变量,来选择运行的环境,调用不同的参数,进行拼接,使用到if控制器 取到的数据,调用的就是test1的数据

  2. dom4j.jar有什么作用?

    om4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点,同时它也是一个开放源代 ...

  3. ZOJ-3286 Very Simple Counting---因子数打表

    题目链接: https://cn.vjudge.net/problem/ZOJ-3286 题目大意: f(n)为n的因子个数 求出有多少个f(i)使得f(i) == f(n) && i ...

  4. 更新UI的几种方式

    在学习Handler的过程中牵涉到UI的更新,在这里就总结一下更新UI的四种方式吧,用法都比较简单,直接看代码就可以了. 一.使用Handler的post方法 新建项目,修改MainActivity代 ...

  5. ui-element消息类型 MessageBox 弹框 type类型

    MessageBox 弹框 type字段表明消息类型,可以为success,error,info和warning

  6. 【题解】洛谷P4145 花神游历各国(线段树)

    洛谷P4145:https://www.luogu.org/problemnew/show/P4145 思路 这道题的重点在于sqrt(1)=1 一个限制条件 与正常线段树不同的是区间修改为开方 那么 ...

  7. 小修改,让mvc的验证锦上添点花

    首先,mvc的客户端验证用的是jquery.validate.js, jquery.validate本身已经提供了很好的扩展功能,通过简单点配置就可以做得更好看些. 而Microsoft通过jquer ...

  8. Vertical-Align你应该知道的一切

    好,我们聊聊vertical-align.这个属性主要目的用于将相邻的文本与元素对齐.而实际上,verticle-algin可以在不同上下文中灵活地对齐元素,以及进行细粒度的控制,不必知道元素的大小. ...

  9. tomcat解析

    tomat是一个servlet容器,来处理http请求.在平时的使用中我们都会再浏览器中输入http地址来访问服务资源,比如格式http://host[":"port][abs_p ...

  10. Context initialization failed org.springframework.beans.factory.BeanCreationException

    严重: Context initialization failed org.springframework.beans.factory.BeanCreationException: Error cre ...