前端接口业务如何优雅的使用缓存

业务并发量挺大的,为了提高性能我就在业务中多数地方使用缓存(大部分还是一些配置情况下用,这部分基本不会改变,偶尔改变一次我也提供了接口供后台手动刷新)

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);
    }
}


  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值