目录结构:
pom.xml
org.springframework.data
spring-data-redis
redis.clients
jedis
2.9.1
io.lettuce
lettuce-core
org.apache.commons
commons-pool2
2.5.0
com.alibaba
fastjson
1.2.68
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
true
mysql
mysql-connector-java
5.1.47
com.baomidou
mybatis-plus-boot-starter
3.0.5
application.properties
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
spring.datasource.url= jdbc:mysql://localhost:3306/cache-db?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username= root
spring.datasource.password= 123456
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
mybatis-plus.mapper-locations= classpath:mapper/*.xml
RedisConfig
package com.frank.cache.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.io.Serializable;
/**
* @author 小石潭记
* @date 2020/6/26 12:44
* @Description: ${todo}
*/
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Bean
public RedisTemplate
ArticleController
package com.frank.cache.controller;
import com.frank.cache.entity.Article;
import com.frank.cache.entity.ResultVo;
import com.frank.cache.mapper.ArticleMapper;
import com.frank.cache.service.ArticleRedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author 小石潭记
* @date 2020/6/26 11:30
* @Description: ${todo}
*/
@RestController
@Slf4j
public class ArticleController {
@Autowired
private ArticleRedisService service;
@Autowired
ArticleMapper articleMapper;
/**
* 添加文章
*/
@PostMapping("/add")
public ResultVo addArticle(@RequestBody Article article) {
log.info(article.toString());
Integer result = service.addArticle(article);
if (result >= 0) {
return ResultVo.success(article);
}
return ResultVo.fail();
}
/**
* 获取一篇文章
*/
@GetMapping("/get")
public ResultVo getArticle(@RequestParam("id") Integer id) {
Long start = System.currentTimeMillis();
Article article = service.getArticle(id);
Long end = System.currentTimeMillis();
log.info("耗时:"+ (end-start));
if (null != article)
return ResultVo.success(article);
return ResultVo.fail();
}
@GetMapping("/getAll")
public ResultVo getAllArticles() {
Long start = System.currentTimeMillis();
Object articles = service.getAllArticles();
Long end = System.currentTimeMillis();
log.info("耗时:"+(end-start));
if (null != articles) {
return ResultVo.success(articles);
}
return ResultVo.fail();
}
/**
* 更新一篇文章
*/
@PostMapping("/update")
public ResultVo update(@RequestBody Article article) {
final Integer result = service.update(article);
if (result > 0) {
return ResultVo.success(result);
} else {
return ResultVo.fail();
}
}
/**
* 删除一篇文章
*/
@GetMapping("/remove")
public ResultVo remove(@RequestParam("id") Integer id) {
final Integer result = service.removeArticleById(id);
if (result > 0) {
return ResultVo.success(result);
} else {
return ResultVo.fail();
}
}
}
Article
package com.frank.cache.entity;
import lombok.Data;
import java.io.Serializable;
/**
* @author 小石潭记
* @date 2020/6/26 11:20
* @Description: ${todo}
*/
@Data
public class Article implements Serializable {
private int id;
private String title;
private String content;
private String author;
private String fileName;
private String state;
}
ResultVo
package com.frank.cache.entity;
import lombok.Data;
/**
* @author 小石潭记
* @date 2020/6/26 11:32
* @Description: ${todo}
*/
@Data
public class ResultVo {
private int code;
private String message;
private Object data;
public static ResultVo success(Object object){
ResultVo resultVo = new ResultVo();
resultVo.setCode(200);
resultVo.setMessage("success");
resultVo.setData(object);
return resultVo;
}
public static ResultVo fail(){
ResultVo resultVo = new ResultVo();
resultVo.setCode(404);
resultVo.setMessage("fail");
resultVo.setData(null);
return resultVo;
}
}
ArticleMapper
package com.frank.cache.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.frank.cache.entity.Article;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.cache.annotation.CacheConfig;
import java.util.List;
/**
* @author 小石潭记
* @date 2020/6/26 11:23
* @Description: ${todo}
*/
public interface ArticleMapper extends BaseMapper {
/**
* 自定义sql查询
*/
List getAllArticles();
}
ArticleRedisService
package com.frank.cache.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.frank.cache.entity.Article;
import com.frank.cache.mapper.ArticleMapper;
import com.frank.cache.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author 小石潭记
* @date 2020/6/26 11:27
* @Description: service层引入cache缓存
* 使用redis的set方式设置缓存
*/
@Service
@Slf4j
public class ArticleRedisService {
private AtomicInteger count =new AtomicInteger(0);
@Autowired
private ArticleMapper articleMapper;
@Autowired
private RedisUtil redisUtil;
/**
* 增加一篇文章 每次就进行缓存
* @return
*/
public Integer addArticle(Article article){
int insert = articleMapper.insert(article);
if (insert > 0) {
return insert;
}
return null;
}
/**
* 获取文章 以传入的id为键,当state为0的时候不进行缓存
* @param id 文章id
* @return
*/
public Article getArticle(Integer id) {
String key = "article_" + id;
boolean hasKey = redisUtil.exists(key);
if (hasKey){
String articleStr = redisUtil.get(key);
JSONObject jsonObject = JSONObject.parseObject(articleStr);
Article article = jsonObject.toJavaObject(Article.class);
log.info("从缓存redis中获取的数据:{}", article);
return article;
}
try {
//模拟耗时操作
Thread.sleep(5000);
Article article = articleMapper.selectById(id);
log.info("--执行数据库查询操作"+count.incrementAndGet()+"次"+"id:"+id);
// 将查询的结果保存至redis缓存里
redisUtil.set(key, article);
return article;
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
/**
* 自定义的sql方法
* @return
*/
public Object getAllArticles() {
try {
String key = "getAllArticles";
boolean hasKey = redisUtil.exists(key);
if (hasKey) {
String str = redisUtil.get(key);
return str;
}
//模拟耗时操作
Thread.sleep(5000);
List allArticles = articleMapper.getAllArticles();
redisUtil.set(key, allArticles);
return allArticles;
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
/**
* 通过id更新内容 清除以id作为键的缓存
*/
public Integer update(Article article) {
try {
log.info("==========数据库中更新文章信息=========");
UpdateWrapper updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", 1);
articleMapper.update(article, updateWrapper);
String key = "article_" + article.getId();
boolean hasKey = redisUtil.exists(key);
if (hasKey) {
redisUtil.remove(key);
log.info("删除缓存中的key=========>" + key);
}
// 再将更新后的数据加入缓存
redisUtil.set(key, JSON.toJSONString(article));
return 1;
}catch (Exception e) {
return 0;
}
}
/**
* 通过id移除文章
* @param id 清除以id作为键的缓存
* @return
*/
public Integer removeArticleById(Integer id){
int result = articleMapper.deleteById(id);
log.info("执行删除操作,id:"+id);
String key = "article_" + id;
redisUtil.remove(key);
return result;
}
}
RedisUtil(set方法里面设置了过期时间30s,根据实际情况修改)
package com.frank.cache.util;
import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
/**
*
* @Description: spring boot 的redis工具类
*/
@Component
public class RedisUtil {
@Autowired
private RedisTemplate redisTemplate;
/**
* 批量删除对应的value
*/
public void remove(final String... keys) {
for (String key : keys) {
remove(key);
}
}
/**
* 批量删除key
*/
public void removePattern(final String pattern) {
Set keys = redisTemplate.keys(pattern);
if (keys.size() > 0)
redisTemplate.delete(keys);
}
/**
* 删除对应的value
*/
public void remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/**
* 判断缓存中是否有对应的value
*/
public boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
/**
* 读取缓存
*/
public String get(final String key) {
Object result = null;
redisTemplate.setValueSerializer(new StringRedisSerializer());
ValueOperations operations = redisTemplate.opsForValue();
result = operations.get(key);
if (result == null) {
return null;
}
return result.toString();
}
/**
* 写入缓存, 并且设置了30s过期
*/
public boolean set(final String key, Object value) {
boolean result = false;
try {
ValueOperations operations = redisTemplate.opsForValue();
operations.set(key, value, 30, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 写入缓存
*
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value, Long expireTime) {
boolean result = false;
try {
ValueOperations operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public boolean hmset(String key, Map value) {
boolean result = false;
try {
redisTemplate.opsForHash().putAll(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public Map hmget(String key) {
Map result = null;
try {
result = redisTemplate.opsForHash().entries(key);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
RedisSpringbootApplication
package com.frank.cache;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
/**
* @author 小石潭记
* @date 2020/6/26 12:42
* @Description: ${todo}
*/
@SpringBootApplication
@EnableCaching
@MapperScan(basePackages = {"com.frank.cache"})
public class RedisSpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(RedisSpringbootApplication.class, args);
}
}
ArticleMapper.xml
测试:
代码下载