增加 Spring Cache 框架

This commit is contained in:
YunaiV 2022-04-03 13:23:00 +08:00
parent 3263b0ab5b
commit 49b906bbfe
14 changed files with 115 additions and 37 deletions

View File

@ -26,6 +26,12 @@
<groupId>org.redisson</groupId> <groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId> <artifactId>redisson-spring-boot-starter</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId> <!-- 实现对 Caches 的自动化配置 -->
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,48 @@
package cn.iocoder.yudao.framework.redis.config;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
/**
* Cache 配置类基于 Redis 实现
*/
@Configuration
@EnableCaching
public class YudaoCacheAutoConfiguration {
/**
* RedisCacheConfiguration Bean
*
* 参考 org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration createConfiguration 方法
*/
@Bean
@Primary
public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
// 设置使用 JSON 序列化方式
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()));
// 设置 CacheProperties.Redis 的属性
CacheProperties.Redis redisProperties = cacheProperties.getRedis();
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (redisProperties.getKeyPrefix() != null) {
config = config.prefixCacheNameWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.framework.redis.config; package cn.iocoder.yudao.framework.redis.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
@ -11,7 +10,6 @@ import org.springframework.data.redis.serializer.RedisSerializer;
* Redis 配置类 * Redis 配置类
*/ */
@Configuration @Configuration
@Slf4j
public class YudaoRedisAutoConfiguration { public class YudaoRedisAutoConfiguration {
/** /**

View File

@ -1,2 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration,\
cn.iocoder.yudao.framework.redis.config.YudaoCacheAutoConfiguration

View File

@ -0,0 +1 @@
<http://www.iocoder.cn/Spring-Boot/Cache/?yudao>

View File

@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data; import lombok.Data;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import java.util.*; import java.util.*;
@ -61,10 +60,6 @@ public class LoginUser implements UserDetails {
* 部门编号 * 部门编号
*/ */
private Long deptId; private Long deptId;
/**
* 所属岗位
*/
private Set<Long> postIds;
// ========== 上下文 ========== // ========== 上下文 ==========
/** /**

View File

@ -0,0 +1,19 @@
### 请求 /infra/test-demo/get 接口 => 成功
GET {{baseUrl}}/infra/test-demo/get?id=106
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
### 请求 /infra/test-demo/update 接口 => 成功
PUT {{baseUrl}}/infra/test-demo/update
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
Content-Type: application/json
{
"id": 106,
"name": "测试",
"status": "0",
"type": 1,
"category": 1
}

View File

@ -1,30 +1,29 @@
package cn.iocoder.yudao.module.infra.controller.admin.test; package cn.iocoder.yudao.module.infra.controller.admin.test;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.*; import cn.iocoder.yudao.module.infra.controller.admin.test.vo.*;
import cn.iocoder.yudao.module.infra.convert.test.TestDemoConvert; import cn.iocoder.yudao.module.infra.convert.test.TestDemoConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO; import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.infra.controller.admin.test.vo.*;
import cn.iocoder.yudao.module.infra.service.test.TestDemoService; import cn.iocoder.yudao.module.infra.service.test.TestDemoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Api(tags = "管理后台 - 字典类型") @Api(tags = "管理后台 - 字典类型")
@RestController @RestController
@ -37,13 +36,15 @@ public class TestDemoController {
@PostMapping("/create") @PostMapping("/create")
@ApiOperation("创建字典类型") @ApiOperation("创建字典类型")
@PreAuthorize("@ss.hasPermission('infra:test-demo:create')") public CommonResult<Long> createTestDemo(@Valid @RequestBody TestDemoCreateReqVO createReqVO) { @PreAuthorize("@ss.hasPermission('infra:test-demo:create')")
public CommonResult<Long> createTestDemo(@Valid @RequestBody TestDemoCreateReqVO createReqVO) {
return success(testDemoService.createTestDemo(createReqVO)); return success(testDemoService.createTestDemo(createReqVO));
} }
@PutMapping("/update") @PutMapping("/update")
@ApiOperation("更新字典类型") @ApiOperation("更新字典类型")
@PreAuthorize("@ss.hasPermission('infra:test-demo:update')") public CommonResult<Boolean> updateTestDemo(@Valid @RequestBody TestDemoUpdateReqVO updateReqVO) { @PreAuthorize("@ss.hasPermission('infra:test-demo:update')")
public CommonResult<Boolean> updateTestDemo(@Valid @RequestBody TestDemoUpdateReqVO updateReqVO) {
testDemoService.updateTestDemo(updateReqVO); testDemoService.updateTestDemo(updateReqVO);
return success(true); return success(true);
} }

View File

@ -8,6 +8,8 @@ import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoUpdateReqV
import cn.iocoder.yudao.module.infra.convert.test.TestDemoConvert; import cn.iocoder.yudao.module.infra.convert.test.TestDemoConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO; import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO;
import cn.iocoder.yudao.module.infra.dal.mysql.test.TestDemoMapper; import cn.iocoder.yudao.module.infra.dal.mysql.test.TestDemoMapper;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -31,6 +33,7 @@ public class TestDemoServiceImpl implements TestDemoService {
private TestDemoMapper testDemoMapper; private TestDemoMapper testDemoMapper;
@Override @Override
@CacheEvict(value = "test", key = "#createReqVO.id")
public Long createTestDemo(TestDemoCreateReqVO createReqVO) { public Long createTestDemo(TestDemoCreateReqVO createReqVO) {
// 插入 // 插入
TestDemoDO testDemo = TestDemoConvert.INSTANCE.convert(createReqVO); TestDemoDO testDemo = TestDemoConvert.INSTANCE.convert(createReqVO);
@ -40,6 +43,7 @@ public class TestDemoServiceImpl implements TestDemoService {
} }
@Override @Override
@CacheEvict(value = "test", key = "#updateReqVO.id")
public void updateTestDemo(TestDemoUpdateReqVO updateReqVO) { public void updateTestDemo(TestDemoUpdateReqVO updateReqVO) {
// 校验存在 // 校验存在
this.validateTestDemoExists(updateReqVO.getId()); this.validateTestDemoExists(updateReqVO.getId());
@ -49,6 +53,7 @@ public class TestDemoServiceImpl implements TestDemoService {
} }
@Override @Override
@CacheEvict(value = "test", key = "'test:' + #id")
public void deleteTestDemo(Long id) { public void deleteTestDemo(Long id) {
// 校验存在 // 校验存在
this.validateTestDemoExists(id); this.validateTestDemoExists(id);
@ -63,6 +68,7 @@ public class TestDemoServiceImpl implements TestDemoService {
} }
@Override @Override
@Cacheable(cacheNames = "test", key = "#id")
public TestDemoDO getTestDemo(Long id) { public TestDemoDO getTestDemo(Long id) {
return testDemoMapper.selectById(id); return testDemoMapper.selectById(id);
} }

View File

@ -1 +0,0 @@
package cn.iocoder.yudao.module.system.dal.dataobject;

View File

@ -15,12 +15,14 @@ import java.util.List;
public interface DeptMapper extends BaseMapperX<DeptDO> { public interface DeptMapper extends BaseMapperX<DeptDO> {
default List<DeptDO> selectList(DeptListReqVO reqVO) { default List<DeptDO> selectList(DeptListReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<DeptDO>().likeIfPresent(DeptDO::getName, reqVO.getName()) return selectList(new LambdaQueryWrapperX<DeptDO>()
.likeIfPresent(DeptDO::getName, reqVO.getName())
.eqIfPresent(DeptDO::getStatus, reqVO.getStatus())); .eqIfPresent(DeptDO::getStatus, reqVO.getStatus()));
} }
default DeptDO selectByParentIdAndName(Long parentId, String name) { default DeptDO selectByParentIdAndName(Long parentId, String name) {
return selectOne(new LambdaQueryWrapper<DeptDO>().eq(DeptDO::getParentId, parentId) return selectOne(new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getParentId, parentId)
.eq(DeptDO::getName, name)); .eq(DeptDO::getName, name));
} }

View File

@ -41,7 +41,7 @@ public class LoginUserRedisDAO {
} }
private static String formatKey(String sessionId) { private static String formatKey(String sessionId) {
return String.format(LOGIN_USER.getKeyTemplate(), sessionId); return LOGIN_USER.formatKey(sessionId);
} }
} }

View File

@ -44,14 +44,12 @@ spring:
datasource: datasource:
master: master:
name: ruoyi-vue-pro name: ruoyi-vue-pro
# name: ruoyi-vue-pro-flowable
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
driver-class-name: com.mysql.jdbc.Driver driver-class-name: com.mysql.jdbc.Driver
username: root username: root
password: 123456 password: 123456
slave: # 模拟从库,可根据自己需要修改 slave: # 模拟从库,可根据自己需要修改
name: ruoyi-vue-pro name: ruoyi-vue-pro
# name: ruoyi-vue-pro-flowable
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
driver-class-name: com.mysql.jdbc.Driver driver-class-name: com.mysql.jdbc.Driver
username: root username: root

View File

@ -20,6 +20,10 @@ spring:
write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳
fail-on-empty-beans: false # 允许序列化无属性的 Bean fail-on-empty-beans: false # 允许序列化无属性的 Bean
# Cache 配置项
cache:
type: REDIS
# 工作流 Activiti 配置 # 工作流 Activiti 配置
activiti: activiti:
# 1. false: 默认值activiti启动时对比数据库表中保存的版本如果不匹配。将抛出异常 # 1. false: 默认值activiti启动时对比数据库表中保存的版本如果不匹配。将抛出异常