SpringBoot + Mybatis + Redis 整合入门项目
这篇文章我决定一改以往的风格,以幽默风趣的故事博文来介绍如何整合 SpringBoot、Mybatis、Redis。
很久很久以前,森林里有一只可爱的小青蛙,他迈着沉重的步伐走向了找工作的道路,结果发现许多的招聘要求都要会 Redis。
小青蛙就想啥是 Redis 呢,为什么要用 Redis 呢?难道是因为 Mysql 的币格不够高吗,小青蛙点开了收藏已久的网站:十万个为什么
发现原来随着使用网站的用户越来越多,表中的数据也越来越多,查询速度越来越慢。
MySql 的性能遇到了瓶颈,所以许多网站都用 Redis 作缓存。
然而能作缓存的不仅只有 Redis,还有 Memcache,那为什么要用 Redis 呢?
1、性能方面:它们都是将数据存放在内存中,所以性能基本相似。
2、数据类型方面:Redis 支持五种数据数据类型:字符串、散列、列表、集合、有序集合,而 Memcache 仅仅支持简单的 key-value。
3、数据持久化方面:Redis 可以通过 RDB快照、AOF日志 等方式进行数据持久化,但是 Memcache 不可以。
4、数据备份方面:Redis 支持 master-slave 主从模式的数据备份。
在了解到许多 Redis 的好处后,小青蛙已经迫不及待的想了解它了。
为了更好的使用 Redis,了解 Redis 的五种数据类型适应场景是很有必要的。
1、String 类型:一个 key 对应一个 value,而 value 不仅仅是 String,也可以是数字、甚至是一个序列化对象。
2、Hash 类型:一个 key 对应 多个 field,一个 field 对应 yige value,实际上该类型最适合存储序列化对象。
key 相当于数据库表名字,field 相当于主键,value 也就是序列化对象。
3、List 类型:简单的字符串列表,按照插入顺序排序,该结构类似于数据结构中的双向链表,可以从头部插也可以从尾部插。
4、Set 类型:它是字符串集合,只不过它是无序的且不存在重复的字符串,但是它可以实现 交集、并集、差集。
5、ZSet 类型:它也是字符串集合,它和 Set 的区别是该集合的元素存在 score 属性,按照 score 属性的高低排序。可以应用在排行榜上。
值得注意的是,不要习惯性的认为 Redis 字符串只能存字符串,实际上,它可以存储任何序列化后的对象,当然也可以读出来。
小青蛙知道了 Redis 的五种数据类型应用场景后,迫不及待的想要实践它了。
为了知道如何让它作为缓存,以及如何操作数据,小青蛙打开了珍藏已久的视频网站来学习:青蛙爱学习
在该视频网站上,小青蛙沉迷其中无法自拔,额,呸呸。缓过神来,发现了一个很好的视频。小青蛙幽默的说:快进我的收藏夹吃灰去吧。
小青蛙向来都不是一个收藏从未停止,学习从未开始的青蛙。它模仿着视频建了一个 SpringBoot 项目。

此时,小青蛙想为什么要勾选 Lombok 呢,因为它可以简化类,并且提供了 log 等功能。
之后小青蛙为了连上 Mysql 和 Redis 就开始配置 application.properties 文件:
# 数据源配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/demo?serverTimezone=UTC&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=lemon@mango # Redis 配置
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
spring.redis.lettuce.shutdown-timeout=100
配置好该文件后,需要 redisTemplate 模板 Bean,因为自动配置的 redisTemplate Bean 没有提供序列化操作:(因为是入门版的,所以这样最好理解)
package com.demo.config; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration
public class RedisConfig { @Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
GenericJackson2JsonRedisSerializer genericJsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(genericJsonRedisSerializer);
template.setHashKeySerializer(genericJsonRedisSerializer);
template.setHashValueSerializer(genericJsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
至此就整合完成了,小青蛙心想这就完事了?!!!,不信?那就来演示一下:(先建一个简单的类测试一下)
package com.test.serviceImpl; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.extern.slf4j.Slf4j; @Service
@Slf4j
public class JustForTest { @Autowired
private RedisTemplate redisTemplate; public void test(String username) { if(redisTemplate.hasKey(username)) {
log.info((String)redisTemplate.opsForValue().get(username));
log.info("get value from redis");
}else {
String password = "password";
log.info(password);
log.info("get value from mysql");
log.info("set value to redis");
redisTemplate.opsForValue().set(username, password);
} } }
package com.test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.beans.factory.annotation.Autowired;
import com.test.serviceImpl.JustForTest; @SpringBootTest
class TestApplicationTests { @Autowired
private JustForTest justFortest; @Test
void contextLoads() {
justFortest.test("username");
}
}

哦嚯,报错了,原来是 pom.xml 中少了 commons.pool 依赖,咱给它加上:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
再来一次:

再再来一次:

可以看到确实存入 Redis 了,小青蛙便去 Redis 数据库中看看有没有:
事实证明确实整合完毕了,小青蛙仍然表示不解,说好的是SpringBoot、Mybatis、Redis的整合呢,怎么只看到 Redis 的?
小青蛙刚这么想,然后视频里就说了,心急吃不了热豆腐,需要慢慢来。紧接着,小青蛙就看到了完整的项目结构:

为了让青蛙们只关注有关整合的部分,视频里仅仅只给出 serviceImpl 中的代码:
package com.demo.serviceImpl; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import com.demo.pojo.SimpleUser;
import com.demo.dao.SimpleUserDao;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import lombok.extern.slf4j.Slf4j; @Service
@Slf4j
@SuppressWarnings({"rawtypes","unchecked"})
public class SimpleUserServiceImpl implements UserDetailsService { @Autowired
private RedisTemplate redisTemplate;
@Autowired
private SimpleUserDao userDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO Auto-generated method stub
if(redisTemplate.opsForHash().hasKey("user",username)) {
SimpleUser user = (SimpleUser)redisTemplate.opsForHash().get("user",username);
return new User(user.getUsername(),user.getPassword(),user.getAuthorities());
}else {
SimpleUser user = userDao.findUserByUsername(username);
if(user != null) {
redisTemplate.opsForHash().put("user", "username", user);
return new User(user.getUsername(),user.getPassword(),user.getAuthorities());
}else {
throw new UsernameNotFoundException("Username or Password is not correct");
}
}
} public int addSimpleUser(SimpleUser user) {
user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
return userDao.addSimpleUser(user);
}
}
和上面测试的简单小例子相似,仅仅是把 String 换成了对象。小青蛙对 Mysql 的表结构和Redis中存入的数据比较感心趣:


由于对 String 类型带有 " 符号,所以需要对其进行转义。
小青蛙是一个有分享精神的蛙,每次它觉得有价值的东西,它都会分享给它的朋友们,项目地址为:GitHub


小青娃逐渐的弄懂了怎么去进行整合,但是它还是不太明白为什么这样就能整合,也就是 know how but don't konw why!
小青蛙知道:万事开头难,但它不知道的是,后面也很难...从此,小青蛙踏上了探寻源码的道路!呱呱呱......
SpringBoot + Mybatis + Redis 整合入门项目的更多相关文章
- 7.springboot+mybatis+redis整合
选择生成的依赖 选择保存的工程路径 查询已经生成的依赖,并修改mysql的版本 <dependencies> <dependency> <groupId>org.s ...
- SpringCloud+MyBatis+Redis整合—— 超详细实例(二)
2.SpringCloud+MyBatis+Redis redis①是一种nosql数据库,以键值对<key,value>的形式存储数据,其速度相比于MySQL之类的数据库,相当于内存读写 ...
- springboot + mybatis + mycat整合
1.mycat服务 搭建mycat服务并启动,windows安装参照. 系列文章: [Mycat 简介] [Mycat 配置文件server.xml] [Mycat 配置文件schema.xml] [ ...
- SpringBoot+Mybatis+MybatisPlus整合实现基本的CRUD操作
SpringBoot+Mybatis+MybatisPlus整合实现基本的CRUD操作 1> 数据准备 -- 创建测试表 CREATE TABLE `tb_user` ( `id` ) NOT ...
- redis(七)---- SpringBoot和redis整合
SpringBoot和Redis整合非常简单 添加pom依赖 <dependency> <groupId>org.springframework.boot</groupI ...
- springboot+mybatis+redis实现分布式缓存
大家都知道springboot项目都是微服务部署,A服务和B服务分开部署,那么它们如何更新或者获取共有模块的缓存数据,或者给A服务做分布式集群负载,如何确保A服务的所有集群都能同步公共模块的缓存数据, ...
- 基于SpringBoot + Mybatis实现SpringMVC Web项目
一.热身 一个现实的场景是:当我们开发一个Web工程时,架构师和开发工程师可能更关心项目技术结构上的设计.而几乎所有结构良好的软件(项目)都使用了分层设计.分层设计是将项目按技术职能分为几个内聚的部分 ...
- springboot + mybatis 前后端分离项目的搭建 适合在学习中的大学生
人生如戏,戏子多半掉泪! 我是一名大四学生,刚进入一家软件件公司实习,虽说在大学中做过好多个实训项目,都是自己完成,没有组员的配合.但是在这一个月的实习中,我从以前别人教走到了现在的自学,成长很多. ...
- SpringBoot日记——Redis整合
上一篇文章,简单记录了一下缓存的使用方法,这篇文章将把我们熟悉的redis整合进来. 那么如何去整合呢?首先需要下载和安装,为了使用方便,也可以做环境变量的配置. 下载和安装的方法,之前有介绍,在do ...
随机推荐
- html文本超出加省略号
如果实现单行文本的溢出显示省略号同学们应该都知道用text-overflow:ellipsis属性来,当然还需要加宽度width属来兼容部分浏览. 实现方法: overflow: hidden; te ...
- 二刷Redux笔记
关于react的一些思考 所有的数据全部先要发送给容器,然后容器负责接受数据单后再分发数据给他下面的组件,通过props来传递,一个页面就可以相当于一个容器,容器之中就会有很多子组件,一般组件只负责接 ...
- 关于String是值传递还是引用传递
public class Itv { static String ss = "kkkkkk"; static String ss1 = new String("kkkkk ...
- django-模型层(ORM语法)
今日内容概要(重要) 模型层(ORM语法):跟数据库打交道的 单表查询(增删改查) 常见的十几种查询方法 神奇的双下划线查询 多表操作 外键字段的增删改查 跨表查询(重点) 子查询 联表查询 今日内容 ...
- Redis详解(十一)------ 过期删除策略和内存淘汰策略
在介绍这篇文章之前,我们先来看如下几个问题: ①.如何设置Redis键的过期时间? ②.设置完一个键的过期时间后,到了这个时间,这个键还能获取到么?假如获取不到那这个键还占据着内存吗? ③.如何设置R ...
- DCL单例为什么要加Volatile
拿一个对象创建赋值来说 class T{ int elem = 1; } T t = new T(); 上段代码转换成汇编码为: 0 new #2 <T> 3 dup 4 invokesp ...
- Rocket - debug - Example: Accessing Registers Using Program Buffer
https://mp.weixin.qq.com/s/8yYLVg-RXX3XX0T431lxeA 介绍riscv debug接口的使用实例:使用Program Buffer读取寄存器. 1. Wri ...
- css 段落文字换行问题
项目中遇到的一个小问题,以前没有注意到: 超链接超出父级元素,想着给a标签加宽度但是没有效果... 后来发现两个很好用的css属性 1.word-wrap 用来控制换行 取值: (1)normal ...
- Java实现 蓝桥杯 算法训练 Lift and Throw
试题 算法训练 Lift and Throw 问题描述 给定一条标有整点(1, 2, 3, -)的射线. 定义两个点之间的距离为其下标之差的绝对值. Laharl, Etna, Flonne一开始在这 ...
- Java实现 LeetCode 664 奇怪的打印机(DFS)
664. 奇怪的打印机 有台奇怪的打印机有以下两个特殊要求: 打印机每次只能打印同一个字符序列. 每次可以在任意起始和结束位置打印新字符,并且会覆盖掉原来已有的字符. 给定一个只包含小写英文字母的字符 ...