当前位置: 首页 > wzjs >正文

云空间可以做网站西安seo报价

云空间可以做网站,西安seo报价,西安网站开发公司有哪家,wordpress 样式引用引言:为什么需要声明式缓存? 背景痛点:传统代码中缓存逻辑与业务逻辑高度耦合,存在重复代码、维护困难等问题(如手动判断缓存存在性、序列化/反序列化操作) 解决方案:通过注解AOP实现缓存逻辑与…
引言:为什么需要声明式缓存?
  • 背景痛点:传统代码中缓存逻辑与业务逻辑高度耦合,存在重复代码、维护困难等问题(如手动判断缓存存在性、序列化/反序列化操作) 
  • 解决方案:通过注解+AOP实现缓存逻辑与业务解耦,开发者只需关注业务,通过注解配置缓存策略(如过期时间、防击穿机制等) 
  • 技术价值:提升代码可读性、降低维护成本、支持动态缓存策略扩展。

核心流程设计

方法调用 → 切面拦截 → 生成缓存Key → 查询Redis → 
└ 命中 → 直接返回缓存数据
└ 未命中 → 加锁查DB → 结果写入Redis → 返回数据
二、核心实现步骤
1. 定义自定义缓存注解(如@RedisCache)
package com.mixchains.ytboot.common.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;/*** @author 卫相yang* OverSion03*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisCache {/*** Redis键前缀(支持SpEL表达式)*/String key();/*** 过期时间(默认1天)*/long expire() default 1;/*** 时间单位(默认天)*/TimeUnit timeUnit() default TimeUnit.DAYS;/*** 是否缓存空值(防穿透)*/boolean cacheNull() default true;
}
2. 编写AOP切面(核心逻辑)
  • 切面职责

    • 缓存Key生成:拼接类名、方法名、参数哈希(MD5或SpEL动态参数)本次使用的是SpEL
    • 缓存查询:优先从Redis读取,使用FastJson等工具反序列化  
  • 空值缓存:缓存NULL值并设置短过期时间,防止恶意攻击
    package com.mixchains.ytboot.common.aspect;import com.alibaba.fastjson.JSON;
    import com.mixchains.ytboot.common.annotation.RedisCache;
    import io.micrometer.core.instrument.util.StringUtils;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.DefaultParameterNameDiscoverer;
    import org.springframework.core.ParameterNameDiscoverer;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.expression.EvaluationContext;
    import org.springframework.expression.ExpressionParser;
    import org.springframework.expression.spel.standard.SpelExpressionParser;
    import org.springframework.expression.spel.support.StandardEvaluationContext;
    import org.springframework.stereotype.Component;import java.lang.reflect.Method;
    import java.lang.reflect.Type;/*** @author 卫相yang* OverSion03*/
    @Aspect
    @Component
    @Slf4j
    public class RedisCacheAspect {@Autowiredprivate RedisTemplate<String, String> redisTemplate;private final ExpressionParser parser = new SpelExpressionParser();private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();@Around("@annotation(redisCache)")public Object around(ProceedingJoinPoint joinPoint, RedisCache redisCache) throws Throwable {Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();// 解析SpEL表达式生成完整keyString key = parseKey(redisCache.key(), method, joinPoint.getArgs());// 尝试从缓存获取String cachedValue = redisTemplate.opsForValue().get(key);if (StringUtils.isNotBlank(cachedValue)) {Type returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();return JSON.parseObject(cachedValue, returnType);}// 执行原方法Object result = joinPoint.proceed();// 处理缓存存储if (result != null || redisCache.cacheNull()) {String valueToCache = result != null ?JSON.toJSONString(result) :(redisCache.cacheNull() ? "[]" : null);if (valueToCache != null) {redisTemplate.opsForValue().set(key,valueToCache,redisCache.expire(),redisCache.timeUnit());}}return result;}private String parseKey(String keyTemplate, Method method, Object[] args) {String[] paramNames = parameterNameDiscoverer.getParameterNames(method);EvaluationContext context = new StandardEvaluationContext();if (paramNames != null) {for (int i = 0; i < paramNames.length; i++) {context.setVariable(paramNames[i], args[i]);}}return parser.parseExpression(keyTemplate).getValue(context, String.class);}
    }
    

    代码片段示例

     @RedisCache(key = "'category:homeSecond:' + #categoryType",  //缓存的Key + 动态参数expire = 1, //过期时间timeUnit = TimeUnit.DAYS // 时间单位)@Overridepublic ReturnVO<List<GoodsCategory>> listHomeSecondGoodsCategory(Integer level, Integer categoryType) {// 数据库查询List<GoodsCategory> dbList = goodsCategoryMapper.selectList(new LambdaQueryWrapper<GoodsCategory>().eq(GoodsCategory::getCategoryLevel, level).eq(GoodsCategory::getCategoryType, categoryType).eq(GoodsCategory::getIsHomePage, 1).orderByDesc(GoodsCategory::getHomeSort));// 设置父级UUID(可优化为批量查询)List<Long> parentIds = dbList.stream().map(GoodsCategory::getParentId).distinct().collect(Collectors.toList());Map<Long, String> parentMap = goodsCategoryMapper.selectBatchIds(parentIds).stream().collect(Collectors.toMap(GoodsCategory::getId, GoodsCategory::getUuid));dbList.forEach(item -> item.setParentUuid(parentMap.get(item.getParentId())));return ReturnVO.ok("列出首页二级分类", dbList);}

    最终效果:

http://www.dtcms.com/wzjs/511579.html

相关文章:

  • 手机网站模板图片免费seo排名网站
  • 安徽省建设工程信息网平台官网苏州网络推广seo服务
  • 单位的网站的建设方案宁波的网络营销服务公司
  • 网站建设合集免费自助建站哪个最好
  • 兴城做网站推广的成都网站搜索排名优化公司
  • 某网站建设策划方案网络营销的内容有哪些方面
  • 番禺人才网单位招考杭州网络推广网络优化
  • 学校网站建设合同sem运营有出路吗
  • 四川做网站有哪些公司网站设计公司上海
  • 网站建设人员工作要求seo专业课程
  • 淘宝网站上的图片是怎么做的网络推广文案怎么写
  • 唐河网站制作公司东莞网站建设工作
  • 成都 企业网站建设公司高端网站制作
  • js商城网站武汉百度seo网站优化
  • 淘宝上的网站建设百度购物平台客服电话
  • 图书馆网站建设目标免费推广论坛
  • 网站内页seo查询google开户
  • 企业形象网站开发宁波seo搜索引擎优化
  • 网站建设 app班级优化大师是干什么用的
  • 网站开发东莞百度热线电话
  • 河南省建设银行网站年报小型培训机构管理系统
  • 怎么做二十八页美食网站网站seo推广公司靠谱吗
  • txt怎么做pdf电子书下载网站b2b b2c c2c o2o区别
  • 建设网站需要学习什么淘宝指数
  • php购物网站开发设计与实现青岛seo推广公司
  • 网络公司网站样本杭州排名优化公司电话
  • 服装定制网站的设计与实现seo 视频
  • 网帆网站建设网站排名顾问
  • 做视频up主视频网站百度排名怎么做
  • 织梦网站访问量统计代码郑州百度快照优化排名