Skip to content

Commit 1cb7cdb

Browse files
author
Xiong Neng
committed
完成springboot-cache
1 parent 1f6885b commit 1cb7cdb

File tree

6 files changed

+108
-124
lines changed

6 files changed

+108
-124
lines changed

springboot-cache/pom.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<groupId>org.springframework.boot</groupId>
1717
<artifactId>spring-boot-starter-parent</artifactId>
1818
<version>2.0.4.RELEASE</version>
19+
<relativePath/>
1920
</parent>
2021

2122
<properties>
@@ -34,10 +35,10 @@
3435
<artifactId>spring-boot-starter-data-redis</artifactId>
3536
</dependency>
3637
<dependency>
37-
<groupId>redis.clients</groupId>
38-
<artifactId>jedis</artifactId>
39-
<version>2.9.0</version>
38+
<groupId>org.apache.commons</groupId>
39+
<artifactId>commons-pool2</artifactId>
4040
</dependency>
41+
4142
<dependency>
4243
<groupId>com.fasterxml.jackson.core</groupId>
4344
<artifactId>jackson-databind</artifactId>

springboot-cache/src/main/java/com/xncoding/trans/Application.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.cache.annotation.EnableCaching;
56

67
@SpringBootApplication
8+
@EnableCaching
79
public class Application {
810
public static void main(String[] args) {
911
SpringApplication.run(Application.class, args);

springboot-cache/src/main/java/com/xncoding/trans/config/RedisCacheConfig.java

Lines changed: 23 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111
import org.springframework.cache.interceptor.KeyGenerator;
1212
import org.springframework.context.annotation.Bean;
1313
import org.springframework.context.annotation.Configuration;
14+
import org.springframework.core.env.Environment;
1415
import org.springframework.data.redis.cache.RedisCacheConfiguration;
1516
import org.springframework.data.redis.cache.RedisCacheManager;
1617
import org.springframework.data.redis.connection.RedisConnectionFactory;
18+
import org.springframework.data.redis.connection.RedisPassword;
1719
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
1820
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
21+
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
1922
import org.springframework.data.redis.core.RedisTemplate;
2023
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
2124
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
@@ -37,73 +40,38 @@
3740
*/
3841
@Configuration
3942
@EnableCaching
40-
public class RedisCacheConfig extends CachingConfigurerSupport {
43+
public class RedisCacheConfig {
4144
private Logger logger = LoggerFactory.getLogger(this.getClass());
4245

43-
@Value("${spring.redis.host}")
44-
private String host;
45-
46-
@Value("${spring.redis.port}")
47-
private String port;
48-
49-
@Bean
50-
public RedisStandaloneConfiguration getRedisClient() {
51-
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(host, Integer.parseInt(port));
52-
return redisStandaloneConfiguration;
53-
}
46+
@Autowired
47+
private Environment env;
5448

5549
@Bean
56-
public JedisConnectionFactory redisConnectionFactory(RedisStandaloneConfiguration RedisStandaloneConfiguration) {
57-
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(RedisStandaloneConfiguration);
58-
return jedisConnectionFactory;
50+
public LettuceConnectionFactory redisConnectionFactory() {
51+
RedisStandaloneConfiguration redisConf = new RedisStandaloneConfiguration();
52+
redisConf.setHostName(env.getProperty("spring.redis.host"));
53+
redisConf.setPort(Integer.parseInt(env.getProperty("spring.redis.port")));
54+
redisConf.setPassword(RedisPassword.of(env.getProperty("spring.redis.password")));
55+
return new LettuceConnectionFactory(redisConf);
5956
}
6057

6158
@Bean
62-
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
63-
RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
64-
redisTemplate.setConnectionFactory(cf);
65-
return redisTemplate;
59+
public RedisCacheConfiguration cacheConfiguration() {
60+
RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
61+
.entryTtl(Duration.ofSeconds(600))
62+
.disableCachingNullValues();
63+
return cacheConfig;
6664
}
6765

6866
@Bean
69-
public RedisCacheConfiguration redisCacheConfiguration() {
70-
return RedisCacheConfiguration
71-
.defaultCacheConfig()
72-
.serializeKeysWith(
73-
RedisSerializationContext
74-
.SerializationPair
75-
.fromSerializer(new StringRedisSerializer()))
76-
.serializeValuesWith(
77-
RedisSerializationContext
78-
.SerializationPair
79-
.fromSerializer(new GenericJackson2JsonRedisSerializer()))
80-
.entryTtl(Duration.ofSeconds(600L));
67+
public RedisCacheManager cacheManager() {
68+
RedisCacheManager rcm = RedisCacheManager.builder(redisConnectionFactory())
69+
.cacheDefaults(cacheConfiguration())
70+
.transactionAware()
71+
.build();
72+
return rcm;
8173
}
8274

83-
@Bean
84-
public CacheManager cacheManager(RedisConnectionFactory cf) {
85-
//RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(cf);
86-
//RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, RedisCacheConfiguration.defaultCacheConfig());
87-
RedisCacheManager cm = RedisCacheManager.builder(cf).cacheDefaults(redisCacheConfiguration()).build();
88-
return cm;
89-
}
90-
91-
// @Bean
92-
// public KeyGenerator keyGenerator() {
93-
// return new KeyGenerator() {
94-
// @Override
95-
// public Object generate(Object o, Method method, Object... objects) {
96-
// StringBuilder sb = new StringBuilder();
97-
// sb.append(o.getClass().getName());
98-
// sb.append(method.getName());
99-
// for (Object obj : objects) {
100-
// sb.append(obj.toString());
101-
// }
102-
// return sb.toString();
103-
// }
104-
// };
105-
// }
106-
10775
/**
10876
* 自定义缓存key的生成类实现
10977
*/
Lines changed: 35 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,84 @@
11
package com.xncoding.trans.service;
22

3+
import com.baomidou.mybatisplus.mapper.Condition;
34
import com.xncoding.trans.dao.entity.User;
45
import com.xncoding.trans.dao.repository.UserMapper;
56
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
7-
import org.springframework.cache.annotation.CacheConfig;
8-
import org.springframework.cache.annotation.CacheEvict;
9-
import org.springframework.cache.annotation.CachePut;
10-
import org.springframework.cache.annotation.Cacheable;
8+
import org.springframework.cache.annotation.*;
119
import org.springframework.stereotype.Service;
10+
import org.springframework.transaction.annotation.Transactional;
1211

1312
import javax.annotation.Resource;
13+
import java.util.List;
1414

1515
@Service
16-
@CacheConfig(cacheNames = "users")
16+
@Transactional
1717
public class UserService {
1818
private Logger logger = LoggerFactory.getLogger(this.getClass());
1919
@Resource
2020
private UserMapper userMapper;
2121

2222
/**
2323
* cacheNames 设置缓存的值
24-
* key:指定缓存的key,这是指参数id值。 key可以使用spEl表达式
24+
* key:指定缓存的key,这是指参数id值。key可以使用spEl表达式
2525
*
2626
* @param id
2727
* @return
2828
*/
29-
@Cacheable(key = "#id")
29+
@Cacheable(value = "userCache", key = "#id", unless="#result == null")
3030
public User getById(int id) {
3131
logger.info("获取用户start...");
3232
return userMapper.selectById(id);
3333
}
3434

35-
/***
36-
* 如果设置sync=true,
37-
* 如果缓存中没有数据,多个线程同时访问这个方法,则只有一个方法会执行到方法,其它方法需要等待
38-
* 如果缓存中已经有数据,则多个线程可以同时从缓存中获取数据
39-
* @param id
40-
* @return
41-
*/
42-
@Cacheable(key = "#id", sync = true)
43-
public User getById2(int id) {
44-
logger.info("获取用户start...");
45-
return userMapper.selectById(id);
35+
@Cacheable(value = "allUsersCache", unless = "#result.size() == 0")
36+
public List<User> getAllUsers() {
37+
logger.info("获取所有用户列表");
38+
return userMapper.selectList(null);
4639
}
4740

4841
/**
49-
* 以上我们使用默认的keyGenerator,对应spring的SimpleKeyGenerator
50-
* 如果你的使用很复杂,我们也可以自定义myKeyGenerator的生成key
51-
* <p>
52-
* key和keyGenerator是互斥,如果同时制定会出异常
53-
* The key and keyGenerator parameters are mutually exclusive and an operation specifying both will result in an exception.
54-
*
55-
* @param id
56-
* @return
42+
* 创建用户,同时使用新的返回值的替换缓存中的值
43+
* 创建用户后会将allUsersCache缓存全部清空
5744
*/
58-
@Cacheable(keyGenerator = "myKeyGenerator")
59-
public User queryUserById(int id) {
60-
logger.info("queryUserById,id={}", id);
61-
return userMapper.selectById(id);
62-
}
63-
64-
/**
65-
* 每次执行都会执行方法,同时使用新的返回值的替换缓存中的值
66-
*
67-
* @param user
68-
*/
69-
@CachePut(key = "#user.id")
70-
public void createUser(User user) {
45+
@Caching(
46+
put = {@CachePut(value = "userCache", key = "#user.id")},
47+
evict = {@CacheEvict(value = "allUsersCache", allEntries = true)}
48+
)
49+
public User createUser(User user) {
7150
logger.info("创建用户start..., user.id=" + user.getId());
7251
userMapper.insert(user);
52+
return user;
7353
}
7454

7555
/**
76-
* 每次执行都会执行方法,同时使用新的返回值的替换缓存中的值
77-
*
78-
* @param user
56+
* 更新用户,同时使用新的返回值的替换缓存中的值
57+
* 更新用户后会将allUsersCache缓存全部清空
7958
*/
80-
@CachePut(key = "#user.id")
81-
public void updateUser(User user) {
59+
@Caching(
60+
put = {@CachePut(value = "userCache", key = "#user.id")},
61+
evict = {@CacheEvict(value = "allUsersCache", allEntries = true)}
62+
)
63+
public User updateUser(User user) {
8264
logger.info("更新用户start...");
8365
userMapper.updateById(user);
66+
return user;
8467
}
8568

8669
/**
87-
* 对符合key条件的记录从缓存中book1移除
70+
* 对符合key条件的记录从缓存中移除
71+
* 删除用户后会将allUsersCache缓存全部清空
8872
*/
89-
@CacheEvict(key = "#id")
73+
@Caching(
74+
evict = {
75+
@CacheEvict(value = "userCache", key = "#id"),
76+
@CacheEvict(value = "allUsersCache", allEntries = true)
77+
}
78+
)
9079
public void deleteById(int id) {
9180
logger.info("删除用户start...");
9281
userMapper.deleteById(id);
9382
}
9483

95-
/**
96-
* allEntries = true: 清空user1里的所有缓存
97-
*/
98-
@CacheEvict(allEntries=true)
99-
public void clearUser1All(){
100-
logger.info("clearAll");
101-
}
102-
10384
}

springboot-cache/src/main/resources/application.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ spring:
1010
profiles:
1111
active: dev
1212
datasource:
13-
url: jdbc:mysql://127.0.0.1:3306/test?useSSL=false&autoReconnect=true&tinyInt1isBit=false&useUnicode=true&characterEncoding=utf8
13+
url: jdbc:mysql://123.207.66.156:3306/test?useSSL=false&autoReconnect=true&tinyInt1isBit=false&useUnicode=true&characterEncoding=utf8
1414
username: root
15-
password: 123456
15+
password: _EnZhi123
1616

1717
################### mybatis-plus配置 ###################
1818
mybatis-plus:
@@ -42,10 +42,22 @@ spring:
4242
profiles: dev
4343
cache:
4444
type: REDIS
45+
redis:
46+
cache-null-values: false
47+
time-to-live: 600000ms
48+
use-key-prefix: true
49+
cache-names: userCache,allUsersCache
4550
redis:
4651
host: 123.207.66.156
4752
port: 6379
4853
database: 0
54+
lettuce:
55+
shutdown-timeout: 200ms
56+
pool:
57+
max-active: 7
58+
max-idle: 7
59+
min-idle: 2
60+
max-wait: -1ms
4961

5062
logging:
5163
level:

springboot-cache/src/test/java/com/xncoding/service/UserServiceTest.java

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
import org.junit.runner.RunWith;
88
import org.springframework.beans.factory.annotation.Autowired;
99
import org.springframework.boot.test.context.SpringBootTest;
10+
import org.springframework.test.annotation.Rollback;
1011
import org.springframework.test.context.junit4.SpringRunner;
12+
import org.springframework.transaction.annotation.Transactional;
1113

14+
import java.util.List;
1215
import java.util.Random;
1316

1417
import static org.junit.Assert.assertEquals;
@@ -24,24 +27,41 @@
2427
*/
2528
@RunWith(SpringRunner.class)
2629
@SpringBootTest(classes = Application.class)
30+
@Transactional
2731
public class UserServiceTest {
2832
@Autowired
2933
private UserService userService;
3034
@Test
3135
public void testCache() {
32-
int id = new Random().nextInt(100);
36+
// 创建一个用户admin
37+
int id = new Random().nextInt(1000);
3338
User user = new User(id, "admin", "admin");
3439
userService.createUser(user);
35-
User user1 = userService.getById(id); // 第1次访问
36-
assertEquals(user1.getPassword(), "admin");
37-
User user2 = userService.getById(id); // 第2次访问
38-
assertEquals(user2.getPassword(), "admin");
39-
User user3 = userService.queryUserById(id); // 第3次访问,使用自定义的KeyGenerator
40+
41+
// 再创建一个用户xiong
42+
int id2 = new Random().nextInt(1000);
43+
User user2 = new User(id2, "xiong", "neng");
44+
userService.createUser(user2);
45+
46+
// 查询所有用户列表
47+
List<User> list = userService.getAllUsers();
48+
assertEquals(list.size(), 2);
49+
50+
// 两次访问看看缓存命中情况
51+
User user3 = userService.getById(id); // 第1次访问
4052
assertEquals(user3.getPassword(), "admin");
41-
user.setPassword("123456");
42-
userService.updateUser(user);
43-
User user4 = userService.getById(id); // 第4次访问
44-
assertEquals(user4.getPassword(), "123456");
53+
User user4 = userService.getById(id); // 第2次访问
54+
assertEquals(user4.getPassword(), "admin");
55+
56+
// 更新用户密码
57+
user4.setPassword("123456");
58+
userService.updateUser(user4);
59+
60+
// 更新完成后再次访问用户
61+
User user5 = userService.getById(id); // 第4次访问
62+
assertEquals(user5.getPassword(), "123456");
63+
64+
// 删除用户admin
4565
userService.deleteById(id);
4666
assertNull(userService.getById(id));
4767
}

0 commit comments

Comments
 (0)