Redis 在 Spring Boot 2.x 中相比 1.5.x 版本,有一些改变。redis 默认链接池,1.5.x 使用了 jedis,而2.x 使用了 lettuce

Redis 接入 Spring Boot 缓存,使用的注解跟 Ehcache 接入缓存的注解是一样的,Spring Boot 缓存应用 Ehcache 入门教程

安装 Redis 请参见 如何在 Mac 下安装 Redis 和 如何在 Window 下安装 Redis

本文仅仅适用

  • spring boot 2.x
  • redis
  • jdk 1.8+

本项目源码下载

0 注意

本章代码与 Spring Boot 缓存应用 Ehcache 入门教程 基本是相同的,不同的是 Ehcache 换成了 Redis。有几点需要注意

  • 本示例代码是基于 Spring Boot 2.1.6,Redis for Spring Boot 2.x 的配置与 Spring Boot 1.5.x 配置有细微的差别,主要是 Redis 默认连接池区别。
  • 实体类 UserDO 必须要求支持序列化,继承与 implements Serializable
  • Redis 没有进行 xml 配置文件配置,使用了 @Configuration 进行配置

1 新建 Spring Boot Maven 示例工程项目

注意:是用来 IDEA 开发工具

  1. File > New > Project,如下图选择 Spring Initializr 然后点击 【Next】下一步
  2. 填写 GroupId(包名)、Artifact(项目名) 即可。点击 下一步

    groupId=com.fishpro

    artifactId=redis
  3. 选择依赖 Spring Web Starter 前面打钩。
  4. 项目名设置为 spring-boot-study-redis.

2 引入依赖 Pom

  • fastjson
  • redis
  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-data-redis</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>com.alibaba</groupId>
  12. <artifactId>fastjson</artifactId>
  13. <version>1.2.44</version>
  14. </dependency>
  15. <dependency>
  16. <groupId>org.springframework.boot</groupId>
  17. <artifactId>spring-boot-starter-test</artifactId>
  18. <scope>test</scope>
  19. </dependency>
  20. </dependencies>

3 Redis 使用注解实现缓存

使用注解方式,不需要做配置也可以运行示例,我们这里不用编写配置文件,只要在启动类上加上 @EnableCaching 注解就可以使用

3.1 示例代码

整个业务代码包括了

模拟一个增删改查来设置缓存示例,包括了

  • UserService 用户服务类
  • UserServiceImpl 用户服务实现类
  • UserController 用户控制层类使用了 RestController

UserService 用户接口(路径 src/main/java/com/fishpro/redis/service/UserService.java)

  1. public interface UserService {
  2. List<UserDO> list();
  3. UserDO get(Integer id);
  4. UserDO save(UserDO user);
  5. UserDO update(UserDO user);
  6. void delete(Integer id);
  7. }

UserServiceImpl(路径 src/main/java/com/fishpro/redis/service/impl/UserServiceImpl.java)

  1. // fpcache 对应 ehcache.xml 中的 fpcache 节点
  2. @CacheConfig(cacheNames = {"fpcache"})
  3. @Service
  4. public class UserServiceImpl implements UserService {
  5. @Override
  6. @Cacheable("fpcache")
  7. public List<UserDO> list() {
  8. List<UserDO> list=new ArrayList<>();
  9. list.add( new UserDO(1,"fishpro","123456",1));
  10. list.add( new UserDO(2,"fishpro2","123456",1));
  11. list.add( new UserDO(3,"fishpro3","123456",1));
  12. System.out.println("获取用户列表使用 @Cacheable 注意执行第二次的时候不会有本语句输出了,部分删除掉缓存");
  13. return list;
  14. }
  15. @Override
  16. @Cacheable(value = "fpcache",key = "#id")
  17. public UserDO get(Integer id) {
  18. System.out.println("获取单个用户 get user by"+id);
  19. return new UserDO(1,"fishpro","123456",1);
  20. }
  21. @Override
  22. @CachePut(value = "fpcache",key = "#user.id")
  23. public UserDO save(UserDO user) {
  24. System.out.println("保存用户使用 @CachePut 每次都会执行语句并缓存 save user by "+user.getUserName());
  25. return user;
  26. }
  27. @Override
  28. @CachePut(value = "fpcache",key = "#user.id")
  29. public UserDO update(UserDO user) {
  30. System.out.println("更新用户使用 @CachePut 每次都会执行语句并缓存 update user by "+user.getUserName());
  31. return user;
  32. }
  33. @Override
  34. @CacheEvict(allEntries = true)
  35. public void delete(Integer id) {
  36. System.out.println("删除用户根据用户ID,如果 allEntries = true 则不论 key 是啥都全部删除缓存"+id);
  37. }
  38. }

UserController(路径 src/main/java/com/fishpro/redis/controller/UserController.java)


  1. @RestController
  2. public class UserController {
  3. @Autowired
  4. private UserService userService;
  5. @GetMapping("/test")
  6. public String testCache(){
  7. System.out.println("============以下第一次调用 ================");
  8. userService.list();
  9. userService.get(1);
  10. userService.save(new UserDO(1,"fishpro","123456",1));
  11. userService.update(new UserDO(1,"fishpro","123456434",1));
  12. System.out.println("============以下第二次调用 观察 list 和 get 方法 ================");
  13. userService.list();
  14. userService.get(1);
  15. userService.save(new UserDO(1,"fishpro","123456",1));
  16. userService.update(new UserDO(1,"fishpro","123456434",1));
  17. System.out.println("============以下第三次调用 先删除 观察 list 和 get 方法 ================");
  18. userService.delete(1);
  19. userService.list();
  20. userService.get(1);
  21. userService.save(new UserDO(1,"fishpro","123456",1));
  22. userService.update(new UserDO(1,"fishpro","123456434",1));
  23. return "";
  24. }
  25. }

3.2 运行

右键 RedisApplication 选择 Run RedisApplication 在浏览器中输入 http://localhost:8080/test

4 Redis 使用 RedisTemplate 方式实现

与使用注解方式不同,注解方式可以零配置,只需引入依赖并在启动类上加上 @EnableCaching 注解就可以使用;而使用 RedisTemplate 方式麻烦些,需要做一些配置

本示例中设置 redis 为 StringRedisSerializer

4.1 配置

  1. #2.x版本中由于引入了不同客户端,需要指定配置哪种连接池
  2. #jedis客户端
  3. spring:
  4. cache:
  5. type: redis
  6. redis:
  7. host: 127.0.0.1
  8. port: 6379
  9. password:
  10. database: 0
  11. jedis:
  12. pool:
  13. max-active: 8
  14. max-wait: -1ms
  15. max-idle: 8
  16. min-idle: 0

然后写个 RedisConfig.java 配置类,本示例中设置 redis 为 StringRedisSerializer

  1. @Configuration
  2. public class RedisConfig extends CachingConfigurerSupport {
  3. @Bean
  4. public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
  5. RedisTemplate<Object,Object> template = new RedisTemplate<>();
  6. //设置连接池
  7. template.setConnectionFactory(redisConnectionFactory);
  8. StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
  9. template.setValueSerializer(serializer);
  10. //hash value的序列化问题
  11. template.setHashValueSerializer(serializer);
  12. //key 的序列化
  13. template.setKeySerializer(new StringRedisSerializer());
  14. template.setHashKeySerializer(new StringRedisSerializer());
  15. return template;
  16. }
  17. @Bean
  18. public CacheManager cacheManager(RedisConnectionFactory factory){
  19. // 生成一个默认配置,通过config对象即可对缓存进行自定义配置
  20. RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
  21. // 设置缓存的默认过期时间,也是使用Duration设置
  22. config = config.entryTtl(Duration.ofMinutes(1))
  23. .disableCachingNullValues(); // 不缓存空值
  24. // 设置一个初始化的缓存空间set集合
  25. Set<String> cacheNames = new HashSet<>();
  26. cacheNames.add("my-redis-cache1");
  27. cacheNames.add("my-redis-cache2");
  28. // 对每个缓存空间应用不同的配置
  29. Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
  30. configMap.put("my-redis-cache1", config);
  31. configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120)));
  32. // 使用自定义的缓存配置初始化一个cacheManager
  33. RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
  34. .initialCacheNames(cacheNames) // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
  35. .withInitialCacheConfigurations(configMap)
  36. .build();
  37. return cacheManager;
  38. }
  39. }

4.3 Redis 数据结构简介

Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。

结构 结构存储的值范围
String 可以是字符串、整数或者浮点数
List 一个链表,链表上的每个节点都包含了一个字符串
Set 包含字符串的无序收集器(unorderedcollection),并且被包含的每个字符串都是独一无二的、各不相同
Hash 包含键值对的无序散列表
Zset 字符串成员(member)与浮点数分值(score)之间的有序映射,元素的排列顺序由分值的大小决定

4.4 StringRedisTemplate 与 RedisTemplate

StringRedisTemplate 与 RedisTemplate 区别

  • StringRedisTemplate 继承 RedisTemplate
  • RedisTemplate 是一个泛型类,而 StringRedisTemplate 不是
  • StringRedisTemplate 只能对 key=String,value=String 的键值操作。
  • 他们各自序列化的方式不同,但是都会得到一个字节数组。StringRedisTemplate 使用的是 StringRedisSerializer 类;RedisTemplate 使用的是 JdkSerializationRedisSerializer 类。反序列化,则是一个得到 String,一个得到 Object
  • 两者的数据是不共通的,StringRedisTemplate 只能管理 StringRedisTemplate 里面的数据,RedisTemplate 只能管理 RedisTemplate中 的数据。

4.5 代码实例

RedisController(路径 src/main/java/com/fishpro/redis/controller/RedisController(路径.java)

  1. package com.fishpro.redis.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
  4. import org.springframework.data.redis.connection.RedisZSetCommands;
  5. import org.springframework.data.redis.core.*;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RequestParam;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import java.util.*;
  10. import java.util.function.Consumer;
  11. @RestController
  12. public class RedisController {
  13. @Autowired
  14. RedisTemplate redisTemplate;
  15. @Autowired
  16. StringRedisTemplate stringRedisTemplate;
  17. public static final String CACHE_PREFIX = "FP:";
  18. @RequestMapping("/redis")
  19. public String testRedis(){
  20. System.out.println("字符串和散列Value和Hash-------------------------------------------------------");
  21. //set字符串
  22. redisTemplate.opsForValue().set("string_key", "string value");
  23. System.out.println("-------------set字符串-------------------: " + redisTemplate.opsForValue().get("string_key"));
  24. //注意这里使用了JDK的序列化器,所以redis保存时不是整数,不能运算
  25. redisTemplate.opsForValue().set("int_key", "1");
  26. System.out.println("-------------set int_key-------------------: " + redisTemplate.opsForValue().get("int_key"));
  27. stringRedisTemplate.opsForValue().set("int", "1");
  28. System.out.println("-------------stringRedisTemplate set int-------------------: " + redisTemplate.opsForValue().get("int"));
  29. //使用运算
  30. stringRedisTemplate.opsForValue().increment("int", 1);
  31. System.out.println("-------------使用运算+1-------------------: " + redisTemplate.opsForValue().get("int"));
  32. //定义一个hashmap散列
  33. Map<String, String> hash = new HashMap<String, String>();
  34. hash.put("field1", "value1");
  35. hash.put("field2", "value2");
  36. //存入一个散列数据类型
  37. stringRedisTemplate.opsForHash().putAll("hash", hash);
  38. System.out.println("-------------存入一个散列数据类型-------------------: ");
  39. System.out.println("-------------map 遍历-------------------: ");
  40. redisTemplate.opsForHash().entries("hash").forEach((k, v) -> {
  41. System.out.println(k + ": " + v);
  42. });
  43. System.out.println("-------------map->set 遍历-------------------: ");
  44. redisTemplate.opsForHash().keys("hash").forEach(key -> {
  45. System.out.println(key + ": " + redisTemplate.opsForHash().get("hash", key));
  46. });
  47. //新增一个字段
  48. stringRedisTemplate.opsForHash().put("hash", "field3", "value3");
  49. System.out.println("-------------新增一个字段 field3-------------------: ");
  50. redisTemplate.opsForHash().entries("hash").forEach((k, v) -> {
  51. System.out.println(k + ": " + v);
  52. });
  53. //绑定散列操作的key,这样可以连续对同一个散列数据进行操作
  54. BoundHashOperations hashOps = stringRedisTemplate.boundHashOps("hash");
  55. //删除两个字段
  56. hashOps.delete("field1", "field2");
  57. System.out.println("-------------删除两个字段 field1 field2-------------------: ");
  58. hashOps.entries().forEach((k, v) -> {
  59. System.out.println(k + ": " + v);
  60. });
  61. //新增一个字段
  62. hashOps.put("field5", "value5");
  63. System.out.println("-------------新增一个字段 field5-------------------: ");
  64. hashOps.entries().forEach((k, v) -> {
  65. System.out.println(k + ": " + v);
  66. });
  67. System.out.println("列表(链表)List-------------------------------------------------------");
  68. //list 链表
  69. //插入两个链表,注意它们在链表中的顺序
  70. //链表从左到右的顺序为v10,v8,v6,v4,v2
  71. stringRedisTemplate.opsForList().leftPushAll("list1", "v2", "v4", "v6", "v8", "v10");
  72. System.out.println("----------链表从左到右的顺序为v10,v8,v6,v4,v2----------------:");
  73. stringRedisTemplate.opsForList().range("list1", 0, stringRedisTemplate.opsForList().size("list1") - 1).forEach(s -> System.out.println(s));
  74. //从左到右顺序为v1,v2,v3,v4,v5,v6
  75. stringRedisTemplate.opsForList().rightPushAll("list2", "v1", "v2", "v3", "v4", "v5", "v6");
  76. System.out.println("----------从左到右顺序为v1,v2,v3,v4,v5,v6----------------:");
  77. stringRedisTemplate.opsForList().range("list2", 0, stringRedisTemplate.opsForList().size("list2") - 1).forEach(s -> System.out.println(s));
  78. // 绑定list2链表操作
  79. BoundListOperations listOps = stringRedisTemplate.boundListOps("list2");
  80. //从右边弹出一个成员
  81. String result1 = (String)listOps.rightPop();
  82. System.out.println("----------从右边弹出一个成员----------------: " + result1);
  83. listOps.range(0, listOps.size() - 1).forEach(s -> System.out.println(s));
  84. //获取定位元素,redis从0开始运算
  85. String result2 = (String)listOps.index(1);
  86. System.out.println("----------获取定位元素,redis从0开始运算----------------: " + result2);
  87. listOps.range(0, listOps.size() - 1).forEach(s -> System.out.println(s));
  88. //从左边插入链表
  89. listOps.leftPush("v0");
  90. System.out.println("----------从左边插入链表----------------: " + "v0");
  91. listOps.range(0, listOps.size() - 1).forEach(s -> System.out.println(s));
  92. //链表长度
  93. Long size = listOps.size();
  94. //求链表下标区间成员,整个链表下标范围为0到size-1,这里不取最后一个元素
  95. List elements = listOps.range(0, size - 2);
  96. System.out.println("----------求链表下标区间成员0->size-2 ----------------: " + "v0");
  97. elements.forEach(s -> System.out.println(s));
  98. System.out.println("集合Set示例-------------------------------------------------------");
  99. //set
  100. //请注意,这里v1重复两次,因为集合不允许重复,所以只是插入5个成员到集合中
  101. stringRedisTemplate.opsForSet().add("set1", "v1", "v1", "v2", "v3", "v4", "v5");
  102. stringRedisTemplate.opsForSet().add("set2", "v2", "v4", "v6", "v8");
  103. //绑定set1集合操作
  104. BoundSetOperations setOps = stringRedisTemplate.boundSetOps("set1");
  105. //增加两个元素
  106. setOps.add("v6", "v7");
  107. //删除两个元素
  108. setOps.remove("v1", "v7");
  109. //返回所有元素
  110. Set set1 = setOps.members();
  111. // 成员数
  112. size = setOps.size();
  113. //求交集
  114. Set inner = setOps.intersect("set2");
  115. //求交集并且用新集合inter保存
  116. setOps.intersectAndStore("set2", "inner");
  117. //求差集
  118. Set diff = setOps.diff("set2");
  119. //求差集,并且用新集合diff保存
  120. setOps.diffAndStore("set2", "diff");
  121. //求并集
  122. Set union = setOps.union("set2");
  123. //求并集并且用新集合union保存
  124. setOps.unionAndStore("set2", "union");
  125. //ZSET
  126. Set<ZSetOperations.TypedTuple<String>> typedTupleSet = new HashSet<>();
  127. for (int i = 1; i <= 9; i++) {
  128. //分数
  129. double score = i * 0.1;
  130. //创建一个TypedTuple对象,存入值和分数
  131. ZSetOperations.TypedTuple<String> typedTuple = new DefaultTypedTuple<String>("value" + i, score);
  132. typedTupleSet.add(typedTuple);
  133. }
  134. //往有序集合插入元素
  135. stringRedisTemplate.opsForZSet().add("zset1", typedTupleSet);
  136. //绑定zset1有序集合操作
  137. BoundZSetOperations zsetOps = stringRedisTemplate.boundZSetOps("zset1");
  138. System.out.println("------------init----------------");
  139. zsetOps.rangeWithScores(0, zsetOps.size() - 1).forEach(new Consumer() {
  140. @Override
  141. public void accept(Object t) {
  142. ZSetOperations.TypedTuple<String> s = (ZSetOperations.TypedTuple)t;
  143. System.out.println(s.getValue() + " : " + s.getScore());
  144. }
  145. });
  146. //增加一个元素
  147. zsetOps.add("value10", 0.26);
  148. System.out.println("------------增加一个元素 value10----------------");
  149. zsetOps.rangeWithScores(0, zsetOps.size() - 1).forEach(new Consumer() {
  150. @Override
  151. public void accept(Object t) {
  152. ZSetOperations.TypedTuple<String> s = (ZSetOperations.TypedTuple)t;
  153. System.out.println(s.getValue() + " : " + s.getScore());
  154. }
  155. });
  156. // 获得range 1---6
  157. Set<String> setRange = zsetOps.range(1, 6);
  158. System.out.println("------------获得range 1---6---------------");
  159. Iterator itor = setRange.iterator();
  160. if (itor.hasNext()) {
  161. String s = (String)itor.next();
  162. System.out.println(s);
  163. }
  164. //按分数排序获得有序集合
  165. Set<String> setScore = zsetOps.rangeByScore(0.2, 0.6);
  166. System.out.println("------------按分数排序获得有序集合 (0.2, 0.6)---------------");
  167. Iterator itor2 = setScore.iterator();
  168. if (itor.hasNext()) {
  169. String s = (String)itor.next();
  170. System.out.println(s);
  171. }
  172. //自定义范围
  173. RedisZSetCommands.Range range = new RedisZSetCommands.Range();
  174. range.gt("value3");//大于value3
  175. // range.gte("value3");//大于等于value3
  176. // range.lt("value8");//小于value8
  177. range.lte("value8");//小于等于value8
  178. //按值排序,请注意这个排序是按字符串排序
  179. Set<String> setLex = zsetOps.rangeByLex(range);
  180. System.out.println("------------自定义范围 (value3, value8)---------------");
  181. Iterator itor3 = setLex.iterator();
  182. if (itor.hasNext()) {
  183. String s = (String)itor.next();
  184. System.out.println(s);
  185. }
  186. //删除元素
  187. zsetOps.remove("value9", "value2");
  188. System.out.println("------------删除元素 value9, value2---------------");
  189. zsetOps.rangeWithScores(0, zsetOps.size() - 1).forEach(new Consumer() {
  190. @Override
  191. public void accept(Object t) {
  192. ZSetOperations.TypedTuple<String> s = (ZSetOperations.TypedTuple)t;
  193. System.out.println(s.getValue() + " : " + s.getScore());
  194. }
  195. });
  196. //求分数
  197. Double score = zsetOps.score("value8");
  198. System.out.println("-----------求分数 value8---------------:" + score);
  199. //在下标区间下,按分数排序,同时返回value和score
  200. Set<ZSetOperations.TypedTuple<String>> rangeSet = zsetOps.rangeWithScores(1, 6);
  201. System.out.println("-----------在下标区间下,按分数排序 (1, 6)---------------");
  202. rangeSet.forEach(new Consumer() {
  203. @Override
  204. public void accept(Object t) {
  205. ZSetOperations.TypedTuple<String> s = (ZSetOperations.TypedTuple)t;
  206. System.out.println(s.getValue() + " : " + s.getScore());
  207. }
  208. });
  209. //在分数区间下,按分数排序,同时返回value和score
  210. Set<ZSetOperations.TypedTuple<String>> scoreSet = zsetOps.rangeByScoreWithScores(0.1, 0.6);
  211. System.out.println("-----------在分数区间下,按分数排序 (0.1, 0.6)---------------");
  212. scoreSet.forEach(new Consumer() {
  213. @Override
  214. public void accept(Object t) {
  215. ZSetOperations.TypedTuple<String> s = (ZSetOperations.TypedTuple)t;
  216. System.out.println(s.getValue() + " : " + s.getScore());
  217. }
  218. });
  219. //按从大到小排序
  220. Set<String> reverseSet = zsetOps.reverseRange(0, zsetOps.size() - 1);
  221. System.out.println("-----------按从大到小排序---------------");
  222. reverseSet.forEach(s -> System.out.println(s));
  223. System.out.println("redis开启事务--------------------------");
  224. redisTemplate.opsForValue().set("key1", "value1");
  225. List list = (List)redisTemplate.execute((RedisOperations operations) -> {
  226. //设置要监控的Key
  227. operations.watch("key1");
  228. //开启事务。在exec命令执行前,全部都只是进入队列
  229. operations.multi();
  230. operations.opsForValue().set("key2", "value2");
  231. //获取值为null,因为redis只是把命令放入队列
  232. Object value2 = operations.opsForValue().get("key2");
  233. System.out.println("命令在队列中,所以key2为null【" + value2 + "】");
  234. operations.opsForValue().set("key3", "value3");
  235. System.out.println("命令在队列中,所以key3为null【" + value2 + "】");
  236. //执行exec命令,将先判断key1是否在监控后被修改过,如果是则不执行事务,否则就执行事务
  237. return operations.exec();
  238. });
  239. System.out.println("redis流水线--------------------------");
  240. Long start = System.currentTimeMillis();
  241. List list = redisTemplate.executePipelined((RedisOperations operations) -> {
  242. for (int i = 1; i <= 100000; i++) {
  243. operations.opsForValue().set("pipeline_" + i, "value" + i);
  244. String value = (String)operations.opsForValue().get("pipeline_" + i);
  245. if (i == 100000) {
  246. System.out.println("命令在队列中,所以值为null【" + value + "】");
  247. }
  248. }
  249. return null;
  250. });
  251. Long end = System.currentTimeMillis();
  252. System.out.println("耗时: " + (end - start) + "毫秒");
  253. return "";
  254. }
  255. }

4.6 运行示例

右键 RedisApplication 选择 Run RedisApplication 在浏览器中输入 http://localhost:8080/redis

本项目源码下载


参考

https://www.cnblogs.com/maria-ld/p/10010219.html

https://blog.csdn.net/Sadlay/article/details/83821629

Spring Boot 2.x 缓存应用 Redis注解与非注解方式入门教程的更多相关文章

  1. Spring Boot移除内嵌Tomcat,使用非web方式启动

    前言:当我们使用Spring Boot编写了一个批处理应用程序,该程序只是用于后台跑批数据,此时不需要内嵌的tomcat,简化启动方式使用非web方式启动项目,步骤如下: 1.在pom.xml文件中去 ...

  2. Spring Boot中的缓存支持(一)注解配置与EhCache使用

    Spring Boot中的缓存支持(一)注解配置与EhCache使用 随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决 ...

  3. Spring Boot 自带缓存及结合 Redis 使用

    本文测试环境: Spring Boot 2.1.4.RELEASE + Redis 5.0.4 + CentOS 7 自带缓存 如果没有使用缓存中间件,Spring Boot 会使用默认的缓存,我们只 ...

  4. Spring Boot中使用缓存

    Spring Boot中使用缓存 随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一. 原始的使 ...

  5. spring(三、spring中的eheche缓存、redis使用)

    spring(三.spring中的eheche缓存.redis使用) 本文主要介绍为什么要构建ehcache+redis两级缓存?以及在实战中如何实现?思考如何配置缓存策略更合适?这样的方案可能遗留什 ...

  6. 阿里P7级教你如何在Spring Boot应用程序中使用Redis

    在Spring Boot应用程序中使用Redis缓存的步骤: 1.要获得Redis连接,我们可以使用Lettuce或Jedis客户端库,Spring Boot 2.0启动程序spring-boot-s ...

  7. Spring Boot 集成 Ehcache 缓存,三步搞定!

    作者:谭朝红 www.ramostear.com/articles/spring_boot_ehcache.html 本次内容主要介绍基于Ehcache 3.0来快速实现Spring Boot应用程序 ...

  8. 基于Spring Cache实现二级缓存(Caffeine+Redis)

    一.聊聊什么是硬编码使用缓存? 在学习Spring Cache之前,笔者经常会硬编码的方式使用缓存. 我们来举个实际中的例子,为了提升用户信息的查询效率,我们对用户信息使用了缓存,示例代码如下: @A ...

  9. spring boot guava cache 缓存学习

    http://blog.csdn.net/hy245120020/article/details/78065676 ****************************************** ...

随机推荐

  1. python接口自动化之用HTMLTestRunner生成html测试报告

    [第一步]:引入HTMLTestRunner包 1.下载HTMLTestRunner,下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html ...

  2. 2.6.1 XML配置:创建XML文件

    (1) 工程名右击---New--file  --  newfile窗口中:filename中输入testng.xml testng.xml 文件中打开后,切换到source 标签中.进行编辑. 内容 ...

  3. html 未选择复选框不上传

    问题 之前就遇到类似的问题,在一个列表中,如果有复选框,并且不选中 会导致这个复选框不上传,导致后台接收不到复选框数据 解决方法我想到的就是 <td> <input type=&qu ...

  4. EQ实现

    原理参考: https://www.cnblogs.com/fellow1988/p/9189338.html https://www.cnblogs.com/fellow1988/p/9136346 ...

  5. php基础扫盲

    .

  6. Mysql SQL CAST()函数

    (1).CAST()函数的参数是一个表达式,它包括用AS关键字分隔的源值和目标数据类型.以下例子用于将文本字符串'12'转换为整型: SELECT CAST('12' AS int) (2).返回值是 ...

  7. 集群Session一致性和同步问题

    一. 何为session 用户使用网站的服务,基本上需要浏览器和web服务器进行多次交互,web服务器如何知道哪些请求是来自哪个会话的? 具体方式为:在会话开始时,分配一个唯一的会话标识(sessio ...

  8. Javascript模块化编程之CommonJS,AMD,CMD,UMD模块加载规范详解

    JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发?     模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问 题进行系 ...

  9. Django 无法同步数据库model相应字段问题

    前言:今天也是充满bug的一天,脸上笑嘻嘻....(继续,讲文明,懂礼貌) 1,问题描述,models中的字段设置的是浮点型,但是输出的结果总是int()类型 models average_score ...

  10. (原创)SoapUI学习(2)- POST请求

    1.新建Project,右键Projects->New REST Project,可以不填直接点击OK,之后通过rename重命名.(如果这里添加URL,则直接达到第三步的图) 2.右键新建的工 ...