springboot笔记—缓存配置redis和Mongdb

缓存配置

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

本篇将介绍 Spring Boot 中缓存和 NoSQL 的使用。

整合缓存

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

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

|

注解

|

说明

|
| --- | --- |
|

@EnableCaching

|

开启缓存功能,放在配置类或启动类上

|
|

@CacheConfig

|

缓存配置,设置缓存名称

|
|

@Cacheable

|

执行方法前先查询缓存是否有数据。有则直接返回缓存数据;否则查询数据再将数据放入缓存

|
|

@CachePut

|

执行新增或更新方法后,将数据放入缓存中

|
|

@CacheEvict

|

清除缓存

|
|

@Caching

|

将多个缓存操作重新组合到一个方法中

|

EhCache 缓存

添加依赖

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-cache</artifactId>

</dependency>

<dependency>

<groupId>net.sf.ehcache</groupId>

<artifactId>ehcache</artifactId>

</dependency>

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

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="ehcache.xsd">

<cache name="department"

       eternal="false"

       maxEntriesLocalHeap="0"

       timeToIdleSeconds="50">

</cache>

</ehcache>

application.properties :

spring.cache.type=ehcache

spring.cache.ehcache.config=classpath:ehcache.xml

打印日志,查看 sql

logging.level.com.light.springboot=DEBUG

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

Service 层:

@CacheConfig(cacheNames = "department")

@Service

public class DepartmentService {

@Autowired

private 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 {

@Autowired

private 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);

}

}

测试说明

发送保存接口

[图片上传中...(image-49dfa3-1524634441874-7)]

发送查询接口

[图片上传中...(image-a3cef6-1524634441874-6)]

再次发送查询接口

[图片上传中...(image-d8f1c8-1524634441874-5)]

说明数据是从缓存中获取。

发起修改请求:

[图片上传中...(image-dce6b1-1524634441874-4)]

发送查询接口

[图片上传中...(image-826dd4-1524634441874-3)]

没有sql日志打印,但返回修改后的对象数据,说明缓存中的数据已经同步。

发起删除请求:

[图片上传中...(image-210460-1524634441874-2)]

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

[图片上传中...(image-46c621-1524634441874-1)]

Redis 缓存

添加依赖

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-redis</artifactId>

</dependency>

添加配置

application.properties :

spring.redis.host=192.168.1.254

spring.redis.port=6379

spring.redis.password=123456

spring.redis.database=6

spring.redis.pool.max-active=8

spring.redis.pool.max-idle=8

spring.redis.pool.max-wait=-1

spring.redis.pool.min-idle=0

spring.redis.timeout=0

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

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

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

整合 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 的数据

|

添加依赖

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-redis</artifactId>

</dependency>

配置连接

spring.redis.host=192.168.1.254

spring.redis.port=6379

spring.redis.password=123456

spring.redis.database=6

spring.redis.pool.max-active=8

spring.redis.pool.max-idle=8

spring.redis.pool.max-wait=-1

spring.redis.pool.min-idle=0

spring.redis.timeout=0

编码

@Component

public class RedisDao {

@Autowired

private 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);

}

}

测试

@RunWith(SpringRunner.class)

@SpringBootTest

public class RedisDaoTest {

@Autowired

private RedisDao redisDao;

@Test

public void testSet() {

    String key = "name";

    String value = "zhangsan";

    this.redisDao.set(key, value);

}

@Test

public void testGet() {

    String key = "name";

    String value = this.redisDao.get(key);

    System.out.println(value);

}

@Test

public void testDelete() {

    String key = "name";

    this.redisDao.delete(key);

}

}

测试结果

[图片上传中...(image-745fa0-1524634441874-0)]

整合 MongoDB

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

添加依赖

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-mongodb</artifactId>

</dependency>

配置连接

spring.data.mongodb.host=192.168.2.25

spring.data.mongodb.port=27017

spring.data.mongodb.database=test

编码

使用 MongoTemplate

@Component

public class MongodbDao {

@Autowired

private MongoTemplate mongoTemplate;

public void insert(User user) {

    this.mongoTemplate.insert(user);

}

public void deleteById(int id) {

    Criteria criteria = Criteria.where("id").is(id);

    Query query = new Query(criteria);

    this.mongoTemplate.remove(query, User.class);

}

public void update(User User) {

    Criteria criteria = Criteria.where("id").is(User.getId());

    Query query = new Query(criteria);

    Update update = new Update();

    update.set("password", User.getPassword());

    this.mongoTemplate.updateMulti(query, update, User.class);

}

public User getById(int id) {

    Criteria criteria = Criteria.where("id").is(id);

    Query query = new Query(criteria);

    return this.mongoTemplate.findOne(query, User.class);

}

public List<User> getAll() {

    List<User> userList = this.mongoTemplate.findAll(User.class);

    return userList;

}

}

使用 Repository

public interface UserRepository extends MongoRepository<User, Integer> {

}

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

参考资料

https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html 官方文档

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • 要加“m”说明是MB,否则就是KB了. -Xms:初始值 -Xmx:最大值 -Xmn:最小值 java -Xms8...
    dadong0505阅读 4,762评论 0 53
  • =========================================================...
    _灯火阑珊处阅读 2,359评论 0 3
  • spring官方文档:http://docs.spring.io/spring/docs/current/spri...
    牛马风情阅读 1,576评论 0 3
  • 缓存是最直接有效提升系统性能的手段之一。个人认为用好用对缓存是优秀程序员的必备基本素质。 本文结合实际开发经验,从...
    Java小生阅读 751评论 1 3
  • 这个世界就是这么奇妙,有人在菜场拼命算计,最后却所获不多;有人在菜场洗尽铅华,却赢得世人尊重。菜场小舞台,演绎的却...
    00后老干妈阅读 498评论 1 3