springboot博客實戰筆記02

一、評論功能:

注意要先登錄之后才能進行評論,所有把評論加入到登錄攔截器當中

@Overridepublic void addInterceptors(InterceptorRegistry registry) {//攔截test接口,后續實際遇到需要攔截的接口時,在配置為真正的攔截接口registry.addInterceptor(loginInterceptor).addPathPatterns("/test").addPathPatterns("/comments/create/change");}
  • 在登錄攔截器LoginInterceptor里面存入了用戶信息:
  //登錄成功 放行//我希望再controller中 直接獲取用戶的信息  怎么獲取UserThreadLocal.put(sysUser);
  • 后續在評論的實現類里面可以用gei方法獲取到 用戶信息 充當評論人
 //這里直接在線程里面找到登錄時候保存的用戶信息SysUser sysUser = UserThreadLocal.get();

1.根據文章id查詢評論

    @Overridepublic Result commentsByArticleId(Long id) {/*** 1.根據文章id 查詢評論列表 從comments表中查詢-* 2.根據作者的id 查詢作者的信息* 3.判斷  如果 level = 1 要去查詢它有沒有子評論* 4.如果 有 根據評論id  進行查詢(parent_id)*/LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(Comment::getArticleId,id);queryWrapper.eq(Comment::getLevel,1);List<Comment> comments = commentMapper.selectList(queryWrapper);List<CommentVo> commentVoList = copyList(comments);return Result.success(commentVoList);}
private List<CommentVo> findCommentsByParentId(Long id) {LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(Comment::getParentId,id);queryWrapper.eq(Comment::getLevel,2);List<Comment> comments = commentMapper.selectList(queryWrapper);return copyList(comments);}

將pojo —> vo的方法,這里有個小巧思,分為level大于1和等于1的情況,當level等于1時,說明可能是樓主,會有子評論

private List<CommentVo> copyList(List<Comment> comments) {List<CommentVo> commentVoList = new ArrayList<>();for (Comment comment : comments) {commentVoList.add(copy(comment));}return  commentVoList;}private CommentVo copy(Comment comment) {CommentVo commentVo = new CommentVo();BeanUtils.copyProperties(comment,commentVo);commentVo.setId(String.valueOf(comment.getId()));//作者信息Long authorId = comment.getAuthorId();UserVo userVo = this.sysUserService.findUserVoById(authorId);commentVo.setAuthor(userVo);//子評論Integer level = comment.getLevel();if( 1 == level){Long id = Long.valueOf(comment.getId());List<CommentVo> commentVoList = findCommentsByParentId(id);commentVo.setChildrens(commentVoList);}//to User 給誰評論if(level >1){Long toUid = comment.getToUid();UserVo toUserVo = this.sysUserService.findUserVoById(toUid);commentVo.setToUser(toUserVo);}return commentVo;}

精度損失問題

當數據庫用的是分布式id的時候,前端會出現精度損失問題,導致找不到正確的id 此時需要在實體類中,添加相關注解,把id轉為string,(分布式id 比較長,傳到前端 會有精度損失,必須轉為string類型,進行運輸,就不會有問題了

    //防止前端精度損失 把id轉為string@JsonSerialize(using = ToStringSerializer.class)private Long id;

二、發布文章

也需要登錄過后才能發布文章,

 registry.addInterceptor(loginInterceptor).addPathPatterns("/test").addPathPatterns("/comments/create/change").addPathPatterns("/articles/publish");
 @Overridepublic Result publish(ArticleParam articleParam) {/*** 1.發布文章  目的 構建Article對象* 2.作者id 當前的登錄用戶* 3.標簽 要將標簽加入到 關聯表中* 4.body 內容存儲**/SysUser sysUser = UserThreadLocal.get();//登錄的用戶id就是作者id 而登錄的用戶 可以去線程中找Article article = new Article();article.setAuthorId(Long.valueOf(sysUser.getId()));article.setWeight(Article.Article_Common);article.setViewCounts(0);article.setTitle(articleParam.getTitle());article.setSummary(articleParam.getSummary());article.setCommentCounts(0);article.setCreateDate(System.currentTimeMillis());article.setCategoryId(Long.valueOf(articleParam.getCategory().getId()));//插入之后會生成一個文章idthis.articleMapper.insert(article);//tagList<TagVo> tags = articleParam.getTags();if(tags!=null){for (TagVo tag : tags) {Long articleId = Long.valueOf(article.getId());ArticleTag articleTag = new ArticleTag();articleTag.setTagId(Long.valueOf(tag.getId()));articleTag.setArticleId(articleId);articleTagMapper.insert(articleTag);}}//bodyArticleBody articleBody = new ArticleBody();articleBody.setArticleId(Long.valueOf(article.getId()));articleBody.setContent(articleParam.getBody().getContent());articleBody.setContentHtml(articleParam.getBody().getContentHtml());articleBodyMapper.insert(articleBody);article.setBodyId(Long.valueOf(articleBody.getId()));articleMapper.updateById(article);//方法1 articleVo
//        ArticleVo articleVo = new ArticleVo();
//        articleVo.setId(article.getId());
//        return Result.success(articleVo);//方法2Map<String,String> map = new HashMap<>();map.put("id",article.getId().toString());//返回字符串避免精度損失問題return Result.success(map);}

三、AOP日志

對于 IoC 的一種補充,面向切面編程,簡化程序的一種方式
IoC 簡化代碼量,AOP 實現解耦合的
讓代碼變得松散,靈活,更方便擴展和維護
日志輸出和業務計算混合在一起,耦合在一起,不方便維護
解耦合,把日志輸出和業務計算的代碼進行分離
最終程序運行的時候,結果還要合到一起

1.在需要記錄日志的controller上添加注解

    @PostMapping//加上此注解 代表要對此接口記錄日志@LogAnnotation(module="文章",operator="獲取文章列表")public Result listArticle(@RequestBody PageParams pageParams){return articleService.listArticle(pageParams);}

2.創建aop包,并且創建annotation類

在這里插入圖片描述

在這里插入圖片描述

package com.mszlu.blog.common.aop;import java.lang.annotation.*;//Type 代表可以放在類上面 Method代表可以放在方法上面
//ElementType.Type ElementType.METHOD
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {String module() default "";String operator() default "";
}

3.開花AOP創建LogAspect類

package com.mszlu.blog.common.aop;import com.alibaba.fastjson.JSON;
import com.mszlu.blog.common.aop.LogAnnotation;
import com.mszlu.blog.utils.HttpContextUtils;
import com.mszlu.blog.utils.IpUtils;
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.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;@Component//讓spring識別到
@Aspect//切面 定義了通知和切點的關系
@Slf4j
public class LogAspect {@Pointcut("@annotation(com.mszlu.blog.common.aop.LogAnnotation)")public void pt(){}@Around("pt()")public Object log(ProceedingJoinPoint joinPoint) throws Throwable {long beginTime = System.currentTimeMillis();//執行方法Object result = joinPoint.proceed();//執行時長(毫秒)long time = System.currentTimeMillis() - beginTime;//保存日志recordLog(joinPoint, time);return result;}private void recordLog(ProceedingJoinPoint joinPoint, long time) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);log.info("=====================log start================================");log.info("module:{}",logAnnotation.module());log.info("operator:{}",logAnnotation.operator());//請求的方法名String className = joinPoint.getTarget().getClass().getName();String methodName = signature.getName();log.info("request method:{}",className + "." + methodName + "()");//        //請求的參數Object[] args = joinPoint.getArgs();String params = JSON.toJSONString(args[0]);log.info("params:{}",params);//獲取request 設置IP地址HttpServletRequest request = HttpContextUtils.getHttpServletRequest();log.info("ip:{}", IpUtils.getIpAddr(request));log.info("excute time : {} ms",time);log.info("=====================log end================================");}}

四、上傳圖片


@RestController
@RequestMapping("upload")
public class UploadController {@Autowiredprivate QiniuUtils qiniuUtils;@PostMapping()public Result upload(@RequestParam("image")MultipartFile file){//原始文件名稱 比如aa.pngString originalFilename = file.getOriginalFilename();String fileName = UUID.randomUUID()+toString()+"."+ StringUtils.substringAfterLast(originalFilename,".");//上傳文件 上傳在哪兒?//七牛云  云服務器 按量付費 幅度快 把圖片發到離用戶最近的服務器上//降低 我們自身應用服務器的寬帶消耗boolean upload = qiniuUtils.upload(file,fileName);if(upload){return Result.success(QiniuUtils.url+fileName);}return Result.fail(20001,"上傳失敗");}

我們用的平臺是七牛云 首先先要導入依賴:

 <dependency><groupId>com.qiniu</groupId><artifactId>qiniu-java-sdk</artifactId><version>[7.7.0, 7.7.99]</version></dependency>
  • QiniuUtils

@Component
public class QiniuUtils {public static  final String url = "http://t0oltruo7.hn-bkt.clouddn.com/";@Value("${qiniu.accessKey}")private  String accessKey;@Value("${qiniu.accessSecretKey}")private  String accessSecretKey;public  boolean upload(MultipartFile file,String fileName){//構造一個帶指定 Region 對象的配置類Configuration cfg = new Configuration(Region.huanan());//...其他參數參考類注釋UploadManager uploadManager = new UploadManager(cfg);//...生成上傳憑證,然后準備上傳String bucket = "danb24";//默認不指定key的情況下,以文件內容的hash值作為文件名try {byte[] uploadBytes = file.getBytes();Auth auth = Auth.create(accessKey, accessSecretKey);String upToken = auth.uploadToken(bucket);Response response = uploadManager.put(uploadBytes, fileName, upToken);//解析上傳成功的結果DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);return true;} catch (Exception ex) {ex.printStackTrace();}return false;}
}

注意點

  • url就是你在七牛云創建的域名 “http://t0oltruo7.hn-bkt.clouddn.com/”;
  • accessKey和SecretKey在七牛云中獲得 并且配置在在properties或者直接賦值(不推薦)
    qiniu.accessKey=NnneEoseKEAqkNNFuaMYWIBU7gn0xdVUbGuBjmGU
    qiniu.accessSecretKey=G5NBjBLd3OdttFet71AGxjbpahwduNpom_amLe1G
  • bucket 修改為自己的文件名
  • 也可以在配置文件中限制上傳文件的值
    #上傳文件總的最大值
    spring.servlet.multipart.max-request-size=20MB
    #單個文件的最大值
    spring.servlet.multipart.max-file-size=2MB

統一緩存處理(優化)

1.cache包下Cache

package com.mszlu.blog.common.cache;import java.lang.annotation.*;//
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Cache {long expire() default 1 * 60 * 1000;//緩存標識KeyString name() default "";}

2.cache包下CacheAspect

package com.mszlu.blog.common.cache;import com.alibaba.fastjson.JSON;
import com.mszlu.blog.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.time.Duration;
//aop定義了一個切面  切面定義了切點和通知的關系
@Aspect
@Component
@Slf4j
public class CacheAspect {@Autowiredprivate RedisTemplate<String, String> redisTemplate;//切點@Pointcut("@annotation(com.mszlu.blog.common.cache.Cache)")public void pt(){}//環繞@Around("pt()")public Object around(ProceedingJoinPoint pjp){try {Signature signature = pjp.getSignature();//類名String className = pjp.getTarget().getClass().getSimpleName();//調用的方法名String methodName = signature.getName();Class[] parameterTypes = new Class[pjp.getArgs().length];Object[] args = pjp.getArgs();//參數String params = "";for(int i=0; i<args.length; i++) {if(args[i] != null) {params += JSON.toJSONString(args[i]);parameterTypes[i] = args[i].getClass();}else {parameterTypes[i] = null;}}if (StringUtils.isNotEmpty(params)) {//加密 以防出現key過長以及字符轉義獲取不到的情況params = DigestUtils.md5Hex(params);}Method method = pjp.getSignature().getDeclaringType().getMethod(methodName, parameterTypes);//獲取Cache注解Cache annotation = method.getAnnotation(Cache.class);//緩存過期時間long expire = annotation.expire();//緩存名稱String name = annotation.name();//先從redis獲取String redisKey = name + "::" + className+"::"+methodName+"::"+params;String redisValue = redisTemplate.opsForValue().get(redisKey);if (StringUtils.isNotEmpty(redisValue)){log.info("走了緩存~~~,{},{}",className,methodName);return JSON.parseObject(redisValue, Result.class);}Object proceed = pjp.proceed();redisTemplate.opsForValue().set(redisKey,JSON.toJSONString(proceed), Duration.ofMillis(expire));log.info("存入緩存~~~ {},{}",className,methodName);return proceed;} catch (Throwable throwable) {throwable.printStackTrace();}return Result.fail(-999,"系統錯誤");}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/918744.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/918744.shtml
英文地址,請注明出處:http://en.pswp.cn/news/918744.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ThinkPHP+Mysql 靈活用工小程序-技術深度解析與實踐指南

一、模塊設計分包商&#xff1a;稅地注冊公司&#xff0c;用于在當地申請有利的稅收政策&#xff0c;是實際報稅公司。 代理商&#xff1a;代理商可以邀請客戶使用本平臺&#xff0c;平臺會給予代理商一定的服務費差價作為傭金。 客戶&#xff1a;使用本平臺進行工資發放的…

開源數據發現平臺:Amundsen 第1部分:基礎入門與本地環境設置

Amundsen 是一個數據發現和元數據引擎&#xff0c;旨在提高數據分析師、數據科學家和工程師與數據交互時的生產力。目前&#xff0c;它通過索引數據資源&#xff08;表格、儀表板、數據流等&#xff09;并基于使用模式&#xff08;例如&#xff0c;查詢頻率高的表格會優先于查詢…

Linux編程--進程

1、基本概念&#xff1a;進程&#xff1a;是程序動態執行的過程&#xff0c;包括創建、調度、消亡程序&#xff1a;存放在外存中一段數據的集合虛擬地址&#xff1a;進程使用的邏輯地址&#xff0c;有操作系統管理&#xff0c;不直接對應物理內存物理地址&#xff1a;實際內存的…

【開源工具】基于硬件指紋的“一機一碼”軟件授權系統全實現(附完整源碼)

?? 緊急預警!你的軟件正在被白嫖?這套Python軟件加密授權方案讓破解者當場崩潰 ?? 個人主頁:創客白澤 - CSDN博客 ?? 系列專欄:??《Python開源項目實戰》 ?? 熱愛不止于代碼,熱情源自每一個靈感閃現的夜晚。愿以開源之火,點亮前行之路。 ?? 希望大家多多支持…

機器學習算法篇(八)-------svm支持向量機

目錄 ??1. SVM 的核心原理&#xff08;必須掌握&#xff09;?? ??2. Python 中的實踐重點?? ??(1) Scikit-learn 的 SVM 實現?? ??(2) 數據預處理?? ??(3) 模型評估與調優?? ??3. 學習側重點優先級?? ??4. 經典案例實踐方向?? ??5. 學習…

發票查驗接口接收參數說明-PHP語言集成-財務管理

發票驗真服務接口可實時聯網核驗發票真偽&#xff0c;查驗一致時返回全票面信息。其支持核驗增值稅發票管理系統開具發票的真偽&#xff0c;且能進行發票批量查驗&#xff0c;當日開具的發票當日即可查驗。同時&#xff0c;結合發票識別接口可實現自動識別發票信息核驗&#xf…

Uniapp物聯網平臺登錄與溫濕度監測系統

下面是一個完整的Uniapp物聯網平臺實現&#xff0c;包含登錄功能和溫濕度監測系統。這個解決方案采用現代化UI設計&#xff0c;模擬了物聯網平臺的核心功能。文章末尾提供源碼下載。 系統功能說明 這個Uniapp物聯網平臺登錄與溫濕度監測系統包含以下核心功能&#xff1a; 1.…

【企業架構】TOGAF概念之四(終結)

導讀&#xff1a;學習TOGAF&#xff08;The Open Group Architecture Framework&#xff0c;開放組架構框架&#xff09;相關概念的意義和價值&#xff0c;體現在它為企業架構&#xff08;Enterprise Architecture, EA&#xff09;實踐提供了標準化方法論、跨領域協同框架、戰略…

centos 怎么部署 vscode 網頁版

安裝編譯工具 下載適用于 linux 版本的 rpm 格式文件 下載 Visual Studio Tools - 免費安裝 Windows、Mac、Linux 拷貝路徑&#xff0c;下載文件 wget https://vscode.download.prss.microsoft.com/dbazure/download/stable/e3550cfac4b63ca4eafca7b601f0d2885817fd1f/code…

sql的關鍵字 limit 和offset

核心概念LIMIT (限制): 指定查詢最多返回多少行記錄。OFFSET (偏移): 指定在開始返回記錄之前要跳過多少行記錄。它定義了結果集的起始點。核心前提&#xff1a; 必須 使用 ORDER BY 子句來確保分頁結果的順序穩定和可預測。示例&#xff1a; 假設 employees 表有 100 條記錄&a…

git config的配置全局或局部倉庫的參數: local, global, system

git config的范圍參數: local, global, system1. --local: 作用于當前倉庫2. --global: 作用于當前用戶的全局范圍的 Git 倉庫3. --system: 作用于系統范圍內的 Git 倉庫4. 注意事項參考鏈接1. --local: 作用于當前倉庫 --local: 這個參數的作用范圍是當前倉庫。其配置的參數保…

應用系統連達夢數據庫報“服務器模式不匹配”的根源與修復方案

近期遇到很多個應用系統連接達夢數據庫報“服務器模式不匹配”的問題&#xff0c;省流直接說文章結論通常兩種場景 初次連接達夢數據庫時報服務器模式不匹配&#xff0c;可能是配置文件中LOGIN_MODE參數配置與數據庫狀態不一致導致連接失敗應用系統正常運行負載大或者偶發報服務…

git:分支

分支命名可以使用斜杠(/)構建分層命名方案不能以減號(-)開頭&#xff0c;分層的命名不能以點(.)開頭不能使用連接兩個點(.)不能包括空格或其他空白字符以及~ ^ : ? * [列出分支名稱 git branch 列出本地版本庫的分支git branch -r 列出遠程跟蹤分支git branch -a …

T05_卷積神經網絡

全連接網絡存的弊端 以MINST數字識別為例&#xff0c;創建一個4層全連接網絡層&#xff0c;輸入為28x28&#xff0c;中間三個隱藏層的節點數都是 256&#xff0c;輸出節點數是10。通過summary()函數打印出模型每一層的參數量&#xff0c;計算總的參數量超過34萬個網絡參數&…

區塊鏈在可信空間智能合約中的應用

區塊鏈在可信數據空間的智能合約應用,通過去中心化信任機制、自動化執行、可驗證計算等特性,正在重塑數據存儲、共享、交易和治理的模式。以下是其核心應用方向、關鍵技術及落地案例的深度解析: 一、核心應用方向 1. 數據確權與授權管理 應用場景 個人數據主權:用戶通過智…

pycharm配置python解釋器教程

一個解釋器對應一個環境&#xff0c;無論是conda環境或是Python環境。python環境的解釋器的路徑形如"D:\Python3.12\python.exe"&#xff0c;conda環境的解釋器的路徑形如"D:\anaconda3\envs\opencv\python.exe"。 如何在Pycharm中設置解釋器 打開pycharm&…

C#教程之NPOI讀寫excel文件XLS,XLSX格式

NPOI 是開源的 POI 項目的.NET版&#xff0c;可以用來讀寫Excel&#xff0c;Word&#xff0c;PPT文件。僅需處理 XLS/XLSX 格式的文本和數字讀寫&#xff0c;最少需要加載 2 個核心 DLL&#xff1a;NPOI.dll包含所有格式的通用接口&#xff08;IWorkbook、ISheet、IRow、ICell …

Perforce P4 Git 連接器

Perforce P4 Git連接器將Git代碼庫與數字資產集中存儲于Perforce P4&#xff08;前身為Helix Core&#xff09;&#xff0c;為所有數字資產&#xff08;源碼二進制文件&#xff09;構建單一事實來源。 突破代碼庫與文件限制 當藝術家、開發者及工程師組成的大型團隊僅使用Git時…

day10_尋找用戶推薦人

一、題目給出一張customer表&#xff0c;里面有id&#xff08;客戶id&#xff09;——主鍵&#xff0c;name&#xff08;客戶姓名&#xff09;&#xff0c;referee_id&#xff08;推薦人客戶id&#xff09;三個字段二、題目要求1、找出被id不是2的用戶推薦的客戶姓名2、沒有被任…

python爬蟲(三)----Selenium

目錄 1. Selenium 1.1 Selenium是啥 1.2 安裝chrom Driver 1.3 selenium 使用 1.4 selenium元素定位 1.5 訪問元素信息 1.6 交互 2. Phantomjs、Chrom handless 1. Selenium 1.1 Selenium是啥 自動化Web瀏覽器操作 主要用于Web應用程序的測試 支持多操作系統、多瀏覽器…