我是靠谱客的博主 土豪白羊,这篇文章主要介绍【四】Spring Boot之 Spring Boot + Cache + RedisTemplate整合,现在分享给大家,希望可以做个参考。

项目目录

pom.xml

复制代码
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.sid</groupId> <artifactId>springboot</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!-- spring-boot的web启动的jar包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- spring-boot 测试包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- spring boot --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <!-- spring-boot redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--jedis--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.7.3</version> </dependency> <!-- json --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency> <!-- mysql数据库连接包 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <!-- alibaba的druid数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.9</version> </dependency> <!-- 分页插件--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.5</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!-- mybatis generator 自动生成代码插件 --> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <configuration> <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile> <overwrite>true</overwrite> <verbose>true</verbose> </configuration> </plugin> </plugins> </build> </project>

application.yml

复制代码
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
server: port: 8088 servlet: context-path: /sid spring: datasource: url: jdbc:mysql://localhost:3306/sid username: root password: root # 使用druid数据源 type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver redis: database: 0 host: localhost password: root port: 6379 pool: max-maxTotal: 300 max-maxIdle: 200 maxWaitMillis: 3000 ## 该配置节点为独立的节点,不是在在spring的节点下 mybatis: mapper-locations: classpath:mapping/*.xml #注意:一定要对应mapper映射xml文件的所在路径 type-aliases-package: com.sid.model # 注意:对应实体类的路径 configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #控制台打印sql #pagehelper分页插件 pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true params: count=countSql

App.java  启动类

使用@EnableCaching表明支持缓存

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.sid; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; /** * @program: springboot * @description: springboot启动类 * @create: 2018-10-16 08:58 **/ @EnableCaching @SpringBootApplication @MapperScan("com.sid.mapper")//将项目中对应的mapper类的路径加进来就可以了 public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }

RedisConfig.java

使用@EnableCaching表明支持缓存

复制代码
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package com.sid.common; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.time.Duration; /** * @program: springboot * @description: * @author: liyijie * @create: 2018-10-16 11:19 **/ @Configuration @EnableCaching//这个注解是的支持缓存 public class RedisConfig extends CachingConfigurerSupport { /** * 管理缓存 springboot1 * @param redisTemplate * @return @Bean public CacheManager cacheManager(RedisTemplate redisTemplate) { //初始化一个RedisCacheWriter RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate); //设置默认的过期时间(以秒为单位) cacheManager.setDefaultExpiration(60*60*24); cacheManager.setUsePrefix(true); //rcm.setExpires();设置缓存区域(按key)的过期时间(以秒为单位) Map<String,Long> expiresMap=new HashMap<>(); expiresMap.put("sid:auth:cache:department",60*60L); expiresMap.put("sid:auth:cache:role",60*60L); expiresMap.put("sid:auth:cache:menu",60*60L); cacheManager.setExpires(expiresMap); //事务 //cacheManager.setTransactionAware(true); return cacheManager; }*/ /** * 管理缓存 springboot2 * @param redisTemplate * @return */ @Bean public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) { //初始化一个RedisCacheWriter RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory()); RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));//设置序列化 //设置默认超过期时间是30秒 redisCacheConfiguration.entryTtl(Duration.ofSeconds(30)); //初始化RedisCacheManager RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, redisCacheConfiguration); return cacheManager; } /** * 设置统一序列化 * @param factory * @return */ @Bean(name = "redisTemplate") public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); template.afterPropertiesSet(); //这里设置redis事务一致 //template.setEnableTransactionSupport(true); return template; } }

UserController.java

复制代码
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.sid.controller; import com.github.pagehelper.PageInfo; import com.sid.model.User; import com.sid.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; /** * @program: springboot * @description: * @author: liyijie * @create: 2018-10-16 09:28 **/ @Controller @RequestMapping(value = "/user") public class UserController { @Autowired private UserService userService; @ResponseBody @RequestMapping(value = "/add") public User addUser(User user){ return userService.addUser(user); } @ResponseBody @RequestMapping(value = "/delete") public int deleteUser(String mobilePhone){ return userService.deleteUser(mobilePhone); } @ResponseBody @RequestMapping(value = "/update") public User updateUser(User user){ return userService.updateUser(user); } @ResponseBody @RequestMapping(value = "/selectAll") public PageInfo<User> selectAll(int pageNum, int pageSize){ return userService.selectAll( pageNum, pageSize); } @ResponseBody @RequestMapping(value = "/getUserByMobilePhone") public User getUserByMobilePhone(String mobilePhone){ return userService.getUserByMobilePhone(mobilePhone); } @ResponseBody @RequestMapping(value = "/set") public void set(){ userService.set(); } }

UserMapper.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.sid.mapper; import com.sid.model.User; import org.springframework.stereotype.Component; import java.util.List; @Component public interface UserMapper { int deleteByPrimaryKey(String mobilePhone); int insert(User record); int insertSelective(User record); User selectByPrimaryKey(String id); int updateByPrimaryKeySelective(User record); int updateByPrimaryKey(User record); List<User> selectAll(); User getUserByMobilePhone(String mobilePhone); }

User.java

需要实现序列化接口

申明序列化ID

复制代码
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
package com.sid.model; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 123456789L; private Long id; private String name; private String password; private String mobilePhone; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name == null ? null : name.trim(); } public String getPassword() { return password; } public void setPassword(String password) { this.password = password == null ? null : password.trim(); } public String getMobilePhone() { return mobilePhone; } public void setMobilePhone(String mobilePhone) { this.mobilePhone = mobilePhone == null ? null : mobilePhone.trim(); } }

UserService.java

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.sid.service; import com.github.pagehelper.PageInfo; import com.sid.model.User; public interface UserService { void set(); User addUser(User user); int deleteUser(String mobilePhone); User updateUser(User user); /* * pageNum 开始页数 * pageSize 每页显示的数据条数 * */ PageInfo<User> selectAll(int pageNum, int pageSize); User getUserByMobilePhone(String mobilePhone); }

@CacheConfig(cacheNames = "user")//类级别的缓存注解,允许共享缓存名称

 

@CachePut 根据方法的请求参数对其结果进行缓存
     * 缓存新增的数据到缓存user中
     * 每次都会请求db
     * 是用方法的返回值作为value请求redis
     * userMapper.insertSelective(user); 返回1
     * 如果直接 return userMapper.insertSelective(user);
     * 则指定key的value变成了1
     *
     * 新增可以不用做缓存操作 查询的时候查询到新增的内容 会回写到缓存中
     */
   @CachePut(value = "user", key = "'CACHE_REDIS_KEY_USER' + #user.mobilePhone")

 

@CacheEvict 根据条件对缓存进行清空
 触发移除缓存 从缓存user中删除key的数据
 参数:

allEntries:非必需,默认为false。当为true时,会移除所有数据。

beforeInvocation:可以改变触发清除操作的时间,该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。
 @CacheEvict(value = "user", key = "'CACHE_REDIS_KEY_USER'+ #mobilePhone", beforeInvocation=true)

 

 @Cacheable
 在调用方法之前,首先应该在缓存中查找方法的返回值,如果这个值能够找到,就会返回缓存的值。否则,这个方法就会被调用,返回值会放到缓存之中。
     
 @Cacheable(value = "user", key = "'CACHE_REDIS_KEY_USER'+ #mobilePhone")

参数:

valuecacheNames:两个等同的参数(cacheNames为Spring 4新增,作为value的别名),用于指定缓存存储的集合名。由于Spring 4中新增了@CacheConfig,因此在Spring 3中原本必须有的value属性,也成为非必需项了

key:缓存对象存储在Map集合中的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:@Cacheable(key = "#p0"):使用函数第一个参数作为缓存的key值,更多关于SpEL表达式的详细内容可参考官方文档

condition:缓存对象的条件,非必需,也需使用SpEL表达式,只有满足表达式条件的内容才会被缓存,比如:@Cacheable(key = "#p0", condition = "#p0.length() < 10"),表示只有当第一个参数的长度小于10的时候才会被缓存。

unless:另外一个缓存条件参数,非必需,需使用SpEL表达式。它不同于condition参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断的,所以它可以通过对result进行判断。

keyGenerator:用于指定key生成器,非必需。若需要指定一个自定义的key生成器,我们需要去实现org.springframework.cache.interceptor.KeyGenerator接口,并使用该参数来指定。需要注意的是:该参数与key是互斥的

 

  @Caching 组合使用多个操作缓存的注解  evict={}中是用@CacheEvict 、 put={}中是用@CachePut 、 cacheable={}中是用@Cacheable
    
  @Caching(
             evict = {
                    @CacheEvict(value = "user", key = "'CACHE_REDIS_KEY_USER'+ #mobilePhone", beforeInvocation=true),
                     @CacheEvict(value = "user", key = "'CACHE_REDIS_KEY_USER'+ #mobilePhone")
            }
    )

UserServiceImpl.java

复制代码
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package com.sid.service.impl; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.sid.mapper.UserMapper; import com.sid.model.User; import com.sid.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.*; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; /** * @program: springboot * @description: * @author: liyijie * @create: 2018-10-16 09:30 **/ //@CacheConfig类级别的缓存注解,允许共享缓存名称 @CacheConfig(cacheNames = "user") //用于配置该类中会用到的一些共用的缓存配置。该数据访问对象中返回的内容将存储于名为users的缓存对象中 @Service public class UserServiceImpl implements UserService { public static final String CACHE_REDIS_KEY_USER = "sid:auth:cacahe:redis:key:user:"; @Autowired RedisTemplate<String, String> redisTemplate; @Autowired private UserMapper userMapper; /** * @Description: 不使用缓存 单独用redisTemplate操作redis * @Param: [] * @return: void * @Author: liyijie * @Date: 2018/10/16 0016 */ @Override public void set(){ redisTemplate.opsForValue().set("sid:test:sigle:redisTemplate:","123"); } /** @CachePut 根据方法的请求参数对其结果进行缓存 * 缓存新增的数据到缓存user中 * 每次都会请求db * 是用方法的返回值作为value请求redis * userMapper.insertSelective(user); 返回1 * 如果直接 return userMapper.insertSelective(user); * 则指定key的value变成了1 * * 新增可以不用做缓存操作 查询的时候查询到新增的内容 会回写到缓存中 */ //@CachePut(value = "user", key = "'CACHE_REDIS_KEY_USER' + #user.mobilePhone") @Override public User addUser(User user) { userMapper.insertSelective(user); return user; } /** @CacheEvict 根据条件对缓存进行清空 * 触发移除缓存 从缓存user中删除key的数据 * 使用beforeInvocation可以改变触发清除操作的时间,该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。 * * @Caching 组合使用多个操作缓存的注解 evict={}中是用@CacheEvict 、 put={}中是用@CachePut 、 cacheable={}中是用@Cacheable * * 双删+超时 保证redis和mysql的数据一致性 */ @Caching( evict = { @CacheEvict(value = "user", key = "'CACHE_REDIS_KEY_USER'+ #mobilePhone", beforeInvocation=true), @CacheEvict(value = "user", key = "'CACHE_REDIS_KEY_USER'+ #mobilePhone") } ) @Override public int deleteUser(String mobilePhone) { return userMapper.deleteByPrimaryKey(mobilePhone); } /** * @Description: 修改的时候不去改缓存 直接双删 查询的时候会回写 * @Param: [user] * @return: com.sid.model.User * @Author: liyijie * @Date: 2018/10/16 0016 */ //@CachePut(value = "user",key = "'CACHE_REDIS_KEY_USER'+ #user.mobilePhone") @Caching( evict = { @CacheEvict(value = "user", key = "'CACHE_REDIS_KEY_USER'+ #user.mobilePhone", beforeInvocation=true), @CacheEvict(value = "user", key = "'CACHE_REDIS_KEY_USER'+ #user.mobilePhone") } ) @Override public User updateUser(User user) { userMapper.updateByPrimaryKey(user); return user; } /**@Cacheable * 在调用方法之前,首先应该在缓存中查找方法的返回值,如果这个值能够找到,就会返回缓存的值。否则,这个方法就会被调用,返回值会放到缓存之中。 * */ @Cacheable(value = "user", key = "'CACHE_REDIS_KEY_USER'+ #mobilePhone") @Override public User getUserByMobilePhone(String mobilePhone){ User user = userMapper.getUserByMobilePhone(mobilePhone); System.out.println(user); return user; } //todo 分页 /* * pageNum 开始页数 * pageSize 每页显示的数据条数 * */ // 配置了selectAll函数的返回值将被加入缓存。同时在查询时,会先从缓存中获取,若不存在才再发起对数据库的访问。 //@Cacheable 触发缓存入口 //@Cacheable(value = "user", key = "#p0") @Override public PageInfo<User> selectAll(int pageNum, int pageSize) { PageHelper.startPage(pageNum, pageSize,"id desc"); //开始起始页 List<User> userList = userMapper.selectAll(); // 获取数据 PageInfo<User> page = new PageInfo<>(userList); // 实例化PageInfo return page; } //todo list缓存 lpush lpop //todo 缓存过期 }

UserMapper.xml

复制代码
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.sid.mapper.UserMapper" > <resultMap id="BaseResultMap" type="com.sid.model.User" > <id column="id" property="id" jdbcType="BIGINT" /> <result column="name" property="name" jdbcType="VARCHAR" /> <result column="password" property="password" jdbcType="VARCHAR" /> <result column="mobile_phone" property="mobilePhone" jdbcType="VARCHAR" /> </resultMap> <sql id="Base_Column_List" > id, name, password, mobile_phone </sql> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long" > select <include refid="Base_Column_List" /> from user where id = #{id,jdbcType=BIGINT} </select> <select id="selectAll" resultMap="BaseResultMap" > select <include refid="Base_Column_List" /> from user </select> <select id="getUserByMobilePhone" resultMap="BaseResultMap" parameterType="java.lang.String" > select <include refid="Base_Column_List" /> from user where mobile_phone = #{mobilePhone,jdbcType=VARCHAR} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.String" > delete from user where mobile_phone = #{mobilePhone,jdbcType=VARCHAR} </delete> <insert id="insert" parameterType="com.sid.model.User" > insert into user (id, name, password, mobile_phone) values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{mobilePhone,jdbcType=VARCHAR}) </insert> <insert id="insertSelective" parameterType="com.sid.model.User" > insert into user <trim prefix="(" suffix=")" suffixOverrides="," > <if test="id != null" > id, </if> <if test="name != null" > name, </if> <if test="password != null" > password, </if> <if test="mobilePhone != null" > mobile_phone, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides="," > <if test="id != null" > #{id,jdbcType=BIGINT}, </if> <if test="name != null" > #{name,jdbcType=VARCHAR}, </if> <if test="password != null" > #{password,jdbcType=VARCHAR}, </if> <if test="mobilePhone != null" > #{mobilePhone,jdbcType=VARCHAR}, </if> </trim> </insert> <update id="updateByPrimaryKeySelective" parameterType="com.sid.model.User" > update user <set > <if test="name != null" > name = #{name,jdbcType=VARCHAR}, </if> <if test="password != null" > password = #{password,jdbcType=VARCHAR}, </if> <if test="mobilePhone != null" > mobile_phone = #{mobilePhone,jdbcType=VARCHAR}, </if> </set> where id = #{id,jdbcType=BIGINT} </update> <update id="updateByPrimaryKey" parameterType="com.sid.model.User" > update user set name = #{name,jdbcType=VARCHAR}, password = #{password,jdbcType=VARCHAR}, mobile_phone = #{mobilePhone,jdbcType=VARCHAR} where id = #{id,jdbcType=BIGINT} </update> </mapper>

 

最后

以上就是土豪白羊最近收集整理的关于【四】Spring Boot之 Spring Boot + Cache + RedisTemplate整合的全部内容,更多相关【四】Spring内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(86)

评论列表共有 0 条评论

立即
投稿
返回
顶部