今天,我们继续讲SpringBoot整合Redis ,也就缓存,它将与我们的Springboot整合

Redis 简介

Redis 是当前比较热门的NOSQL系统之一,它是一个开源的使用ANSI c语言编写的
key-value 存储系统(区别于MySQL的二维表格的形式存储。)。

Memcache类似,但很大程度补偿了Memcache的不足。和Memcache一样,Redis数据都是缓存在计算机内存中,不同的是,Memcache只能将数据缓存到内存中,无法自动定期写入硬盘,这就表示,一断电或重启,内存清空,数据丢失。所以Memcache的应用场景适用于缓存无需持久化的数据。而Redis不同的是它会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,实现数据的持久化

特点

  • Redis读取的速度是110000次/s,写的速度是81000次/s
    原子 。
  • Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
    支持多种数据结构:string(字符串);list(列表);hash(哈希),set(集合);zset(有序集合)
  • 持久化,主从复制(集群)
  • 支持过期时间,支持事务,消息订阅。
  • 官方不支持window,但是又第三方版本。
好了,现在知道他是干什么来的 ,我开动吧,相信你也等急了

准备工作

本文使用 Linux 版本的 redis ,当然你也可以使用 Windows ,Windows的话,只需要点击


当然我们要复杂一点,不然写博客太没意思了,就以Linux版本为例

  • 1.Linux系统

  • 2.安装redis(也可以安装docker,然后再docker中装redis,本文章就直接用Linux安装redis做演示)

redis下载地址:http://download.redis.io/releases/redis-4.0.14.tar.gz

修改Redis,开启远程访问

默认Redis是不支持远程访问的 ,我们需要手动开启

找到redis中的redis.conf文件并编辑(在安装路径中找到)

vim ./redis.conf

找到bind 127.0.0.1并注释掉

  1. 默认127.0.0.1只能本地访问,注释掉即可ip访问

  2. 修改 protected-mode 属性值为no,注释掉并把保护模式禁用以后可以IP访问

  3. 修改daemonize属性将no 改为yes,将daemonize设置为yes即启动后台运行

  4. 开放6379端口

/sbin/iptables -I INPUT -p tcp --dport 6379 -j ACCEPT
  1. 最后一步,开启Redis
redis-server /myconf/redis.conf
  1. 测试连接 redis-server默认在/usr/local/bin路径下,redis.conf在redis的安装路径下
redis-cli -h 192.168.126.129 -p 6379

redis-cli -h redis服务器IP -p 6379 -a 密码(没有设置redis密码不要写空,否则报错)

Quick Start

第一步 : 加依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- mybatis 与 spring boot 2.x的整合包 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><!--mysql JDBC驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.39</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency></dependencies>

application.yml

下面是springboot的配置文件application.yml,配置redis(里面都有注释解释)

server:port: 8081#数据库连接
spring:datasource:url: jdbc:mysql://localhost:3306/mytest_springboot_cache?useUnicode=truedriver-class-name: com.mysql.jdbc.Driverusername: rootpassword: root## Redis 配置redis:## Redis数据库索引(默认为0)database: 0## Redis服务器地址host: 192.168.126.129## Redis服务器连接端口port: 6379## Redis服务器连接密码(默认为空)password:jedis:pool:## 连接池最大连接数(使用负值表示没有限制)#spring.redis.pool.max-active=8max-active: 8## 连接池最大阻塞等待时间(使用负值表示没有限制)#spring.redis.pool.max-wait=-1max-wait: -1## 连接池中的最大空闲连接#spring.redis.pool.max-idle=8max-idle: 8## 连接池中的最小空闲连接#spring.redis.pool.min-idle=0min-idle: 0## 连接超时时间(毫秒)timeout: 1200#将themilef的默认缓存禁用,热加载生效thymeleaf:cache: false#mybatis的下划线转驼峰配置configuration:map-underscore-to-camel-case: true#另外一种打印语句的方式log-impl: org.apache.ibatis.logging.stdout.StdOutImpl#打印sql时的语句
logging:level:com:acong:dao: debugfile: d:/logs/bsbdj.log

接着是实体类,这个比较简单就不多说了

package com.spiritmark.springbootstudytest.bean;import java.io.Serializable;/*** @author spiritmark* create 2019-09-18-22:32*/
public class User implements Serializable {private static final long serialVersionUID = 1L;private int uid;private String userName;private String passWord;private int salary;public int getUid() {return uid;}public void setUid(int uid) {this.uid = uid;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassWord() {return passWord;}public void setPassWord(String passWord) {this.passWord = passWord;}public int getSalary() {return salary;}public void setSalary(int salary) {this.salary = salary;}public User(int uid, String userName, String passWord, int salary) {super();this.uid = uid;this.userName = userName;this.passWord = passWord;this.salary = salary;}public User() {super();}
} 
Controller
package com.spiritmark.springbootstudytest.controller;import com.spiritmark.springbootstudytest.bean.User;
import com.spiritmark.springbootstudytest.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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author spiritmark* create 2019-09-18-22:36*/
@RestController
public class TestController {@Autowiredprivate UserService userService;@RequestMapping("/queryAll")public List<User> queryAll(){List<User> lists = userService.queryAll();return lists;}@RequestMapping("/findUserById")public Map<String, Object> findUserById(@RequestParam int id){User user = userService.findUserById(id);Map<String, Object> result = new HashMap<>();result.put("uid", user.getUid());result.put("uname", user.getUserName());result.put("pass", user.getPassWord());result.put("salary", user.getSalary());return result;}@RequestMapping("/updateUser")public String updateUser(){User user = new User();user.setUid(1);user.setUserName("cat");user.setPassWord("miaomiao");user.setSalary(4000);int result = userService.updateUser(user);if(result != 0){return "update user success";}return "fail";}@RequestMapping("/deleteUserById")public String deleteUserById(@RequestParam int id){int result = userService.deleteUserById(id);if(result != 0){return "delete success";}return "delete fail";}
}

之前都是学过的内容,下面是新增的 也就是Redis配置redistemplate序列化

package com.spiritmark.springbootstudytest.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
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.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;/*** @author spiritmark* create 2019-09-24-15:07*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {/*** 选择redis作为默认缓存工具* @param redisConnectionFactory* @return*//*@Bean//springboot 1.xxpublic CacheManager cacheManager(RedisTemplate redisTemplate) {RedisCacheManager rcm = new RedisCacheManager(redisTemplate);return rcm;}*/@Beanpublic CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)).cacheDefaults(redisCacheConfiguration).build();}/*** retemplate相关配置* @param factory* @return*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();// 配置连接工厂template.setConnectionFactory(factory);//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和publicom.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jacksonSeial.setObjectMapper(om);// 值采用json序列化template.setValueSerializer(jacksonSeial);//使用StringRedisSerializer来序列化和反序列化redis的key值template.setKeySerializer(new StringRedisSerializer());// 设置hash key 和value序列化模式template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(jacksonSeial);template.afterPropertiesSet();return template;}/*** 对hash类型的数据操作** @param redisTemplate* @return*/@Beanpublic HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {return redisTemplate.opsForHash();}/*** 对redis字符串类型数据操作** @param redisTemplate* @return*/@Beanpublic ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {return redisTemplate.opsForValue();}/*** 对链表类型的数据操作** @param redisTemplate* @return*/@Beanpublic ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {return redisTemplate.opsForList();}/*** 对无序集合类型的数据操作** @param redisTemplate* @return*/@Beanpublic SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {return redisTemplate.opsForSet();}/*** 对有序集合类型的数据操作** @param redisTemplate* @return*/@Beanpublic ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {return redisTemplate.opsForZSet();}
}
数据访问层

接着是Mapper持久层Dao,这里主要用注解写比较方便,也可以使用mybatis的xml配置文件写sql语句

package com.spiritmark.springbootstudytest.mapper;import com.spiritmark.springbootstudytest.bean.User;
import org.apache.ibatis.annotations.*;import java.util.List;/*** @author SpiritMark* create 2019-09-18-22:32*/
@Mapper
public interface UserDao {@Select("select * from user")List<User> queryAll();@Select("select * from user where uid = #{id}")User findUserById(int id);@Update("UPDATE USER SET username = CASE WHEN (#{userName} != NULL) AND (#{userName} != '') THEN #{userName},PASSWORD = CASE WHEN (#{passWord} != NULL) AND (#{passWord} != '') THEN #{passWord},salary = CASE WHEN (#{salary} != 0) THEN #{salary} WHERE uid = #{uid}")int updateUser(@Param("user") User user);@Delete("delete from user where uid = #{id}")int deleteUserById(int id);}

service层,这里主要是使用redis模板来写

业务逻辑层,就是重点讲 RedisTemplate

package com.spiritmark.springbootstudytest.service;import com.spiritmark.springbootstudytest.bean.User;
import com.spiritmark.springbootstudytest.mapper.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.concurrent.TimeUnit;/*** @author spiritmark* create 2019-09-18-22:33*/
@Service
public class UserService {@Autowiredprivate UserDao userDao;@Autowiredprivate RedisTemplate redisTemplate;public List<User> queryAll() {return userDao.queryAll();}/*** 获取用户策略:先从缓存中获取用户,没有则取数据表中 数据,再将数据写入缓存*/public User findUserById(int id) {String key = "user_" + id;ValueOperations<String, User> operations = redisTemplate.opsForValue();//判断redis中是否有键为key的缓存boolean hasKey = redisTemplate.hasKey(key);if (hasKey) {User user = operations.get(key);System.out.println("从缓存中获得数据:"+user.getUserName());System.out.println("------------------------------------");return user;} else {User user = userDao.findUserById(id);System.out.println("查询数据库获得数据:"+user.getUserName());System.out.println("------------------------------------");// 写入缓存operations.set(key, user, 5, TimeUnit.HOURS);return user;}}/*** 更新用户策略:先更新数据表,成功之后,删除原来的缓存,再更新缓存*/public int updateUser(User user) {ValueOperations<String, User> operations = redisTemplate.opsForValue();int result = userDao.updateUser(user);if (result != 0) {String key = "user_" + user.getUid();boolean haskey = redisTemplate.hasKey(key);if (haskey) {redisTemplate.delete(key);System.out.println("删除缓存中的key-----------> " + key);}// 再将更新后的数据加入缓存User userNew = userDao.findUserById(user.getUid());if (userNew != null) {operations.set(key, userNew, 3, TimeUnit.HOURS);}}return result;}/*** 删除用户策略:删除数据表中数据,然后删除缓存*/public int deleteUserById(int id) {int result = userDao.deleteUserById(id);String key = "user_" + id;if (result != 0) {boolean hasKey = redisTemplate.hasKey(key);if (hasKey) {redisTemplate.delete(key);System.out.println("删除了缓存中的key:" + key);}}return result;}} 

这里主要是使用RedisTemplate来对远程redis操作,每次访问controller暴露的接口,

  • 首先判断redis缓存中是否存在该数据
  • 若不存在就从数据库中读取数据,然后保存到redis缓存中
  • 当下次访问的时候,就直接从缓存中取出来。这样就不用每次都执行sql语句,能够提高访问速度。
  • 但是在保存数据到缓存中,通过设置键和值和超时删除,注意设置超时删除缓存时间不要太长,否则会给服务器带来压力。

执行spring boot的启动类,访问 http://localhost:8081/findUserById?id=1

再次访问 http://localhost:8081/findUserById?id=1就是从缓存中获取保存的数据

好了今天就写到这里,如果对您有帮助记得点个关注哦 !

SpringBoot从入门到精通教程(七):集成Redis相关推荐

  1. SpringBoot从入门到精通教程(二十九)- 微信企业支付集成(五分钟集成)

    需求背景 SpringBoot用法:微信企业支付集成(五分钟集成) 问题痛点 通过SpringBoot框架,集成服务端微信企业支付接口,做到下载即用(填写好相关微信支付后台相关Key信息),最快五分钟 ...

  2. SpringBoot从入门到精通教程(三十一)- 爬虫框架集成

    需求背景 SpringBoot用法:爬虫框架集成 业务场景 以抓取"今日头条"新闻举例说明 技术点 1. 集成爬虫框架webmagic(更多了解webmagic,可以去官方地址) ...

  3. SpringBoot从入门到精通教程

    SpringBoot从入门到精通教程 一.来自ImportNew公众号的SpringBoot教程系列,可参考学习 SpringBoot (一) :入门篇--http://mp.weixin.qq.co ...

  4. SpringBoot从入门到精通教程(二十七)- @Valid注解用法详解+全局处理器Exception优雅处理参数验证用法

    问题痛点 用 Spring 框架写代码时,写接口类,相信大家对该类的写法非常熟悉.在写接口时要写效验请求参数逻辑,这时候我们会常用做法是写大量的 if 与 if else 类似这样的代码来做判断,如下 ...

  5. SpringBoot从入门到精通教程(八):集成ElasticSearch

    本主要介绍ElasticSearch 和 SpringBoot 的整合 ,对您有帮助的话,点个关注哦 ElastSearch 介绍 ElasticSearch是一个基于Lucene的搜索服务器.它提供 ...

  6. Elasticsearch入门到精通教程 - 学习资料综合

    背景 因经常被问到Elasticsearch相关一些资料教程,这里特例整理一份以前自己的学习资料,希望对你有用. 信息资料 1. 基本API用法教程 Elasticsearch JAVA API教程G ...

  7. SpringCloud从入门到精通教程/SpringCloud Alibaba从入门到精通教程

    对于SpringCloud,很多小伙伴问到了我的研究学习资料来源,除官方文档外,特例完整整理一下自己的平时参考学习其他资料,以及分享实战项目源码和代码资源,供大家参考学习 主要教程:SpringClo ...

  8. Arduino Mixly入门到精通教程

    目录 1.介绍 2.实验器材和相关资料下载链接 3. Uno Plus 开发板和米思齐软件 第1小节  简单介绍 Uno Plus 开发板 第2小节 Uno Plus 开发板的驱动安装方法 第3小节 ...

  9. C 语言从入门到精通教程(2021 )

    C 语言从入门到精通教程(2021年) 文章目录 计算机常识 什么是计算机程序 ? 什么是计算机语言 ? 常见的计算机语言类型有哪些 ? 什么是C语言? C语言历史 C语言标准 C语言现状 为什么要学 ...

最新文章

  1. MyAdapter Andriod
  2. 18_使用react脚手架构建应用
  3. 成都python数据分析师职业技能_想成为数据分析师,需要重点学习什么技能?
  4. leetcode1169. 查询无效交易
  5. 力扣——k个一组翻转链表
  6. c语言 有趣的代码,分享一段有趣的小代码
  7. 王爽 汇编语言第三版 第9章 转移指令的原理
  8. 贝叶斯方法(Bayesian approach) —— 一种概率解释(probabilistic interpretation)
  9. python3 模板引擎_Python实现的简单模板引擎功能示例
  10. IE6不支持hover赋予css样式的解决方法 如div:hover li:hover支持
  11. 让代码看起来更舒服(1):选择适合的配色方案 (转)
  12. 英语不好,也能让你看懂man手册
  13. mac 运行android模拟器速度慢,Android模拟器速度慢 启动时间长的解决办法
  14. 国内哪家CDN加速服务好用?
  15. 计算机自带输入法在哪里设置方法,Windows7设置默认输入法_Win7默认输入法怎么设置?-192路由网...
  16. QT提取字符串中的数字
  17. 51单片机——51单片机入门基础知识
  18. 11种流行的木马清除方法
  19. java—set创建迭代器的两个方法
  20. SQL Server2008 R2下载及安装

热门文章

  1. mysql-通过年份,或每月求和
  2. 【JavaScript】常用JS
  3. Windows 版本的 B站 开源了?
  4. Gallery Server Pro ----用于分享相片,视频,音频及其他媒体的ASP.NET相册[Carol]
  5. U盘启动盘制作工具哪个好用?你怕是没用过Rufus
  6. Be fearful when others are greedy and greedy when others are fearful.
  7. 什么是飞机的上反效应
  8. Linux找回mysql的root密码
  9. 笔试题(十五):身高体重排序
  10. 【技能积累】presentation实用技巧积累,常用句式