名称 |
解释 |
Cache | 缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、ConcurrentMapCache等 |
CacheManager | 缓存管理器,管理各种缓存(cache)组件 |
@Cacheable | 主要针对方法配置,能够根据方法的请求参数对其进行缓存 |
@CacheEvict | 清空缓存 |
@CachePut | 保证方法被调用,又希望结果被缓存与@Cacheable区别在于是否每次都调用方法,常用于更新 |
@EnableCaching | 开启基于注解的缓存 |
keyGenerator | 缓存数据时key生成策略 |
serialize | 缓存数据时value序列化策略 |
@CacheConfig | 统一配置本类的缓存注解的属性 |
安装docker
开机启动docker
检验docker是否安装成功
docker安装redis
docker检测是否安装成功redis
docker启动redis并设置端口映射(-d表示后台运行)
查看redis是否启动成功
在看代码前先看看目录结构吧(在这里使用ssm来整合redis)
数据库表结构
pom.xml文件,这里主要是引入spring-boot-starter-cache依赖
配置文件application.yml,配置redis
启动类加入@EnableCaching注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package
com.lzh.springbootstudytestcache;
import
org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.SpringBootApplication;
import
org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public
class
SpringBootStudyTestCacheApplication {
public
static
void
main(String[] args) {
SpringApplication.run(SpringBootStudyTestCacheApplication.
class
, args);
}
}
|
UserController 类暴露接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
package
com.lzh.springbootstudytestcache.controller;
import
com.lzh.springbootstudytestcache.model.User;
import
com.lzh.springbootstudytestcache.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.RequestParam;
import
org.springframework.web.bind.annotation.RestController;
/**
* @author lzh
* create 2019-09-24-20:34
*/
@RestController
public
class
UserController {
@Autowired
UserService userService;
@GetMapping
(
"/user/save"
)
public
User saveUser(
@RequestParam
Integer id,
@RequestParam
String name,
@RequestParam
Integer age){
User user= userService.save(
new
User(id,name,age));
return
user;
}
@GetMapping
(
"/user/{id}"
)
public
User getUserById(
@PathVariable
Integer id){
System.out.println(
"id="
+id);
User user = userService.findUserById(id);
System.out.println(
"getUserById - "
+user);
return
user;
}
@GetMapping
(
"/user/update"
)
public
User updateUser(
@RequestParam
Integer id,
@RequestParam
String name,
@RequestParam
Integer age){
User user= userService.updateUser(
new
User(id,name,age));
return
user;
}
@GetMapping
(
"/user/del/{id}"
)
public
String deleteUser(
@PathVariable
Integer id){
System.out.println(
"id="
+id);
int
num = userService.deleteUser(id);
if
(num >
0
){
return
"删除成功"
;
}
else
{
return
"删除失败"
;
}
}
}
|
1
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package
com.lzh.springbootstudytestcache.service;
import
com.lzh.springbootstudytestcache.model.User;
/**
* @author lzh
* create 2019-09-24-9:14
*/
public
interface
UserService {
User save(User user);
User findUserById(Integer id);
User updateUser(User user);
int
deleteUser(Integer id);
}
|
UserService实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
package
com.lzh.springbootstudytestcache.service.impl;
import
com.lzh.springbootstudytestcache.mapper.UserMapper;
import
com.lzh.springbootstudytestcache.model.User;
import
com.lzh.springbootstudytestcache.service.UserService;
import
lombok.extern.log4j.Log4j2;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.cache.annotation.CacheEvict;
import
org.springframework.cache.annotation.CachePut;
import
org.springframework.cache.annotation.Cacheable;
import
org.springframework.stereotype.Service;
/**
* @author lzh
* create 2019-09-24-9:14
*/
@Service
@Log4j2
public
class
UserServiceImpl
implements
UserService {
@Autowired
UserMapper userMapper;
@Cacheable
(value =
"user"
,key =
"#user.id"
)
@Override
public
User save(User user) {
int
saveNum = userMapper.saveUser(user);
System.out.println(
"saveNum="
+saveNum);
return
user;
}
@Cacheable
(value =
"user"
,key =
"#id"
)
@Override
public
User findUserById(Integer id) {
log.info(
"进入findUserById方法"
);
return
userMapper.findUserById(id);
}
@CachePut
(value =
"user"
, key =
"#user.id"
)
@Override
public
User updateUser(User user) {
int
num = userMapper.updateUser(user);
System.out.println(
"num="
+num);
return
user;
}
@CacheEvict
(value =
"user"
)
@Override
public
int
deleteUser(Integer id) {
return
userMapper.deleteUser(id);
}
}
|
User实体类,加入@Data相当于加入getset方法,@AllArgsConstructor全参构造方法,@ToString重写tostring方法,引入Lombok简化代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package
com.lzh.springbootstudytestcache.model;
import
lombok.AllArgsConstructor;
import
lombok.Data;
import
lombok.ToString;
import
java.io.Serializable;
/**
* @author Levin
* @since 2018/5/10 0007
*/
@Data
@AllArgsConstructor
@ToString
public
class
User
implements
Serializable {
private
Integer id;
private
String name;
private
Integer age;
}
|
UserMapper持久层,使用mybatis注解@Select、@Update、@Insert、@Delete实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package
com.lzh.springbootstudytestcache.mapper;
import
com.lzh.springbootstudytestcache.model.User;
import
org.apache.ibatis.annotations.*;
/**
* @author lzh
* create 2019-09-24-20:39
*/
@Mapper
public
interface
UserMapper {
@Select
(
"SELECT * FROM User WHERE id = #{id}"
)
User findUserById(Integer id);
@Update
(
"update user set name=#{name},age=#{age} where id=#{id}"
)
int
updateUser(User user);
@Insert
(
"insert into user set name=#{name},age=#{age}"
)
int
saveUser(User user);
@Delete
(
"DELETE FROM USER WHERE id=#{id}"
)
int
deleteUser(Integer id);
}
|
改变默认jdk序列化器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
package
com.lzh.springbootstudytestcache.config;
import
com.fasterxml.jackson.annotation.JsonAutoDetect;
import
com.fasterxml.jackson.annotation.PropertyAccessor;
import
com.fasterxml.jackson.databind.ObjectMapper;
import
org.springframework.context.annotation.Bean;
import
org.springframework.context.annotation.Configuration;
import
org.springframework.data.redis.connection.RedisConnectionFactory;
import
org.springframework.data.redis.core.RedisTemplate;
import
org.springframework.data.redis.serializer.*;
/**
* @author lzh
* create 2019-09-24-22:22
*/
import
org.springframework.cache.CacheManager;
import
org.springframework.context.annotation.Primary;
import
org.springframework.data.redis.cache.RedisCacheConfiguration;
import
org.springframework.data.redis.cache.RedisCacheManager;
import
org.springframework.data.redis.cache.RedisCacheWriter;
import
java.time.Duration;
//@Configuration
public
class
MyRedisConfig {
//@Bean(name = "redisTemplate")
public
RedisTemplate
RedisTemplate
new
RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(keySerializer());
redisTemplate.setHashKeySerializer(keySerializer());
redisTemplate.setValueSerializer(valueSerializer());
redisTemplate.setHashValueSerializer(valueSerializer());
return
redisTemplate;
}
//@Primary
//@Bean
public
CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
//缓存配置对象
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration.entryTtl(Duration.ofMinutes(30L))
//设置缓存的默认超时时间:30分钟
.disableCachingNullValues()
//如果是空值,不缓存
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
//设置key序列化器
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer((valueSerializer())));
//设置value序列化器
return
RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
}
private
RedisSerializer
return
new
StringRedisSerializer();
}
private
RedisSerializer
return
new
GenericJackson2JsonRedisSerializer();
}
}
|
启动srpingboot访问http://localhost:8080/user/1
使用redis可视化工具查看发现多了一个user对象,这就是在执行查询语句的时候保存的缓存
看控制台这里打印出了日志,这是第一次查询,说明执行了sql语句
再次访问http://localhost:8080/user/1,没有执行findUserById方法说明没有执行sql语句,而是直接从redis缓存中读取