文章目錄
- 1.基本準備(構建一個SpringBoot模塊)
- 1.在A_universal_solution模塊下創建新的子模塊unified-processing
- 2.pom.xml引入基本依賴
- 3.編寫springboot啟動類
- 4.啟動測試
- 2.統一響應處理
- 1.首先定義一個響應枚舉類 RespBeanEnum.java 每個枚舉對象都有code和message
- 2.然后定義一個響應的Bean RespBean.java ,可以調用響應枚舉類,進行響應
- 3.測試使用
- 1.目錄結構
- 2.ResponseTest.java
- 3.瀏覽器測試
- 1.成功響應,不攜帶數據。
- 2.成功響應,攜帶數據。
- 3.失敗響應,不攜帶數據。
- 4.失敗響應,攜帶數據。
- 5.測試withData方法。
- 6.測試withMessage方法。
- 3.自定義校驗器
- 1.首先編寫一個Bean測試使用,LoginVo.java
- 2.需求分析
- 自定義校驗器來校驗手機號和密碼
- 3.通用校驗器模板
- 1.定義通用校驗器接口 GenericValidatorInterface.java
- 2.自定義校驗注解 GenericValidation.java
- 3.通用校驗器實現類 GenericValidatorImpl.java
- 4.使用方式
- 1.需求分析
- 2.將模板復制一份,放到validator包下,準備進行修改
- 3.要校驗的字段為Integer類型,也就是修改value類型
- 4.注解中的value是int數組類型,也就是修改annotationValue的類型
- 5.修改三個類的名字前綴為Test,直接修改然后alter +enter 讓IDEA自動修改
- 6.TestValidatorImpl.java編寫校驗邏輯
- 7.修改LoginVo.java 添加測試校驗字段
- 8.編寫controller加上@Valid字段進行校驗
- 9.測試
- 4.統一異常處理器整合自定義校驗器
- 1.編寫自定義異常攜帶響應枚舉對象 CustomException.java
- 2.編寫全局異常處理器 GlobalExceptionHandler.java
- 3.最佳實踐
- 1.當需要響應error時直接拋出自定義異常對象,指定響應枚舉對象
- 2.此時當出現參數綁定異常時也會交給統一異常處理解決
- 3.當出現其他異常時,就會響應服務端異常,控制臺也會打印錯誤信息
1.基本準備(構建一個SpringBoot模塊)
1.在A_universal_solution模塊下創建新的子模塊unified-processing
2.pom.xml引入基本依賴
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!-- 繼承spring-boot父模塊 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.4</version><relativePath/> <!-- 如果交給父模塊統一管理,但是又要繼承springboot的父模塊,就必須加這個 --></parent><artifactId>unified-processing</artifactId><packaging>jar</packaging><name>unified-processing</name><url>http://maven.apache.org</url><!-- 解決java: -source 1.5 中不支持 diamond 運算符 問題 --><properties><java.version>1.8</java.version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><!--validation 參數校驗--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><version>2.4.5</version></dependency><!-- springboot兩個常規配置 --><!-- spring-boot-starter-web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- spring-boot-starter-test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- lombok也是常規配置 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- jupiter測試 --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.7.2</version><scope>compile</scope></dependency></dependencies><!-- maven打包插件--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
3.編寫springboot啟動類
package com.sun.solution;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Description:** @Author sun* @Create 2024/5/6 13:00* @Version 1.0*/
@SpringBootApplication
public class UnifiedApplication {public static void main(String[] args) {SpringApplication.run(UnifiedApplication.class, args);}
}
4.啟動測試
2.統一響應處理
1.首先定義一個響應枚舉類 RespBeanEnum.java 每個枚舉對象都有code和message
package com.sxs.seckill.vo;import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;/*** Description: 響應枚舉類** @Author sun* @Create 2024/5/5 15:15* @Version 1.0*/@Getter
@AllArgsConstructor
@ToString
public enum RespBeanEnum {// 通用SUCCESS(200, "SUCCESS"),ERROR(500, "服務端異常"),//登錄模塊LOGIN_ERROR(500210, "用戶名或者密碼錯誤"),MOBILE_ERROR(500211, "手機號碼格式不正確"),BING_ERROR(500212, "參數綁定異常"),MOBILE_NOT_EXIST(500213, "手機號碼不存在"),PASSWORD_UPDATE_FAIL(500214, "更新密碼失敗");//其他模塊。。。// 響應碼和響應信息private final Integer code;private final String message;
}
2.然后定義一個響應的Bean RespBean.java ,可以調用響應枚舉類,進行響應
package com.sxs.seckill.vo;import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;/*** 通用響應數據封裝類。* 提供了構造函數和靜態方法來創建響應對象,支持鏈式調用來設置屬性。*/
@Getter
@Setter
@Accessors(chain = true) // 支持鏈式調用
public class RespBean {private long code;private String message;private Object data;/*** 默認構造函數。*/public RespBean() {}/*** 構造函數,初始化響應碼和消息。* @param code 響應碼。* @param message 響應消息。*/public RespBean(long code, String message) {this.code = code;this.message = message;}/*** 構造函數,初始化響應碼、消息和數據。* @param code 響應碼。* @param message 響應消息。* @param data 響應數據。*/public RespBean(long code, String message, Object data) {this.code = code;this.message = message;this.data = data;}/*** 成功響應,攜帶數據。* @param data 響應數據。* @return 生成的成功響應對象。*/public static RespBean success(Object data) {return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBeanEnum.SUCCESS.getMessage(), data);}/*** 成功響應,不攜帶數據。* @return 生成的成功響應對象。*/public static RespBean success() {return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBeanEnum.SUCCESS.getMessage(), null);}/*** 錯誤響應,只攜帶錯誤枚舉。* @param respBeanEnum 錯誤枚舉,包含錯誤碼和消息。* @return 生成的錯誤響應對象。*/public static RespBean error(RespBeanEnum respBeanEnum) {return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), null);}/*** 錯誤響應,攜帶錯誤枚舉和額外數據。* @param respBeanEnum 錯誤枚舉,包含錯誤碼和消息。* @param data 額外數據。* @return 生成的錯誤響應對象。*/public static RespBean error(RespBeanEnum respBeanEnum, Object data) {return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), data);}/*** 設置響應數據。* @param data 響應數據。* @return 當前對象,支持鏈式調用。*/public RespBean withData(Object data) {this.data = data;return this;}/*** 設置響應消息。* @param message 響應消息。* @return 當前對象,支持鏈式調用。*/public RespBean withMessage(String message) {this.message = message;return this;}
}
3.測試使用
1.目錄結構
2.ResponseTest.java
package com.sun.solution.conroller;import com.sun.solution.unified_response_processing.RespBean;
import com.sun.solution.unified_response_processing.RespBeanEnum;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** Description:** @Author sun* @Create 2024/5/6 13:07* @Version 1.0*/
@RestController
public class ResponseTest {/*** 成功響應,不攜帶數據。** @return*/@RequestMapping("/success1")public RespBean success1() {return RespBean.success();}/*** 成功響應,攜帶數據。** @return*/@RequestMapping("/success2")public RespBean success2() {return RespBean.success("成功響應,攜帶數據。");}/*** 失敗響應,不攜帶數據。** @return*/@RequestMapping("/error1")public RespBean error1() {return RespBean.error(RespBeanEnum.ERROR);}/*** 失敗響應,攜帶數據。** @return*/@RequestMapping("/error2")public RespBean error2() {return RespBean.error(RespBeanEnum.ERROR, "失敗響應,攜帶數據。");}/*** 測試withData方法** @return*/@RequestMapping("/withData")public RespBean withData() {return RespBean.error(RespBeanEnum.ERROR).withData("測試withData方法");}/*** 測試withMessage方法** @return*/@RequestMapping("/withMessage")public RespBean withMessage() {return RespBean.error(RespBeanEnum.ERROR).withMessage("測試withMessage方法");}}
3.瀏覽器測試
1.成功響應,不攜帶數據。
2.成功響應,攜帶數據。
3.失敗響應,不攜帶數據。
4.失敗響應,攜帶數據。
5.測試withData方法。
6.測試withMessage方法。
3.自定義校驗器
1.首先編寫一個Bean測試使用,LoginVo.java
package com.sun.solution.vo;import lombok.Data;/*** Description:** @Author sun* @Create 2024/5/6 13:29* @Version 1.0*/
@Data
public class LoginVo {private String mobile;private String password;
}
2.需求分析
自定義校驗器來校驗手機號和密碼
3.通用校驗器模板
1.定義通用校驗器接口 GenericValidatorInterface.java
package com.sun.solution.validator;/*** Description: 通用校驗器接口,用于重新定義校驗方法,使其更加靈活** @Author sun* @Create 2024/5/6 13:34* @Version 1.0*/public interface GenericValidatorInterface {/*** 校驗接口* @param value 待校驗的值,根據情況自定義類型* @param annotationValue 注解中的value值,根據情況自定義類型* @param required 是否必填* @return*/boolean isValid(String value, String annotationValue, boolean required);
}
2.自定義校驗注解 GenericValidation.java
package com.sun.solution.validator;import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;/*** Description: 自定義校驗注解** @Author sun* @Create 2024/5/6 13:38* @Version 1.0*/
@Documented
@Constraint(validatedBy = GenericValidatorImpl.class) // 1.這里是校驗器的實現類
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface GenericValidation {// 2.這里是注解的屬性// message是校驗失敗時的提示信息String message() default "校驗失敗!";// value是注解的值,可以根據情況自定義類型,類型改變則校驗器也需要改變String value() default "";// required是是否必填boolean required() default true;// 下面這兩個屬性必須添加,是默認屬性Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}
3.通用校驗器實現類 GenericValidatorImpl.java
package com.sun.solution.genericvalidator;import org.springframework.util.StringUtils;import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;/*** Description: 通用校驗器實現類,ConstraintValidator<TestValidation, String>中的兩個參數分別是注解和校驗的值類型** @Author sun* @Create 2024/5/6 13:42* @Version 1.0*/
public class GenericValidatorImpl implements ConstraintValidator<GenericValidation, String>, GenericValidatorInterface {// 注解中的value值,根據情況自定義類型private String annotationValue;// 注解中的required值,表示是否必填private boolean required;/*** 初始化方法,獲取注解中的value值和required值* @param annotation*/@Overridepublic void initialize(GenericValidation annotation) {this.annotationValue = annotation.value();this.required = annotation.required();}/*** 初始的校驗方法* @param value* @param context* @return*/@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {return isValid(value, annotationValue, required);}/*** 增強的校驗方法* @param value 待校驗的值* @param annotationValue 注解中的value值,根據情況自定義類型* @param required 是否必填* @return*/@Overridepublic boolean isValid(String value, String annotationValue, boolean required) {// 校驗邏輯編寫,根據三個參數進行校驗return false;}
}
4.使用方式
1.需求分析
假設,要校驗的字段類型是Integer類型,注解中的value是int數組類型
2.將模板復制一份,放到validator包下,準備進行修改
3.要校驗的字段為Integer類型,也就是修改value類型
GenericValidatorInterface.java
GenericValidatorImpl.java
4.注解中的value是int數組類型,也就是修改annotationValue的類型
GenericValidation.java
GenericValidatorImpl.java
GenericValidatorInterface.java
5.修改三個類的名字前綴為Test,直接修改然后alter +enter 讓IDEA自動修改
6.TestValidatorImpl.java編寫校驗邏輯
/*** 增強的校驗方法* @param value 待校驗的值* @param annotationValue 注解中的value值,根據情況自定義類型* @param required 是否必填* @return*/@Overridepublic boolean isValid(Integer value, int[] annotationValue, boolean required) {// 如果不是必填項,且值為空,則直接返回trueif (!required && value == null) {return true;}// 如果是必填項,且值為空,則直接返回falseif (required && value == null) {return false;}// 如果注解中的value值不為空,且待校驗的值不在value值中,則返回falseif (annotationValue.length > 0) {for (int i : annotationValue) {if (value == i) {return true;}}return false;}return true;}
7.修改LoginVo.java 添加測試校驗字段
package com.sun.solution.vo;import com.sun.solution.validator.TestValidation;
import lombok.Data;/*** Description:** @Author sun* @Create 2024/5/6 13:29* @Version 1.0*/
@Data
public class LoginVo {private String mobile;private String password;@TestValidation(value = {1, 2, 3}, required = true)private Integer test;
}
8.編寫controller加上@Valid字段進行校驗
package com.sun.solution.conroller;import com.sun.solution.unified_response_processing.RespBean;
import com.sun.solution.vo.LoginVo;
import org.springframework.web.bind.annotation.*;import javax.validation.Valid;/*** Description:** @Author sun* @Create 2024/5/6 14:56* @Version 1.0*/
@RestController
public class ValidationTest {@PostMapping("/test")public RespBean test(@Valid @RequestBody LoginVo loginVo) {return RespBean.success("success!");}
}
9.測試
4.統一異常處理器整合自定義校驗器
1.編寫自定義異常攜帶響應枚舉對象 CustomException.java
package com.sun.solution.exception;import com.sun.solution.unified_response_processing.RespBeanEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** Description: 自定義異常類,具有響應枚舉的屬性。** @Author sun* @Create 2024/5/6 15:15* @Version 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CustomException extends RuntimeException{private RespBeanEnum respBeanEnum;
}
2.編寫全局異常處理器 GlobalExceptionHandler.java
package com.sun.solution.exception;import com.sun.solution.unified_response_processing.RespBean;
import com.sun.solution.unified_response_processing.RespBeanEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** Description:** @Author sun* @Create 2024/5/6 15:16* @Version 1.0*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {// 處理所有的異常@ExceptionHandler(Exception.class)public RespBean exceptionHandler(Exception e) {// 日志記錄異常信息及堆棧log.error("Exception caught: ", e); // 如果得到的是自定義異常的對象,那么直接返回這個異常的響應枚舉類信息if (e instanceof CustomException) {CustomException ex = (CustomException) e;return RespBean.error(ex.getRespBeanEnum());} else if (e instanceof BindException) {// 如果是綁定異常,就獲取綁定異常的message信息,返回給前端// 需要獲取改異常 BindException,進行打印BindException ex = (BindException) e;// 獲取綁定異常的信息RespBean respBean = RespBean.error(RespBeanEnum.BING_ERROR).withMessage("參數校驗異常:" +ex.getBindingResult().getAllErrors().get(0).getDefaultMessage());return respBean;}// 如果不是自定義異常,那么返回服務端異常return RespBean.error(RespBeanEnum.ERROR);}
}