Spring Boot 入门之缓存和 NoSQL 篇(四)

原文地址:Spring Boot 入门之缓存和 NoSQL 篇(四)
博客地址:http://www.extlight.com

一、前言

当系统的访问量增大时,相应的数据库的性能就逐渐下降。但是,大多数请求都是在重复的获取相同的数据,如果使用缓存,将结果数据放入其中可以很大程度上减轻数据库的负担,提升系统的响应速度。

本篇将介绍 Spring Boot 中缓存和 NoSQL 的使用。上篇文章《Spring Boot 入门之持久层篇(三)》。

二、整合缓存

Spring Boot 针对不同的缓存技术实现了不同的封装,本篇主要介绍 EhCache 和 Redis 缓存。

Spring Boot 提供了以下几个注解实现声明式缓存:

注解说明
@EnableCaching开启缓存功能,放在配置类或启动类上
@CacheConfig缓存配置,设置缓存名称
@Cacheable执行方法前先查询缓存是否有数据。有则直接返回缓存数据;否则查询数据再将数据放入缓存
@CachePut执行新增或更新方法后,将数据放入缓存中
@CacheEvict清除缓存
@Caching将多个缓存操作重新组合到一个方法中

2.1 EhCache 缓存

2.1.1 添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId>
</dependency>

2.1.2 添加配置

1)在 src/main/resources 目录下创建 ehcache.xml 文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"><!-- 磁盘缓存位置 --><diskStore path="java.io.tmpdir/ehcache"/><!-- 默认缓存 --><defaultCachemaxEntriesLocalHeap="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"maxEntriesLocalDisk="10000000"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"><persistence strategy="localTempSwap"/></defaultCache><!-- 自定义缓存 --><cache name="department"maxElementsInMemory="1000"eternal="false"timeToIdleSeconds="50"timeToLiveSeconds="50"overflowToDisk="false"memoryStoreEvictionPolicy="LRU"/>
</ehcache>

说明:

name:Cache 的唯一标识
maxElementsInMemory:内存中允许存储的最大的元素个数
maxElementsOnDisk:硬盘最大缓存个数,0代表无限个
clearOnFlush:内存数量最大时是否清除
eternal:缓存对象是否永久有效,如果是,超时设置将被忽略
overflowToDisk:内存不足(超过 maxElementsInMemory)时,是否启用磁盘缓存
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大
timeToLiveSeconds:缓存数据的生存时间(TTL),也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间
diskPersistent:是否将缓存数据持久化到磁盘上,如果为 true,JVM 重启数据依然存在。默认值是false
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒
memoryStoreEvictionPolicy:当达到 maxElementsInMemory 限制时,Ehcache 将根据指定策略清除内存。默认为 LRU(最近最少使用),其他策略有 FIFO(先进先出),LFU(较少使用)

2)application.properties :

# 缓存类型(ehcache、redis)
spring.cache.type=ehcache# ehcache 配置文件
spring.cache.ehcache.config=classpath:ehcache.xml# 打印日志,查看 sql
logging.level.com.light.springboot=DEBUG

2.1.3 编码

在持久层篇的基础上,结合 Mybatis 测试:

Service 层:

@CacheConfig(cacheNames = "department")
@Service
public class DepartmentService {@Autowiredprivate DepartmentMapper departmentMapper;@CachePut(key = "#department.id")public Department save(Department department) {System.out.println("保存 id=" + department.getId() + " 的数据");this.departmentMapper.insert(department);return department;}@CachePut(key = "#department.id")public Department update(Department department) {System.out.println("修改 id=" + department.getId() + " 的数据");this.departmentMapper.update(department);return department;}@Cacheable(key = "#id")public Department getDepartmentById(Integer id) {System.out.println("获取 id=" + id + " 的数据");Department department = this.departmentMapper.getById(id);return department;}@CacheEvict(key = "#id")public void delete(Integer id) {System.out.println("删除 id=" + id + " 的数据");this.departmentMapper.deleteById(id);}
}

控制层:

@Controller
@RequestMapping("department")
@ResponseBody
public class DepartmentController {@Autowiredprivate DepartmentService departmentService;@RequestMapping("save")public Map<String,Object> save(Department department) {this.departmentService.save(department);Map<String,Object> map = new HashMap<String,Object>();map.put("code", "200");map.put("msg", "保存成功");return map;}@RequestMapping("get/{id}")public Map<String,Object> get(@PathVariable("id") Integer id) {Department department = this.departmentService.getDepartmentById(id);Map<String,Object> map = new HashMap<String,Object>();map.put("code", "200");map.put("msg", "获取成功");map.put("data", department);return map;}@RequestMapping("update")public Map<String,Object> update(Department department) {this.departmentService.update(department);Map<String,Object> map = new HashMap<String,Object>();map.put("code", "200");map.put("msg", "修改成功");return map;}@RequestMapping("delete/{id}")public Map<String,Object> delete(@PathVariable("id") Integer id) {this.departmentService.delete(id);Map<String,Object> map = new HashMap<String,Object>();map.put("code", "200");map.put("msg", "删除成功");return map;}
}

启动类:

添加 @EnableCaching 注解,开启缓存功能。

@EnableCaching
@SpringBootApplication
public class SpringbootNosqlApplication {public static void main(String[] args) {SpringApplication.run(SpringbootNosqlApplication.class, args);}
}

2.1.4 测试说明

1) 发起保存请求:

保存 id=2 的数据
2017-12-06 14:50:48.800 DEBUG 680 --- [nio-8081-exec-7] c.l.s.dao.DepartmentMapper.insert        : ==>  Preparing: insert into department(id,name,descr) values(?,?,?) 
2017-12-06 14:50:48.801 DEBUG 680 --- [nio-8081-exec-7] c.l.s.dao.DepartmentMapper.insert        : ==> Parameters: 2(Integer), Ehcache 部门(String), Ehcache(String)
2017-12-06 14:50:48.868 DEBUG 680 --- [nio-8081-exec-7] c.l.s.dao.DepartmentMapper.insert        : <==    Updates: 1

2) 保存成功后,立刻发起查询请求,没有日志打印,但返回对象数据,说明数据是从缓存中获取。

3) 发起修改请求:

修改 id=2 的数据
2017-12-06 14:51:16.588 DEBUG 680 --- [nio-8081-exec-8] c.l.s.dao.DepartmentMapper.update        : ==>  Preparing: update department set name = ? , descr = ? where id = ? 
2017-12-06 14:51:16.589 DEBUG 680 --- [nio-8081-exec-8] c.l.s.dao.DepartmentMapper.update        : ==> Parameters: Ehcache 部门2(String), Ehcache2(String), 2(Integer)
2017-12-06 14:51:16.657 DEBUG 680 --- [nio-8081-exec-8] c.l.s.dao.DepartmentMapper.update        : <==    Updates: 1

4) 修改成功后,立刻发起查询请求,没有日志打印,但返回修改后的对象数据,说明缓存中的数据已经同步。

5) 发起删除请求:

删除 id=2 的数据
2017-12-06 14:52:07.572 DEBUG 680 --- [nio-8081-exec-1] c.l.s.dao.DepartmentMapper.deleteById    : ==>  Preparing: delete from department where id = ? 
2017-12-06 14:52:07.572 DEBUG 680 --- [nio-8081-exec-1] c.l.s.dao.DepartmentMapper.deleteById    : ==> Parameters: 2(Integer)
2017-12-06 14:52:07.613 DEBUG 680 --- [nio-8081-exec-1] c.l.s.dao.DepartmentMapper.deleteById    : <==    Updates: 1

6) 删除成功后,立刻发起查询请求,控制台打印 sql 语句,说明缓存数据被删除,需要查询数据库。

获取 id=2 的数据
2017-12-06 14:52:40.324 DEBUG 680 --- [nio-8081-exec-3] c.l.s.dao.DepartmentMapper.getById       : ==>  Preparing: select id,name,descr from department where id = ? 
2017-12-06 14:52:40.325 DEBUG 680 --- [nio-8081-exec-3] c.l.s.dao.DepartmentMapper.getById       : ==> Parameters: 2(Integer)
2017-12-06 14:52:40.328 DEBUG 680 --- [nio-8081-exec-3] c.l.s.dao.DepartmentMapper.getById       : <==      Total: 0

2.2 Redis 缓存

2.2.1 添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.2.2 添加配置

application.properties :

# redis 配置
spring.redis.host=192.168.2.11
spring.redis.port=6379
spring.redis.password=redis123
# 缓存过期时间,单位毫秒
spring.cache.redis.time-to-live=60000# 缓存类型(ehcache、redis)
spring.cache.type=redis# 打印日志,查看 sql
logging.level.com.light.springboot=DEBUG

注意:spring.cache.type=redis,缓存类型设置成 redis。

完成上边 2 个步骤后,其他步骤与测试 Ehcache 时的步骤一致。

测试结果也一致,此处省略。

三、整合 Redis

上一个小节其实已经介绍了 Spring Boot 整合 Redis 的内容。

在添加 redis 依赖包启动项目后,Spring Boot 会自动配置 RedisCacheManger 和 RedisTemplate 的 Bean。如果开发者不想使用 Spring Boot 写好的 Redis 缓存,而是想使用其 API 自己实现缓存功能、消息队列或分布式锁之类的需求时,可以继续往下浏览。

Spring Data Redis 为我们提供 RedisTemplate 和 StringRedisTemplate 两个模板进行数据操作,它们主要 的访问方法如下:

方法说明
opsForValue()操作简单属性的数据
opsForList()操作含有 list 的数据
opsForSet()操作含有 set 的数据
opsForZSet()操作含有 zset 的数据
opsForHash()操作含有 hash 的数据

3.1 添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

3.2 配置连接

spring.redis.host=192.168.2.11
spring.redis.port=6379
spring.redis.password=redis123

3.3 编码

@Component
public class RedisDao {@Autowiredprivate StringRedisTemplate stringRedisTemplate;public void set(String key, String value) {this.stringRedisTemplate.opsForValue().set(key, value);}public String get(String key) {return this.stringRedisTemplate.opsForValue().get(key);}public void delete(String key) {this.stringRedisTemplate.delete(key);}
}

3.4 测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisDaoTest {@Autowiredprivate RedisDao redisDao;@Testpublic void testSet() {String key = "name";String value = "zhangsan";this.redisDao.set(key, value);}@Testpublic void testGet() {String key = "name";String value = this.redisDao.get(key);System.out.println(value);}@Testpublic void testDelete() {String key = "name";this.redisDao.delete(key);}
}

测试结果省略...

四、整合 MongoDB

Spring Data MongoDB 提供了 MongoTemplate 模板 和 Repository 让开发者进行数据访问。

4.1 添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

4.2 配置连接

spring.data.mongodb.host=192.168.2.31
spring.data.mongodb.port=27017
spring.data.mongodb.database=test

4.3 编码

4.3.1 使用 MongoTemplate

@Component
public class MongodbDao {@Autowiredprivate MongoTemplate mongoTemplate;public void insert(Department department) {this.mongoTemplate.insert(department);}public void deleteById(int id) {Criteria criteria = Criteria.where("id").is(id);Query query = new Query(criteria);this.mongoTemplate.remove(query, Department.class);}public void update(Department department) {Criteria criteria = Criteria.where("id").is(department.getId());Query query = new Query(criteria);Update update = new Update();update.set("descr", department.getDescr());this.mongoTemplate.updateMulti(query, update, Department.class);}public Department getById(int id) {Criteria criteria = Criteria.where("id").is(id);Query query = new Query(criteria);return this.mongoTemplate.findOne(query, Department.class);}public List<Department> getAll() {List<Department> userList = this.mongoTemplate.findAll(Department.class);return userList;}}

4.3.2 使用 Repository

public interface DepartmentRepository extends MongoRepository<Department, Integer> {}

测试方式与 Redis 测试大同小异,测试结果省略...

五、源码下载

  • Spring Boot 入门之缓存和 NoSQL 篇测试源码

六、参考资料

  • 官方文档
  • ehcache入门基础示例
  • ML-BLOG (读者可参考笔者的开源博客源码学习)

转载于:https://www.cnblogs.com/moonlightL/p/8066033.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/267878.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Silverlight 2.5D RPG游戏技巧与特效处理:(七)动画特写

Silverlight中的HLSL不仅适用于场景与动画渲染&#xff0c;对于游戏中的角色&#xff0c;我们同样可以利用它制作动画特写。较常见的比如角色传送时的淡入淡出、扭曲变形、幻化呈现等切换动画&#xff0c;当然还有例如角色被DeBuff时所表现出来的放大缩小以及虚弱时的不规则体形…

mysql myisampack_每天进步一点达——MySQL——myisampack

一、简单介绍myisampack是一个压缩使用MyISAM引擎表的工具&#xff0c;通常会压缩40%~70%,当须要訪问数据。server会将所须要的信息读入到内存中。所以当訪问详细记录时&#xff0c;性能会更好&#xff0c;由于仅仅须要解压一条记录MySQL使用mmap()对变哦进行压缩映射&#xff…

实现搜索功能

准备视图函数search()修改base.html 中搜索输入框所在的<form action"{{ url_for(search) }}" method"get"> <input name"q" type"text" placeholder"请输入关键字">完成视图函数search()获取搜索关键字q re…

日本核辐射究竟有多可怕?

你应该已经知道了由于日本海啸引起的核电站事故。大量无辜的人在得知放射性原料&#xff08;物质&#xff09;泄露的消息之后&#xff0c;都感到害怕和恐慌。 而让你保持冷静的唯一方法&#xff0c;就是掌握正确的科学知识。 有关核辐射的知识 这里有一些信息&#xff1a;   …

mysql下载安装及配置_mysql的下载,安装和配置

顺道向大家介绍一下mysql的安装和配置&#xff0c;mysql数据库应该说是现在整个互联网行业最流行的数据库了&#xff0c;简单易用1.下载&#xff0c;大家可以去官网下载最新的mysql版本&#xff0c;地址&#xff1a;http://dev.mysql.com/downloads/mysql/5.6.html&#xff0c;…

[svc]gns3模拟器及探讨几个bgp问题

模拟器 链接&#xff1a;https://pan.baidu.com/s/1geMcmND 密码&#xff1a;7iir gns0.8.6的版本好用 思科的这个iso好用: c3660-js2-mz.124-21a.bin C2691-AD.BIN(这个也很ok,但是这两个支持的hash算法较少) ctrlshit6 停止命令 R1(config)#crypto isakmp policy 10 R1(confi…

算法导论8.3-4习题解答(基数排序)

CLRS 8.3-4 : 说明如何在O(n)时间内&#xff0c;对0到n^2 - 1之间的n个整数进行排序。 算法思想&#xff1a; 1.把这n个数看成n进制数&#xff0c;那么每个数只有两位&#xff0c;因而循环只需两次 2.调用通用的基数排序(在这写着&#xff0c;留着以后用) 在此题中&#xff0c…

mysql open-files-limit_在mysql 5.5中更改open-files-limit

我在使用open-files-limit参数在Ubuntu 12.04上运行mysql 5.5时遇到问题.我最近注意到由于1024限制导致的一些问题,实际上主系统限制设置为1024,所以我使用以下内容修改了/etc/security/limits.conf&#xff1a;* soft nofile 32000* hard nofile 32000root soft nofile 32000r…

Lucas定理

定义 对于任意质数p $\Huge C_m^n\equiv C_{\biggl\lfloor\frac{m}{p}\biggr\rfloor}^{\biggl\lfloor\frac{n}{p}\biggr\rfloor}*C_{m\ mod\ p}^{n\ mod\ p}\ \ (MOD\ p)$ 证明 对于任意质数p都有 $\huge C_p^i\equiv0\ MOD\ p(i\not 0\&\&i\notp)$ 通过二项式定理&…

Reverse-engineer Source Code into UML Diagrams

今天同事需要反向生成类图&#xff0c;用PowerDesigner 转了一份&#xff0c;不甚满意&#xff0c;在网上逛了逛&#xff0c;发现在这篇文章挺不错。 I have been on several teams where we studiously designed UML diagrams at the beginning of the project. As the projec…

mysql数据库优先_MySQL数据库配置文件之优先级

1.数据库配置方式1)预编译cmake . -DCMAKE_INSTALL_PREFIX/application/mysql-5.7.20 -DMYSQL_DATADIR/application/mysql-5.7.20/data -DMYSQL_UNIX_ADDR/application/mysql-5.7.20/tmp/mysql.sock -DDEFAULT_CHARSETutf8 -DDEFAULT_COLLATIONutf8_general_ci -DWITH_EXTRA_CH…

What's the best way to get rid of get parameters from url string?

https://stackoverflow.com/questions/27267111/whats-the-best-way-to-get-rid-of-get-parameters-from-url-string转载于:https://www.cnblogs.com/jianglijs/p/8081564.html

wince版本ffmpeg的编译 第四篇

4. 编译faac#cd faac-1.28#dos2unix bootstrap //这里是要转换编码格式的&#xff0c;不然configure过不去#dos2unix configure.in#dos2unix Makefile.in#chmod x bootstrap#./bootstrap#./configure –prefix/wm –enable-static –hostarm-mingw32ce –without-mp4v2#make …

R语言数据去重

R语言常用的去重命令有unique duplicated unique主要是返回一个把重复元素或行给删除的向量、数据框或数组 > x <- c(3:5, 11:8, 8 0:5)> x [1] 3 4 5 11 10 9 8 8 9 10 11 12 13> unique(x)[1] 3 4 5 11 10 9 8 12 13> unique(x, fromLast TRUE)…

postman测试带权限接口_接口测试工具:postman

一、postman简介一般简单的接口测试我们可以直接在浏览器里面进行调试&#xff0c;但是涉及到一些要权限设置的就无法操作了&#xff0c;因此我们需接口测试的相关工具&#xff1b;Postman 是一个接口测试和 http 请求的工具。官网下载地址&#xff1a;https://www.getpostman…

记录在Spring-Boot中使用Fegin调用RESTfull的PATCH方法设置

使用了ZooKeeper&#xff0c;设置 spring.cloud.zookeeper.dependency.headers.enabledfalse 参考&#xff1a; https://github.com/spring-cloud/spring-cloud-netflix/issues/2550#issuecomment-353230054 http://blog.csdn.net/menggudaoke/article/details/77884674转载于:…

mysql getcolumnname_jdbc-mysql基础 ResultSetMetaData getColumnName getColumnLabel 得到列的名字和别名...

礼悟&#xff1a;好好学习多思考&#xff0c;尊师重道存感恩。叶见寻根三二一&#xff0c;江河湖海同一体。虚怀若谷良心主&#xff0c;愿行无悔给最苦。读书锻炼强身心&#xff0c;诚劝且行且珍惜。数据、数据&#xff0c;命根就在数据。云计算、AI等技术&#xff0c;都是以数…

AutoLISP 绘制表情图案

AutoLISP 绘制表情图案&#xff0c;喜怒哀乐表情&#xff0c;代码如下。 (defun c:test() (setvar "cmdecho" 0) (princ "\n选取圆或[ENTER]自定圆心半径&#xff1a;") (setq en (entsel)) (if (null en) (progn (setq srr (getvar &qu…

QT的组合键

https://www.cnblogs.com/Jace-Lee/p/5859293.html 转载于:https://www.cnblogs.com/132818Creator/p/8087536.html

python与7无关的数输出格式第一行为所有与7无关的数_70 道 NumPy 测试题

(给Python开发者加星标&#xff0c;提升Python技能)来源&#xff1a;机器之心本 NumPy 测试题旨在为大家提供参考&#xff0c;让大家可以使用 NumPy 的更多功能。问题共分为四个等级&#xff0c;L1 最简单&#xff0c;难度依次增加。机器之心对该测试题进行了编译介绍&#xff…