从零搭建若依(Ruoyi

您所在的位置:网站首页 前端怎么缓存数据库 从零搭建若依(Ruoyi

从零搭建若依(Ruoyi

2024-07-13 21:37| 来源: 网络整理| 查看: 265

文章目录 1. 添加依赖1.1 Gangbb-common的pom.xml 2. Redis数据库连接信息配置3. 在RedisConfig中自定义RedisTemplate解决序列化问题4. 封装RedisUtil --Redis常用命令工具类5.Redis测试使用6. Mybatis使用Redis做二级缓存

本章结束后对应的节选代码文件:Gangbb-Vue-06-Redis 项目地址:https://github.com/Gang-bb/Gangbb-Vue

历史遗留TODO:

第三章 mybatis缓存暂时没用到,后面整合redis后用redis做缓存(整合Redis完成)。 第四章 登录日志还未实现。(到登录和权限模块完成)LogAspect从缓存获取当前的用户信息使用模拟的数据(到登录和权限模块完成)

本章将留下TODO:

本章将解决TODO:

第三章 mybatis缓存暂时没用到,后面整合redis后用redis做缓存(整合Redis完成)。 1. 添加依赖 1.1 Gangbb-common的pom.xml org.springframework.boot spring-boot-starter-data-redis org.apache.commons commons-pool2 2. Redis数据库连接信息配置 spring: #Redis配置 redis: # 地址 host: localhost #Redis服务器连接密码(默认为空) password: # Redis数据库索引(默认为0) database: 0 # 端口,默认为6379 port: 6379 # 连接超时时间(毫秒) timeout: 10s # 这里使用的是lettuce,如果使用Jedis,把下面的lettuce改成Jedis即可 lettuce: pool: #连接池中的最大空闲连接 max-idle: 8 #连接池中的最小空闲连接 min-idle: 0 #连接池最大连接数(使用负值表示没有限制) max-active: 8 #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1 3. 在RedisConfig中自定义RedisTemplate解决序列化问题

若依用了fastjson做了序列化,这里使用jackon。fastjson出事太多了,实际业务开发中尽量少用为妙

@Configuration @EnableCaching public class RedisConfig { @Bean @SuppressWarnings("all") public RedisTemplate redisTemplate(RedisConnectionFactory factory) { //我们为了自己的开发方便,一般直接使用类型 RedisTemplate template = new RedisTemplate(); template.setConnectionFactory(factory); //Json序列化配置 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); //String的序列化 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // key采用String的序列化方式 template.setKeySerializer(stringRedisSerializer); // hash的key也采用String的序列化方式 template.setHashKeySerializer(stringRedisSerializer); // value序列化方式采用jackson template.setValueSerializer(jackson2JsonRedisSerializer); // hash的value序列化方式采用jackson template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } } 4. 封装RedisUtil --Redis常用命令工具类

若依中对Redis的工具类封装是叫RedisCache,且方法不够丰富。用我自己网上找到的redis封装工具,封装与原生的命令一摸一样!

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; /** * @author : Gangbb * @ClassName : RedisUtil * @Description : Redis操作工具类 * @Date : 2021/3/9 7:26 */ @Component public final class RedisUtil { @Autowired private RedisTemplate redisTemplate; // =============================common============================ /** * 指定缓存失效时间 * @param key 键 * @param time 时间(秒) */ public boolean expire(String key, long time) { try { if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据key 获取过期时间 * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */ public long getExpire(String key) { return redisTemplate.getExpire(key, TimeUnit.SECONDS); } /** * 判断key是否存在 * @param key 键 * @return true 存在 false不存在 */ public boolean hasKey(String key) { try { return redisTemplate.hasKey(key); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除缓存 * @param key 可以传一个值 或多个 */ @SuppressWarnings("unchecked") public void del(String... key) { if (key != null && key.length > 0) { if (key.length == 1) { redisTemplate.delete(key[0]); } else { redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); } } } // ============================String============================= /** * 普通缓存获取 * @param key 键 * @return 值 */ public Object get(String key) { return key == null ? null : redisTemplate.opsForValue().get(key); } /** * 普通缓存放入 * @param key 键 * @param value 值 * @return true成功 false失败 */ public boolean set(String key, Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 普通缓存放入并设置时间 * @param key 键 * @param value 值 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */ public boolean set(String key, Object value, long time) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else { set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 递增 * @param key 键 * @param delta 要增加几(大于0) */ public long incr(String key, long delta) { if (delta 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除hash表中的值 * * @param key 键 不能为null * @param item 项 可以使多个 不能为null */ public void hdel(String key, Object... item) { redisTemplate.opsForHash().delete(key, item); } /** * 判断hash表中是否有该项的值 * * @param key 键 不能为null * @param item 项 不能为null * @return true 存在 false不存在 */ public boolean hHasKey(String key, String item) { return redisTemplate.opsForHash().hasKey(key, item); } /** * hash递增 如果不存在,就会创建一个 并把新增后的值返回 * * @param key 键 * @param item 项 * @param by 要增加几(大于0) */ public double hincr(String key, String item, double by) { return redisTemplate.opsForHash().increment(key, item, by); } /** * hash递减 * * @param key 键 * @param item 项 * @param by 要减少记(小于0) */ public double hdecr(String key, String item, double by) { return redisTemplate.opsForHash().increment(key, item, -by); } // ============================set============================= /** * 根据key获取Set中的所有值 * @param key 键 */ public Set sGet(String key) { try { return redisTemplate.opsForSet().members(key); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 根据value从一个set中查询,是否存在 * * @param key 键 * @param value 值 * @return true 存在 false不存在 */ public boolean sHasKey(String key, Object value) { try { return redisTemplate.opsForSet().isMember(key, value); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将数据放入set缓存 * * @param key 键 * @param values 值 可以是多个 * @return 成功个数 */ public long sSet(String key, Object... values) { try { return redisTemplate.opsForSet().add(key, values); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 将set数据放入缓存 * * @param key 键 * @param time 时间(秒) * @param values 值 可以是多个 * @return 成功个数 */ public long sSetAndTime(String key, long time, Object... values) { try { Long count = redisTemplate.opsForSet().add(key, values); if (time > 0){ expire(key, time); } return count; } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 获取set缓存的长度 * * @param key 键 */ public long sGetSetSize(String key) { try { return redisTemplate.opsForSet().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 移除值为value的 * * @param key 键 * @param values 值 可以是多个 * @return 移除的个数 */ public long setRemove(String key, Object... values) { try { Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } // ===============================list================================= /** * 获取list缓存的内容 * * @param key 键 * @param start 开始 * @param end 结束 0 到 -1代表所有值 */ public List lGet(String key, long start, long end) { try { return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获取list缓存的长度 * * @param key 键 */ public long lGetListSize(String key) { try { return redisTemplate.opsForList().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 通过索引 获取list中的值 * * @param key 键 * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index 0){ expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @return */ public boolean lSet(String key, List value) { try { redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, List value, long time) { try { redisTemplate.opsForList().rightPushAll(key, value); if (time > 0){ expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据索引修改list中的某条数据 * * @param key 键 * @param index 索引 * @param value 值 * @return */ public boolean lUpdateIndex(String key, long index, Object value) { try { redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 移除N个值为value * * @param key 键 * @param count 移除多少个 * @param value 值 * @return 移除的个数 */ public long lRemove(String key, long count, Object value) { try { Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) { e.printStackTrace(); return 0; } } } 5.Redis测试使用 @RestController @RequestMapping("/test/redis") public class TestRedisController { private final Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private RedisUtil redisUtil; @GetMapping("/hello") public String helloRedis(){ // 测试写入一个string类型键值,过期时间20S redisUtil.set("key1", "Gangbb", 20); System.out.println("获取key1值"+ redisUtil.set("key1", "测试redis", 20)); return "测试redis"; } @Cacheable("cache1") @GetMapping("/hello2") public String helloRedis2(){ return "xxredis"; } @GetMapping("/hello3") public JSONObject helloRedis3(){ return getTestDetail(); } public JSONObject getTestDetail() { JSONObject retJson = new JSONObject(); String retCode = "1"; String retMsg = "操作失败!"; JSONObject bizDataJson = new JSONObject(); try { TestMybatis testMybatis = new TestMybatis(); testMybatis.setId(22); testMybatis.setName("梁yx"); testMybatis.setGender("女"); String key = "TestMybatis::"+testMybatis.getId(); //向Redis中缓存数据,-1为设置永久时效 redisUtil.set(key, testMybatis,-1); bizDataJson = JSONObject.parseObject(JSON.toJSONString(testMybatis)); retCode = "0"; retMsg = "操作成功!"; } catch (Exception e) { log.error(String.valueOf(e)); } retJson.put("retCode", retCode); retJson.put("retMsg", retMsg); retJson.put("bizData", bizDataJson); return retJson; } } 6. Mybatis使用Redis做二级缓存

(若依中未提及该内容)

大概思路:

实现自定义Mybatis缓存的Cache接口的缓存工具RedisCache /** * @author : Gangbb * @ClassName : RedisCache * @Description : 自定义Mybatis缓存的Cache接口 * @Date : 2021/3/9 10:27 */ public class RedisCache implements Cache { private static final Logger logger = LoggerFactory.getLogger(RedisCache.class); private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); @Autowired private RedisTemplate redisTemplate; private String id; public RedisCache(final String id) { if (id == null) { throw new IllegalArgumentException("Cache instances require an ID"); } logger.info("Redis Cache id " + id); this.id = id; } @Override public String getId() { return this.id; } @Override public void putObject(Object key, Object value) { RedisTemplate redisTemplate = getRedisTemplate(); if (value != null) { //向redis中加入数据,有效期是2天 redisTemplate.opsForValue().set(key.toString(), value, 2, TimeUnit.DAYS); } } @Override public Object getObject(Object key) { RedisTemplate redisTemplate = getRedisTemplate(); try { if (key != null) { Object object = redisTemplate.opsForValue().get(key.toString()); return object; } } catch (Exception e) { logger.error("redis exception....."); e.printStackTrace(); } return null; } @Override public Object removeObject(Object key) { RedisTemplate redisTemplate = getRedisTemplate(); try { if (key != null) { redisTemplate.delete(key.toString()); } } catch (Exception e) { } return null; } @Override public void clear() { RedisTemplate redisTemplate = getRedisTemplate(); logger.debug("插入or更新or删除数据库操作,清除对应redis缓存"); try { Set keys = redisTemplate.keys("*:" + this.id + "*"); if (!CollectionUtils.isEmpty(keys)) { redisTemplate.delete(keys); } } catch (Exception e) { logger.error("clear exception...."); } } @Override public int getSize() { RedisTemplate redisTemplate = getRedisTemplate(); Long size = (Long) redisTemplate.execute(new RedisCallback() { @Override public Long doInRedis(RedisConnection connection) throws DataAccessException { return connection.dbSize(); } }); return size.intValue(); } @Override public ReadWriteLock getReadWriteLock() { return this.readWriteLock; } private RedisTemplate getRedisTemplate() { if (redisTemplate == null) { redisTemplate = SpringUtils.getBean("redisTemplate"); } return redisTemplate; } } XxxMapper.xml调用该工具,开启使用二级缓存

在这里插入图片描述

测试

SysOperationLogServiceImpl、SysOperationLogService、SysOperationLogMapper文件添加内容不再展示,就是简单的添加一个查询所有sys_operation_log库的方法。

(还需多往库里加点数据,本次测试1000多条记录)

在这里插入图片描述

结果:

image-20210309105411653

可以看到每查询一次,查询命中缓存率就越高,用时就越少。

注意此时如果想要在控制台看到hi用缓存相关信息需要在log4j2.xml日志配置文件中,把mybatis的打印级别设置到debug

image-20210309105901411

redis中:

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3