瑞吉外賣項目學習筆記(二)Swagger、logback、表單校驗和參數打印功能的實現

瑞吉外賣項目學習筆記(一)準備工作、員工登錄功能實現

文章目錄

  • 3 項目組件優化
    • 3.1 實現Swagger文檔輸出
    • 3.2 實現logback日志打印
    • 3.3 實現表單校驗功能
    • 3.4 實現請求參數和響應參數的打印

3 項目組件優化

3.1 實現Swagger文檔輸出

  • 1)在application.yml中增加knife4j配置
spring:mvc:pathmatch:matching-strategy: ANT_PATH_MATCHER
knife4j:enable: truetitle: 瑞吉外賣group: ruiji_takeoutdescription: 瑞吉外賣version: 1.0name: itweidurl:email:base-package: com.itweid.takeout.controller
  • 2)創建配置類SwaggerProperties類接收配置
@Data
@ConfigurationProperties(prefix = "knife4j")
public class SwaggerProperties {private String title = ""; //標題private String group = ""; //組名private String description = ""; //描述private String version = ""; //版本private String name = ""; // 聯系人private String url = ""; // 聯系人urlprivate String email = ""; // 聯系人emailprivate String basePackage = ""; //swagger會解析的包路徑private List<String> basePath = new ArrayList<>(); //swagger會解析的url規則private List<String> excludePath = new ArrayList<>(); //在basePath基礎上需要排除的url// 如果沒有填寫組名,則直接用標題作為組名public String getGroup() {if (group == null || group.isEmpty()) {return title;}return group;}
}
  • 3)創建自動配置類SwaggerAutoConfiguration進行初始化
@Configuration
@ConditionalOnProperty(name = "knife4j.enable", havingValue = "true", matchIfMissing = true)
@EnableSwagger2
@EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerAutoConfiguration implements BeanFactoryAware {@Autowiredprivate SwaggerProperties swaggerProperties;@Autowiredprivate BeanFactory beanFactory;@Bean@ConditionalOnMissingBeanpublic List<Docket> createRestApi(){ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;List<Docket> docketList = new LinkedList<>();ApiInfo apiInfo = new ApiInfoBuilder()// 頁面標題.title(swaggerProperties.getTitle())// 創建人.contact(new Contact(swaggerProperties.getName(),swaggerProperties.getUrl(),swaggerProperties.getEmail()))// 版本號.version(swaggerProperties.getVersion())// 描述.description(swaggerProperties.getDescription()).build();Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).groupName(swaggerProperties.getGroup()).select()// 為當前包路徑.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage())).paths(PathSelectors.any()).build();configurableBeanFactory.registerSingleton(swaggerProperties.getGroup(), docket);docketList.add(docket);return docketList;}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = beanFactory;}
}
  • 4)重新啟動項目,在瀏覽器訪問http://localhost:8081/doc.html,即可查看Swagger文檔:


在Swagger文檔的調試功能中,可以直接進行測試:

3.2 實現logback日志打印

  • 1)引入依賴
<!--logback-->
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version>
</dependency>
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.2.3</version>
</dependency>
  • 2)在resources目錄下創建配置文件

  • logback-base.xml

<?xml version="1.0" encoding="UTF-8"?>
<included><contextName>logback</contextName><!--name的值是變量的名稱,value的值時變量定義的值定義變量后,可以使“${}”來使用變量--><property name="log.path" value="logs" /><!-- 彩色日志 --><!-- 彩色日志依賴的渲染類 --><conversionRuleconversionWord="clr"converterClass="org.springframework.boot.logging.logback.ColorConverter" /><conversionRuleconversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /><conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /><!-- 彩色日志格式 --><property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/><!--輸出到控制臺--><appender name="LOG_CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><Pattern>${CONSOLE_LOG_PATTERN}</Pattern><!-- 設置字符集 --><charset>UTF-8</charset></encoder></appender><!--輸出到文件--><appender name="LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在記錄的日志文件的路徑及文件名 --><file>${log.path}/Business.log</file><!--日志文件輸出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset></encoder><!-- 日志記錄器的滾動策略,按日期,按大小記錄 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 每天日志歸檔路徑以及格式 --><fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天數--><maxHistory>15</maxHistory></rollingPolicy></appender>
</included>
  • logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration><!--引入其他配置文件--><include resource="logback-base.xml" /><!--<logger>用來設置某一個包或者具體的某一個類的日志打印級別、以及指定<appender>。<logger>僅有一個name屬性,一個可選的level和一個可選的addtivity屬性。name:用來指定受此logger約束的某一個包或者具體的某一個類。level:用來設置打印級別,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,如果未設置此屬性,那么當前logger將會繼承上級的級別。addtivity:是否向上級logger傳遞打印信息。默認是true。--><!--開發環境--><springProfile name="dev"><logger name="com.itweid.takeout" additivity="false" level="debug"><appender-ref ref="LOG_CONSOLE"/></logger></springProfile><!--生產環境--><springProfile name="pro"><logger name="com.itweid.takeout" additivity="false" level="info"><appender-ref ref="LOG_FILE"/></logger></springProfile><!--root節點是必選節點,用來指定最基礎的日志輸出級別,只有一個level屬性level:設置打印級別,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF 默認是DEBUG可以包含零個或多個元素,標識這個appender將會添加到這個logger。--><root level="info"><appender-ref ref="LOG_CONSOLE" /><appender-ref ref="LOG_FILE" /></root>
</configuration>
  • 3)重新啟動項目,可以看到根目錄下生成了logs文件夾及日志文件:

3.3 實現表單校驗功能

員工登錄時,必須輸入用戶名和密碼,雖然前端JS進行了校驗,但對于后端來說,前端傳來的數據是不可信的。

前端很容易獲取到后端的接口,如果有人直接調用接口,就可能會出現非法數據,因此服務端也要數據校驗。總的來說:

  • 前端校驗:主要是提高用戶體驗
  • 后端校驗:主要是保證數據安全可靠

Hibernate Validator框架可以以很優雅的方式實現參數的校驗,讓業務代碼和校驗邏輯分開,不再編寫重復的校驗邏輯。

更詳細的用法可參考:后臺管理系統的通用權限解決方案(五)SpringBoot整合hibernate-validator實現表單校驗

  • 1)首先,在LoginForm類中加入表單校驗的注解,如字符串類型的參數則用@NotBlank
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel("登錄表單")
public class LoginForm {@ApiModelProperty("用戶名")@NotBlank(message = "用戶名不能為空")private String username;@ApiModelProperty("密碼")@NotBlank(message = "密碼不能為空")private String password;
}
  • 2)在EmployeeController類中使用@Validated注解開啟校驗功能:

  • 3)需要特別注意的是,在2.3.0版本之前,spring-boot-starter-web是集成了validation檢驗的,但是在2.3.0開始就去掉了該依賴,所以根據實際版本決定是否添加依賴:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>
  • 4)重啟服務,發起登錄請求,如果用戶名為空,則會報錯:


但此時前端提示不太友好(報400)。我們還要繼續完善一下,對異常進行統一處理。

  • 5)自定義一個CustomException異常類來統一處理已知的異常。未來在業務邏輯中,使用try...catch...捕獲異常后,再拋出一個CustomException異常:
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Slf4j
public class CustomException extends RuntimeException {private BaseResult result;/*** 指定一個是否追蹤信息棧的異常*/public CustomException(BaseResult result, boolean writableStackTrace) {super(result.getMsg(), null, false, writableStackTrace);this.result = result;}/*** 指定一個不追蹤信息棧的異常*/public CustomException(BaseResult result) {super(result.getMsg(), null, false, false);this.result = result;}/*** 指定一個不追蹤棧信息的異常*/public CustomException(ErrorCode errorCode) {super(errorCode.getMsg(), null, false, false);this.result = BaseResult.error(errorCode);}
}
  • 6)創建一個全局異常處理類GlobalExceptionHandler,對自定義異常和參數綁定異常進行統一處理:
@ControllerAdvice(annotations = { RestController.class, Controller.class })
@Slf4j
public class GlobalExceptionHandler {/*** 自定義異常的處理*/@ExceptionHandler(CustomException.class)@ResponseBodypublic BaseResult customExceptionHandler(CustomException customException) {log.error("捕獲自定義異常:{}", customException.getResult().getMsg(), customException);return customException.getResult();}/*** 參數綁定異常的處理*/@ExceptionHandler({ConstraintViolationException.class, BindException.class})@ResponseBodypublic String validateException(Exception e, HttpServletRequest request) {log.error("捕獲參數異常:{}", e.getMessage(), e);String msg = null;if (e instanceof ConstraintViolationException) {ConstraintViolationException constraintViolationException =(ConstraintViolationException) e;Set<ConstraintViolation<?>> violations =constraintViolationException.getConstraintViolations();ConstraintViolation<?> next = violations.iterator().next();msg = next.getMessage();} else if (e instanceof BindException) {BindException bindException = (BindException) e;msg = bindException.getBindingResult().getFieldError().getDefaultMessage();}log.error("參數異常信息:{}", msg);return msg;}}
  • 7)重啟服務,再次調用登錄請求,當參數不符合要求時,則會返回更加友好的提示:

3.4 實現請求參數和響應參數的打印

頁面的每個請求都有請求參數和響應參數,如果每個請求都單獨打印這些參數,則顯得非常冗余。

為此我們可以基于注解和切面編程,實現請求參數和響應參數的打印。

  • 1)引入依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--hutool工具-->
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.1.0</version>
</dependency>
  • 2)創建切面類OptLogAspect,配置切入點攔截規則,攔截所有Controller方法
@Aspect
@Slf4j
public class OptLogAspect {/*** 定義Controller切入點攔截規則,攔截 @OptLog 注解的方法*/@Pointcut("execution(public * com.itweid.takeout.controller.*Controller.*(..))")public void optLogAspect() {}
}
  • 3)在OptLogAspect的前置通知方法中,打印請求參數信息
/*** 前置通知*/
@Before(value = "optLogAspect()")
public void doBefore(JoinPoint joinPoint) throws Throwable {HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();// 請求參數Object[] args = joinPoint.getArgs();String strArgs = "";try {if (!request.getContentType().contains("multipart/form-data")) {strArgs = JSONUtil.toJsonStr(args);}} catch (Exception e) {try {strArgs = Arrays.toString(args);} catch (Exception ex) {log.warn("解析參數異常", ex);}}log.info("請求參數:{}", StrUtil.sub(strArgs, 0, 65535));
}
  • 4)在成功返回通知方法和異常返回通知中,打印響應參數信息
/*** 成功返回通知*/
@AfterReturning(returning = "ret", pointcut = "optLogAspect()")
public void doAfterReturning(Object ret) {BaseResult baseResult = Convert.convert(BaseResult.class, ret);log.info("響應參數:{}", baseResult);
}/*** 異常返回通知*/
@AfterThrowing(throwing = "e", pointcut = "optLogAspect()")
public void doAfterThrowable(Throwable e) {log.info("響應異常:{}", getStackTrace(e));
}public static String getStackTrace(Throwable throwable) {StringWriter sw = new StringWriter();try (PrintWriter pw = new PrintWriter(sw)) {throwable.printStackTrace(pw);return sw.toString();}
}
  • 5)在WebMvcConfig配置類中注冊切面類為Bean
@Bean
public OptLogAspect optLogAspect() {return new OptLogAspect();
}
  • 6)重啟服務,測試登錄功能


可見,請求參數和響應參數成功打印。后續還可以將請求IP、操作員等信息收集起來存到數據庫,就可以實現常說的審計功能。

本節完,更多內容查閱:瑞吉外賣項目實戰

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

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

相關文章

leetcode刷題-回溯算法04

代碼隨想錄回溯算法part01| 491.遞增子序列、46.全排列、47.全排列II 491.遞增子序列46.全排列47.全排列II 491.遞增子序列 leetcode題目鏈接 代碼隨想錄文檔講解 思路&#xff1a; 與上一題不同&#xff0c;不能用used列表&#xff0c;因為這個題不能排序&#xff0c; 在每一…

基于字節大模型的論文翻譯(含免費源碼)

基于字節大模型的論文翻譯 源代碼&#xff1a; &#x1f44f; star ? https://github.com/boots-coder/LLM-application 展示 項目簡介 本項目是一個基于大語言模型&#xff08;Large Language Model, LLM&#xff09;的論文閱讀與翻譯輔助工具。它通過用戶界面&#xff08…

mysql的事務控制和數據庫的備份和恢復

事務控制語句 行鎖和死鎖 行鎖 兩個客戶端同時對同一索引行進行操作 客戶端1正常運行 客戶端2想修改&#xff0c;被鎖行 除非將事務提交才能繼續運行 死鎖 客戶端1刪除第5行 客戶端2設置第1行為排他鎖 客戶端1刪除行1被鎖 客戶端2更新行5被鎖 如何避免死鎖 mysql的備份和還…

Tengine:Nginx二次開發-高性能進化

前言&#xff1a;在當今的互聯網時代&#xff0c;Web 服務器的性能和穩定性對于網站的成功至關重要。Nginx 以其高性能和可擴展性而聞名&#xff0c;但有時候&#xff0c;我們需要更多的特性來滿足特定的業務需求。Tengine&#xff0c;作為一個由淘寶網發起的 Nginx 二次開發版…

RK3588, FFmpeg 拉流 RTSP, mpp 硬解碼轉RGB

RK3588 ,基于FFmpeg, 拉取RTSP,使用 mpp 實現硬解碼. ?? 傳送 ?? Ubuntu x64 架構, 交叉編譯aarch64 FFmpeg mppRK3588, FFmpeg 拉流 RTSP, mpp 硬解碼轉RGBRk3588 FFmpeg 拉流 RTSP, 硬解碼轉RGBRK3588 , mpp硬編碼yuv, 保存MP4視頻文件.

Windows 下 Anaconda的安裝與配置 GPU 版

給之前的電腦安一下深度學習環境 判斷是否有NVIDIA GPU Ctrl Shift Esc 打開任務管理器 帶此字眼表示有 NVIDIA GPU 安裝Anaconda anaconda 打開郵箱會看到下載鏈接 這里建議修改為其他盤,要不然下載的包和創建的環境都在C盤&#xff0c;占用空間 三個都打鉤 取…

【openssl】 version `OPENSSL_3.0.3‘ not found 問題

【openssl】 version OPENSSL_3.0.3 not found 問題 使用openssl時候報錯&#xff1a; openssl lib/libcrypto.so.3: version OPENSSL_3.0.3 not found查閱CSDN發現有博主說把別的地方的libcrypto.so.3 復制過去就好了。 嘗試無效 警告&#xff01;這個操作不對&#xff1a; 不…

flask flask-socketio創建一個網頁聊天應用

應用所需環境&#xff1a; python 3.11.11 其他 只需要通過這個命令即可 pip install flask3.1.0 Flask-SocketIO5.4.1 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple 最好是用conda創建一個新的虛擬環境來驗證 完整的pip list如下 Package Version ----…

聯邦學習防止數據泄露

文章目錄 聯邦學習防止數據泄露的原理聯邦學習的優勢聯邦學習與集中式學習的成本分析聯邦學習的實際應用案例個人設想參考文獻 聯邦學習 (Federated Learning) 是一種分布式機器學習技術&#xff0c;旨在解決數據隱私保護問題。它允許在分散的數據源上進行模型訓練&#xff0c;…

STM32 水質水位檢測項目(硬件架構)及(軟件架構)

硬件選型 水位測量模塊 TDS采集模塊 外置ADC模塊&#xff08;ADS1115&#xff09; 水位測量模塊使用方法 水位測量原理 壓力傳感器&#xff1a;水越深壓力越大 P ρgh Fps Fρgh*s P大氣壓 水位測量傳感器本質上是一個壓力測量傳感器。壓力的值和傳感器產生的電壓值是線…

C# 6.0 連接elasticsearch數據庫

在 C# 6.0 中連接 Elasticsearch 數據庫,您可以使用官方的 Elasticsearch 客戶端庫 NEST。NEST 是一個高性能的 .NET 客戶端,用于與 Elasticsearch 進行交互。以下是一個詳細的步驟指南,幫助您在 C# 6.0 項目中連接和操作 Elasticsearch。 1. 安裝 NEST 包 首先,您需要在您…

服務器數據恢復—RAIDZ離線硬盤數超過熱備盤數導致陣列崩潰的數據恢復案例

服務器存儲數據恢復環境&#xff1a; ZFS Storage 7320存儲陣列中有32塊硬盤。32塊硬盤分為4組&#xff0c;每組8塊硬盤&#xff0c;共組建了3組RAIDZ&#xff0c;每組raid都配置了熱備盤。 服務器存儲故障&#xff1a; 服務器存儲運行過程中突然崩潰&#xff0c;排除人為誤操…

Java轉C++之編程范式

1. 過程式編程&#xff08;Procedural Programming&#xff09; 在 C 中的表現 過程式編程是通過一系列的函數調用來實現程序的功能。函數是核心構建單元&#xff0c;數據和操作通過函數進行交互。 C 中&#xff1a;可以使用普通的函數和全局變量來進行過程式編程。Java 中&…

llama2中的model.py中的結構示意圖

參考文章&#xff1a;https://zhuanlan.zhihu.com/p/679640407

開放詞匯目標檢測(Open-Vocabulary Object Detection, OVOD)綜述

定義 開放詞匯目標檢測&#xff08;Open-Vocabulary Object Detection, OVOD&#xff09;是一種目標檢測任務&#xff0c;旨在檢測和識別那些未在訓練集中明確標注的物體類別。傳統的目標檢測模型通常只能識別有限數量的預定義類別&#xff0c;而OVOD模型則具有識別“開放詞匯…

Vue與React:前端框架的巔峰對決

文章目錄 一、引言&#xff08;一&#xff09;前端框架發展現狀簡述 二、Vue 與 React 框架概述&#xff08;一&#xff09;Vue.js 簡介&#xff08;二&#xff09;React.js 簡介 三、開發效率對比&#xff08;一&#xff09;Vue 開發效率分析&#xff08;二&#xff09;React …

3分鐘讀懂數據分析的流程是什么

數據分析是基于商業目的&#xff0c;有目的地進行收集、整理、加工和分析數據&#xff0c;提煉出有價值的 信息的一個過程。整個過程大致可分為五個階段&#xff0c;具體如下圖所示。 1.明確目的和思路 在開展數據分析之前&#xff0c;我們必須要搞清楚幾個問題&#xff0c;比…

vba批量化調整word的圖和圖表標題

vba代碼 將圖片進行居中操作 Sub ChangePictureFormate()Dim oPara As ParagraphDim oRange As RangeDim i As LongDim beforeIsPicture As BooleanbeforesIsPicture False 確保文檔中至少有圖片If ActiveDocument.InlineShapes.Count 0 ThenMsgBox "沒有找到圖片。&qu…

llama.cpp:PC端測試 MobileVLM -- 電腦端部署圖生文大模型

llama.cpp&#xff1a;PC端測試 MobileVLM 1.環境需要2.構建項目3.PC測試 1.環境需要 以下是經實驗驗證可行的環境參考&#xff0c;也可嘗試其他版本。 &#xff08;1&#xff09;PC&#xff1a;Ubuntu 22.04.4 &#xff08;2&#xff09;軟件環境&#xff1a;如下表所示 工…

詞嵌入(Word Embedding):自然語言處理的基石

目錄 ?編輯 詞嵌入&#xff08;Word Embedding&#xff09;&#xff1a;自然語言處理的基石 引言 詞嵌入的基本概念 詞嵌入的主要方法 1. Word2Vec 2. GloVe 3. FastText 4. ELMo 5. BERT 詞嵌入的應用場景 詞嵌入的研究進展 結論 詞嵌入&#xff08;Word Embedd…