fix: mock功能缓存
This commit is contained in:
@@ -1,24 +1,10 @@
|
|||||||
/*
|
|
||||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
|
||||||
*
|
|
||||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
|
||||||
*
|
|
||||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
|
||||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
|
||||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
|
||||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
|
||||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
|
||||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
|
||||||
*/
|
|
||||||
package org.nl.common.annotation;
|
package org.nl.common.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义节流防抖注解
|
* 自定义节流防抖注解
|
||||||
*
|
|
||||||
* @author xuyuxiang
|
|
||||||
* @date 2022/6/20 14:25
|
|
||||||
**/
|
**/
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ public class MockConfigController {
|
|||||||
return CommonResult.data(mockConfigService.detail(mockConfigIdParam));
|
return CommonResult.data(mockConfigService.detail(mockConfigIdParam));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SaIgnore
|
||||||
@GetMapping("/test")
|
@GetMapping("/test")
|
||||||
public String test() {
|
public String test() {
|
||||||
return "WELCOME";
|
return "WELCOME";
|
||||||
|
|||||||
@@ -62,4 +62,14 @@ public class MockConfig {
|
|||||||
@Schema(description = "更新时间")
|
@Schema(description = "更新时间")
|
||||||
@TableField(fill = FieldFill.UPDATE)
|
@TableField(fill = FieldFill.UPDATE)
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 领域方法:生成缓存键
|
||||||
|
* 缓存键由API路径和方法组合而成,用于在缓存中唯一标识配置
|
||||||
|
*
|
||||||
|
* @return 格式为 "apiPath:apiMethod" 的缓存键
|
||||||
|
*/
|
||||||
|
public String getCacheKey() {
|
||||||
|
return apiPath + ":" + apiMethod;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,4 +52,14 @@ public class MockConfigEditParam {
|
|||||||
@Schema(description = "是否启用:true-启用,false-禁用")
|
@Schema(description = "是否启用:true-启用,false-禁用")
|
||||||
private Boolean isEnabled;
|
private Boolean isEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 领域方法:生成缓存键
|
||||||
|
* 缓存键由API路径和方法组合而成,用于在缓存中唯一标识配置
|
||||||
|
*
|
||||||
|
* @return 格式为 "apiPath:apiMethod" 的缓存键
|
||||||
|
*/
|
||||||
|
public String getCacheKey() {
|
||||||
|
return apiPath + ":" + apiMethod;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nl.tool.mock.core.handle.MockCacheService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.nl.common.enums.CommonSortOrderEnum;
|
import org.nl.common.enums.CommonSortOrderEnum;
|
||||||
@@ -42,9 +46,19 @@ import java.util.Optional;
|
|||||||
* @author liyongde
|
* @author liyongde
|
||||||
* @date 2026/01/28 17:50
|
* @date 2026/01/28 17:50
|
||||||
**/
|
**/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class MockConfigServiceImpl extends ServiceImpl<MockConfigMapper, MockConfig> implements MockConfigService {
|
public class MockConfigServiceImpl extends ServiceImpl<MockConfigMapper, MockConfig> implements MockConfigService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private MockCacheService cacheService;
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
public MockConfigServiceImpl(ObjectMapper objectMapper) {
|
||||||
|
this.objectMapper = objectMapper;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<MockConfig> page(MockConfigPageParam mockConfigPageParam) {
|
public Page<MockConfig> page(MockConfigPageParam mockConfigPageParam) {
|
||||||
QueryWrapper<MockConfig> queryWrapper = new QueryWrapper<MockConfig>().checkSqlInjection();
|
QueryWrapper<MockConfig> queryWrapper = new QueryWrapper<MockConfig>().checkSqlInjection();
|
||||||
@@ -71,6 +85,8 @@ public class MockConfigServiceImpl extends ServiceImpl<MockConfigMapper, MockCon
|
|||||||
@Override
|
@Override
|
||||||
public void add(MockConfigAddParam mockConfigAddParam) {
|
public void add(MockConfigAddParam mockConfigAddParam) {
|
||||||
MockConfig mockConfig = BeanUtil.toBean(mockConfigAddParam, MockConfig.class);
|
MockConfig mockConfig = BeanUtil.toBean(mockConfigAddParam, MockConfig.class);
|
||||||
|
// 更新缓存
|
||||||
|
cacheService.put(mockConfig.getCacheKey(), mockConfig);
|
||||||
this.save(mockConfig);
|
this.save(mockConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,13 +94,33 @@ public class MockConfigServiceImpl extends ServiceImpl<MockConfigMapper, MockCon
|
|||||||
@Override
|
@Override
|
||||||
public void edit(MockConfigEditParam mockConfigEditParam) {
|
public void edit(MockConfigEditParam mockConfigEditParam) {
|
||||||
MockConfig mockConfig = this.queryEntity(mockConfigEditParam.getId());
|
MockConfig mockConfig = this.queryEntity(mockConfigEditParam.getId());
|
||||||
|
// 记录旧的缓存键(如果路径或方法被更新,需要失效旧缓存)
|
||||||
|
String oldCacheKey = mockConfig.getCacheKey();
|
||||||
|
// 验证JSON格式(如果提供)
|
||||||
|
if (mockConfigEditParam.getResponseJson() != null) {
|
||||||
|
validateJson(mockConfigEditParam.getResponseJson());
|
||||||
|
}
|
||||||
|
// 如果路径或方法改变了,也要失效新的缓存键
|
||||||
|
String newCacheKey = mockConfigEditParam.getCacheKey();
|
||||||
|
if (!oldCacheKey.equals(newCacheKey)) {
|
||||||
|
cacheService.invalidate(newCacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
BeanUtil.copyProperties(mockConfigEditParam, mockConfig);
|
BeanUtil.copyProperties(mockConfigEditParam, mockConfig);
|
||||||
|
|
||||||
|
// 更新缓存
|
||||||
|
cacheService.put(newCacheKey, mockConfig);
|
||||||
this.updateById(mockConfig);
|
this.updateById(mockConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@Override
|
@Override
|
||||||
public void delete(List<MockConfigIdParam> mockConfigIdParamList) {
|
public void delete(List<MockConfigIdParam> mockConfigIdParamList) {
|
||||||
|
for (MockConfigIdParam configIdParam : mockConfigIdParamList) {
|
||||||
|
MockConfig mockConfig = this.queryEntity(configIdParam.getId());
|
||||||
|
// 失效缓存
|
||||||
|
cacheService.invalidate(mockConfig.getCacheKey());
|
||||||
|
}
|
||||||
// 执行删除
|
// 执行删除
|
||||||
this.removeByIds(CollStreamUtil.toList(mockConfigIdParamList, MockConfigIdParam::getId));
|
this.removeByIds(CollStreamUtil.toList(mockConfigIdParamList, MockConfigIdParam::getId));
|
||||||
}
|
}
|
||||||
@@ -110,4 +146,25 @@ public class MockConfigServiceImpl extends ServiceImpl<MockConfigMapper, MockCon
|
|||||||
.eq(MockConfig::getApiMethod, apiMethod);
|
.eq(MockConfig::getApiMethod, apiMethod);
|
||||||
return Optional.ofNullable(getOne(wrapper));
|
return Optional.ofNullable(getOne(wrapper));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证JSON格式
|
||||||
|
*
|
||||||
|
* @param json JSON字符串
|
||||||
|
* @throws IllegalArgumentException 如果JSON格式无效
|
||||||
|
*/
|
||||||
|
private void validateJson(String json) {
|
||||||
|
if (json == null || json.trim().isEmpty()) {
|
||||||
|
log.error("JSON string is null or empty");
|
||||||
|
throw new IllegalArgumentException("Response JSON cannot be null or empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
objectMapper.readTree(json);
|
||||||
|
log.debug("JSON validation passed");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Invalid JSON format: {}", e.getMessage());
|
||||||
|
throw new IllegalArgumentException("Invalid JSON format: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -714,12 +714,8 @@ public class GlobalConfigure implements WebMvcConfigurer {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
// log.info("Registering MockInterceptor");
|
|
||||||
|
|
||||||
registry.addInterceptor(mockInterceptor)
|
registry.addInterceptor(mockInterceptor)
|
||||||
.addPathPatterns("/**") // 拦截所有路径
|
.addPathPatterns("/**") // 拦截所有路径
|
||||||
.excludePathPatterns(CollectionUtil.newArrayList(NO_CHECK_MOCK));
|
.excludePathPatterns(CollectionUtil.newArrayList(NO_CHECK_MOCK));
|
||||||
|
|
||||||
// log.info("MockInterceptor registered successfully");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user