Redis安装:https://blog.csdn.net/gavinbj/article/details/104098730
代码基于SpringCache的代码:https://blog.csdn.net/gavinbj/article/details/104310547
DB访问代码自动生成参考:https://blog.csdn.net/gavinbj/article/details/104024890
Redis是一个高性能的key-value缓存存储数据库。完全开源免费的,遵守BSD协议。Redis产品有以下三个特点:
在pom.xml中添加关于Redis的依赖。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
配置文件添加Redis配置项目:application.properties
# Redis 配置项目
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器连接密码(默认为空)
spring.redis.password=HaoJT1980
# Redis服务器地址
spring.redis.host=119.3.155.121
# Redis服务器连接端口
spring.redis.port=6379
# 链接超时时间 单位 ms(毫秒)
spring.redis.timeout=3000
#连接池中最大空闲链接,默认值是8
spring.redis.jedis.pool.max-idle=20
#连接池中最小空闲链接,默认是0
spring.redis.jedis.pool.min-idle=10
## 如果赋值为-1,则表示不限制
spring.redis.jedis.pool.max-active=200
#等待连接的最长时间
spring.redis.jedis.pool.max-wait=1000
Controller层和前面一样不在赘述,这里只给出改变的业务逻辑层代码。
package com.gavinbj.confmng.service.impl;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.gavinbj.confmng.persistence.entity.UserInfo;
import com.gavinbj.confmng.persistence.entity.UserInfoExample;
import com.gavinbj.confmng.persistence.mapper.UserInfoMapper;
import com.gavinbj.confmng.service.UserInfoService;
/**
* 用户信息
*
* @author gavinbj
*
*/
@Service
public class UserInfoServiceRedisImpl implements UserInfoService {
@Autowired
private UserInfoMapper userInfoMapper;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
/**
* 根据用户ID进行主键检索
*/
@Override
public UserInfo getUserByPK(String userId) {
UserInfo user = (UserInfo)redisTemplate.opsForValue().get(userId);
if(user == null) {
user = this.userInfoMapper.selectByPrimaryKey(userId);
}
if (user != null) {
redisTemplate.opsForValue().set(user.getUserId(), user, 100L, TimeUnit.SECONDS);
}
return user;
}
/**
* 保存用户信息
*
*/
@Override
public UserInfo saveUserInfo(UserInfo user) {
UserInfo userExist = this.userInfoMapper.selectByPrimaryKey(user.getUserId());
if(userExist == null) {
// 该用户ID不存在可以插入用户
this.userInfoMapper.insertSelective(user);
redisTemplate.opsForValue().set(user.getUserId(), user, 100L, TimeUnit.SECONDS);
}else {
throw new SysException(EnumCodeMsg.USER_EXIST, "用户信息");
}
return user;
}
/**
* 删除用户信息
*
*/
@Override
public void delUserInfo(String userId) {
this.userInfoMapper.deleteByPrimaryKey(userId);
// 同步删除Redis中的该用户信息
redisTemplate.delete(userId);
}
}
验证工具:Postman (UserInfoServiceImpl.saveUserInfo
)
POST
http://localhost:9003/gavin/api/users
JSON Body:
{
"userId" : "lijing",
"userName" : "李静",
"introduce" : "美女主播",
"mobilephone" : "13948474647",
"email": "[email protected]"
}
执行结果:
{
"status": 0,
"code": 1003,
"msg": "处理成功!",
"data": {
"userId": "lijing",
"userName": "李静",
"introduce": "美女主播",
"mobilephone": "13948474647",
"email": "[email protected]",
"birthday": null,
"gender": null
}
}
控制台输出:
2020-02-15 10:10:29.403 INFO 18812 --- [nio-9003-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/gavin] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-02-15 10:10:30.130 DEBUG 18812 --- [nio-9003-exec-1] c.g.c.p.m.U.selectByPrimaryKey : ==> Preparing: select user_id, user_name, introduce, mobilephone, email, birthday, gender from user_info where user_id = ?
2020-02-15 10:10:30.138 DEBUG 18812 --- [nio-9003-exec-1] c.g.c.p.m.U.selectByPrimaryKey : ==> Parameters: lijing(String)
2020-02-15 10:10:30.295 DEBUG 18812 --- [nio-9003-exec-1] c.g.c.p.m.U.selectByPrimaryKey : <== Total: 0
2020-02-15 10:10:30.319 DEBUG 18812 --- [nio-9003-exec-1] c.g.c.p.m.U.insertSelective : ==> Preparing: insert into user_info ( user_id, user_name, introduce, mobilephone, email ) values ( ?, ?, ?, ?, ? )
2020-02-15 10:10:30.352 DEBUG 18812 --- [nio-9003-exec-1] c.g.c.p.m.U.insertSelective : ==> Parameters: lijing(String), 李静(String), 美女主播(String), 13948474647(String), [email protected](String)
2020-02-15 10:10:30.457 DEBUG 18812 --- [nio-9003-exec-1] c.g.c.p.m.U.insertSelective : <== Updates: 1
此时在数据库中已经保存了该数据,接下来我们用检索数据的方式,验证数据是直接从缓存取得相应数据。因为我们开启了SQL执行日志的打印,所以,如果检索时,有没有打印输出检索SQL使我们检验是否走缓存的依据。
GET
http://localhost:9003/gavin/api/users/lijing
执行结果:
{
"status": 0,
"code": 1003,
"msg": "处理成功!",
"data": {
"userId": "lijing",
"userName": "李静",
"introduce": "美女主播",
"mobilephone": "13948474647",
"email": "[email protected]",
"birthday": "",
"gender": ""
}
}
此时看控制台,没有输出新的检索SQL,可以验证本次数据检索直接从Redis数据区中取得,在上次请求中除了将用户信息保存到数据库外,Redis数据库中也缓存了相应的用户数据。
基于第一步中,我们在向数据库保存用户信息时,同时将该数据保存到了Redis数据库中。现在,我们调用删除用户信息方法(该方法中通过使用redisTemplate.delete
来删除指定关键字的缓存内容),我们看看是否同时将缓存的用户信息删除掉。验证步骤如下:
调用用户删除方法
调用用户信息查询
如果缓存删除后,在调用用户信息查询,应该去数据库检索,控制台能够输出相应的检索语句。
DELETE
http://localhost:9003/gavin/api/users/lijing
执行结果
{
"status": 0,
"code": 1003,
"msg": "处理成功!",
"data": "OK"
}
控制台信息:
2020-02-15 10:15:03.273 DEBUG 18812 --- [nio-9003-exec-6] c.g.c.p.m.U.deleteByPrimaryKey : ==> Preparing: delete from user_info where user_id = ?
2020-02-15 10:15:03.276 DEBUG 18812 --- [nio-9003-exec-6] c.g.c.p.m.U.deleteByPrimaryKey : ==> Parameters: lijing(String)
2020-02-15 10:15:03.449 DEBUG 18812 --- [nio-9003-exec-6] c.g.c.p.m.U.deleteByPrimaryKey : <== Updates: 1
从上面可以看出,已经从数据库删除了数据并打印了删除语句。
接下来执行检索用的接口
GET
http://localhost:9003/gavin/api/users/lijing
执行结果
{
"status": 1,
"code": 5003,
"msg": "用户信息检索结果为空",
"data": ""
}
我们看控制台输出:
2020-02-15 10:15:31.510 DEBUG 18812 --- [nio-9003-exec-7] c.g.c.p.m.U.selectByPrimaryKey : ==> Preparing: select user_id, user_name, introduce, mobilephone, email, birthday, gender from user_info where user_id = ?
2020-02-15 10:15:31.512 DEBUG 18812 --- [nio-9003-exec-7] c.g.c.p.m.U.selectByPrimaryKey : ==> Parameters: lijing(String)
2020-02-15 10:15:31.559 DEBUG 18812 --- [nio-9003-exec-7] c.g.c.p.m.U.selectByPrimaryKey : <== Total: 0
可见执行检索时,没有从缓存中区的数据,接下里直接检索数据库,数据库检索结果也没有。所以返回用户信息为空。刚才删除Redis缓存也是正确的。
通过如上两步,现在缓存中没有缓存的用户信息,我们此时执行两次检索方法,检索一个数据库中存在的用户。第一次,因为缓存中没有该用户,所以会输出检索用SQL。第二次在执行该用户的检索,此时应该直接使用缓存中的检索结果,不去数据库重新检索,控制台中不输出SQL。
GET
http://localhost:9003/gavin/api/users/zhangsanfeng
连续执行两次结果:
{
"status": 0,
"code": 1003,
"msg": "处理成功!",
"data": {
"userId": "zhangsanfeng",
"userName": "张三丰",
"introduce": "一代宗师",
"mobilephone": "13948474647",
"email": "[email protected]",
"birthday": "",
"gender": ""
}
}
控制台输出:
2020-02-15 10:18:49.607 DEBUG 18812 --- [nio-9003-exec-8] c.g.c.p.m.U.selectByPrimaryKey : ==> Preparing: select user_id, user_name, introduce, mobilephone, email, birthday, gender from user_info where user_id = ?
2020-02-15 10:18:49.608 DEBUG 18812 --- [nio-9003-exec-8] c.g.c.p.m.U.selectByPrimaryKey : ==> Parameters: zhangsanfeng(String)
2020-02-15 10:18:49.655 DEBUG 18812 --- [nio-9003-exec-8] c.g.c.p.m.U.selectByPrimaryKey : <== Total: 1
从上可以看出第一次检索zhangsanfeng时,直接检索了数据库。第二次检索使用了缓存,没有打印出SQL日志。
以上是基本的缓存使用的例子,旨在让大家了解入门,实际项目中使用缓存的场景比较复杂,这里不做分析,各位根据实际项目进行适当的研究学习。