• 码神之路项目总结(四)


    目录

    一、图片上传

    二、导航--文章分类

    三、导航--文章标签

    四、导航--文章归档

    五、统一缓存处理


    一、图片上传

    请求接口:

    思路:

    1、后端用MultipartFile接收前端传过来的文件信息

    2、用uuid将文件重命名,然后将文件以新文件名通过七牛云上传到七牛云服务器 

    二、导航--文章分类

    请求接口:

    思路:

    1、直接从文章分类表里面查出全部的分类返回给前端即可

    三、导航--文章标签

    请求接口:

    思路:

    1、直接从标签表里面查出全部的标签返回给前端页面即可· 

    四、导航--文章归档

     请求接口:

     思路:

    导航文章归档涉及到两个接口。查询内容那个接口就是首页列表的那个接口;左侧文章归档是文章归档那个接口,接下来讲解的就是这个接口

    1、前端页面请求文章归档,我们需要自定义文章表的接口

    2、将文章表的创建时间当做突破点,使用函数将创作时间分为年份和月份,然后再以年份和月份分组,用count(*)统计每组的文章数量,然后将年份、月份、每组的文章数量返回给前端页面

    五、统一缓存处理

    作用:可以加快请求的处理进度,我们把方法的返回结果存入redis中,下次再请求这个方法时直接返回结果加快了请求处理速度

    思路:

    1、老样子自定义缓存注解

    1. /**
    2. * @Description: 缓存注解
    3. * @Author: 李传城
    4. * @Date: 2022/11/4
    5. * @Time: 9:42
    6. */
    7. @Target({ElementType.METHOD})
    8. @Retention(RetentionPolicy.RUNTIME)
    9. @Documented
    10. public @interface Cache {
    11. long expire() default 1 * 60 * 1000;
    12. String name() default "";
    13. }

    2、使用AOP实现缓存,在切面中绑定切入点和通知,切入点即自定义注解

    1. /**
    2. * @description: 缓存切面
    3. * @author: 李传城
    4. * @date: 2022-11-04 09:25
    5. */
    6. @Aspect
    7. @Component
    8. @Slf4j
    9. public class CacheAspect {
    10. @Autowired
    11. private RedisTemplate redisTemplate;
    12. //1、切入点
    13. @Pointcut("@annotation(com.mszlu.blog.common.cache.Cache)")
    14. public void pt(){}
    15. //2、通知 通知中缓存方法结果
    16. @Around("pt()")
    17. public Object around(ProceedingJoinPoint pjp){
    18. try {
    19. Signature signature = pjp.getSignature();
    20. //类名
    21. String className = pjp.getTarget().getClass().getSimpleName();
    22. //调用的方法名
    23. String methodName = signature.getName();
    24. Class[] parameterTypes = new Class[pjp.getArgs().length];
    25. Object[] args = pjp.getArgs();
    26. //参数
    27. String params = "";
    28. for(int i=0; i
    29. if(args[i] != null) {
    30. params += JSON.toJSONString(args[i]);
    31. parameterTypes[i] = args[i].getClass();
    32. }else {
    33. parameterTypes[i] = null;
    34. }
    35. }
    36. if (StringUtils.isNotEmpty(params)) {
    37. //加密 以防出现key过长以及字符转义获取不到的情况
    38. params = DigestUtils.md5Hex(params);
    39. }
    40. Method method = pjp.getSignature().getDeclaringType().getMethod(methodName, parameterTypes);
    41. //获取Cache注解
    42. Cache annotation = method.getAnnotation(Cache.class);
    43. //缓存过期时间
    44. long expire = annotation.expire();
    45. //缓存名称
    46. String name = annotation.name();
    47. //先从redis获取
    48. String redisKey = name + "::" + className+"::"+methodName+"::"+params;
    49. String redisValue = redisTemplate.opsForValue().get(redisKey);
    50. if (StringUtils.isNotEmpty(redisValue)){
    51. log.info("走了缓存~~~,{},{}",className,methodName);
    52. return JSON.parseObject(redisValue, Result.class);
    53. }
    54. Object proceed = pjp.proceed();
    55. redisTemplate.opsForValue().set(redisKey,JSON.toJSONString(proceed), Duration.ofMillis(expire));
    56. log.info("存入缓存~~~ {},{}",className,methodName);
    57. return proceed;
    58. } catch (Throwable throwable) {
    59. throwable.printStackTrace();
    60. }
    61. return Result.fail(-999,"系统错误");
    62. }
    63. }

    3、在想使用缓存的方法上,添加自定义注解即可实现缓存

  • 相关阅读:
    java并发包的基石:AbstractQueuedSychronier及synchornized
    ChatGPT批量写作文章软件
    MySQL8 创建函数报错:This function has none of DETERMINISTIC
    单线程模型想象不到的高并发能力、多路复用是效率杠杆
    【3D 图像分类】基于 Pytorch 的 3D 立体图像分类4(多人标注的结节立体框合并和特征等级投票)
    Docker Rootfs
    程序员 保 密 协 议 书
    升余弦滤波器的FPGA实现
    通讯录和内存动态管理
    Arduino框架下ESP32使用固件自带的SD库的总结
  • 原文地址:https://blog.csdn.net/weixin_51930617/article/details/127876110