业务并发量挺大的,为了提高性能我就在业务中多数地方使用缓存(大部分还是一些配置情况下用,这部分基本不会改变,偶尔改变一次我也提供了接口供后台手动刷新)
1、CommonCacheService
使用到缓存处理的Service都要实现这个类
/**
* 通用缓存服务
*/
public interface CommonCacheService {
/**
* 系统启动
*/
void init();
/**
* 刷新
*/
void refresh();
/**
* 清理
*/
void cleanup();
/**
* 每个Service实现自己的,通过此方法获取缓存前缀
* 此方法虽然可以做成静态,但为了结构规范才这样做...
* @param key 缓存对应的key,可以是id或者标志
* @return redisCache Key
*/
String getCacheKey(String key);
}
2、CacheManager
用于清除缓存
/**
* 缓存Service管理器
*/
@Service("sdkCacheManager")
public class CacheManager {
@Autowired
private List<CommonCacheService> cacheServices;
/**
* 刷新所有缓存
*/
public void flushAll() {
for (CommonCacheService service : cacheServices) {
service.refresh();
}
}
/**
* 刷新指定类的缓存
* @param serviceClass 指定ServiceImpl
*/
public void flushService(Class<? extends CommonCacheService> serviceClass) {
for (CommonCacheService service : cacheServices) {
if (service.getClass().equals(serviceClass)) {
service.refresh();
break;
}
}
}
}
3、CacheController
暴露接口给前端调用,我们接口本身就是加密的,但这个接口单独暴露给管理中心用,所以手动执行了验签
/**
* SDK缓存刷新Controller
* 管理后台请求此接口刷新SDK缓存数据
* By XuanRan on 2024/02/21
*/
@RestController
@RequestMapping("/cacheManage")
public class CacheController {
@Autowired
private CacheManager cacheManager;
/**
* 请求加密前缀
*/
public static final String Ciphertext = "xxxxxx";
/**
* 刷新所有缓存,非必要不调用
* @return 结果
*/
@PostMapping("/flushAll")
public AjaxResult flushAll(HttpServletRequest request) {
if (checkSign(request)) {
AjaxResult.error("验签失败,请检查参数");
}
cacheManager.flushAll();
return AjaxResult.success();
}
/**
* 刷新指定ServiceImpl实现类的缓存处理
* @param serviceName ServiceImpl全路径
* @return 刷新结果
*/
@PostMapping("/flush/{serviceName}")
@SuppressWarnings("unchecked")
public AjaxResult flushService(@PathVariable String serviceName, HttpServletRequest request) {
if (checkSign(request)) {
AjaxResult.error("验签失败,请检查参数");
}
try {
Class<?> clazz = Class.forName(serviceName);
if (CommonCacheService.class.isAssignableFrom(clazz)) {
cacheManager.flushService((Class<? extends CommonCacheService>) clazz);
return AjaxResult.success();
} else {
return AjaxResult.error("目标类非缓存控制实现类");
}
} catch (ClassNotFoundException e) {
return AjaxResult.error("找不到目标处理器");
}
}
/**
* 检查Sign算法是否合法,只有合法Sign才能执行缓存刷新
* 规则:从请求头中拿到Sign和Time,使用Ciphertext + Time进行MD5后全部转小写
* 检查是否与前端传来的一致
* @param request request
* @return true不合法 false合法
*/
public static boolean checkSign(HttpServletRequest request) {
String sign = null;
long requestTime = 0;
try {
// 得到请求体Sign
sign = request.getHeader("sign");
// 得到请求时间
requestTime = Long.parseLong(request.getHeader("time"));
} catch (Exception e) {
return true;
}
// 计算哈希
String hash = Md5Utils.hash((Ciphertext + requestTime)).toLowerCase();
return !Objects.equals(sign, hash);
}
}