一、前言
一個后端接口大致分為四個部分組成: 接口地址(url)、接口請求方式(get、post等)、請求數(shù)據(jù)(request)、響應(yīng)數(shù)據(jù)(response) 。雖然說后端接口的編寫并沒有統(tǒng)一規(guī)范要求,而且如何構(gòu)建這幾個部分每個公司要求都不同,沒有什么“一定是最好的”標(biāo)準(zhǔn),但其中最重要的關(guān)鍵點(diǎn)就是看是否規(guī)范。
二、環(huán)境說明
因?yàn)橹v解的重點(diǎn)是后端接口,所以需要導(dǎo)入一個spring-boot-starter-web
包,而lombok作用是簡化類,前端顯示則使用了knife4j,具體使用在Spring Boot整合knife4j實(shí)現(xiàn)Api文檔已寫明。另外從springboot-2.3開始,校驗(yàn)包被獨(dú)立成了一個starter組件,所以需要引入如下依賴:
org.springframework.bootclass="hljs-name"groupId>
spring-boot-starter-validationclass="hljs-name"artifactId>
class="hljs-name"dependency>
com.github.xiaoyminclass="hljs-name"groupId>
knife4j-spring-boot-starterclass="hljs-name"artifactId>
2.0.2class="hljs-name"version>
class="hljs-name"dependency>
org.springframework.bootclass="hljs-name"groupId>
spring-boot-starter-webclass="hljs-name"artifactId>
class="hljs-name"dependency>
org.projectlombokclass="hljs-name"groupId>
lombokclass="hljs-name"artifactId>
trueclass="hljs-name"optional>
class="hljs-name"dependency>
三、參數(shù)校驗(yàn)
1、介紹
一個接口一般對參數(shù)(請求數(shù)據(jù))都會進(jìn)行安全校驗(yàn),參數(shù)校驗(yàn)的重要性自然不必多說,那么如何對參數(shù)進(jìn)行校驗(yàn)就有講究了。一般來說有三種常見的校驗(yàn)方式,我們使用了最簡潔的第三種方法
- 業(yè)務(wù)層校驗(yàn)
- Validator + BindResult校驗(yàn)
- Validator + 自動拋出異常
業(yè)務(wù)層校驗(yàn)無需多說,即手動在java的Service層進(jìn)行數(shù)據(jù)校驗(yàn)判斷。不過這樣太繁瑣了,光校驗(yàn)代碼就會有很多
而使用Validator+ BindingResult
已經(jīng)是非常方便實(shí)用的參數(shù)校驗(yàn)方式了,在實(shí)際開發(fā)中也有很多項(xiàng)目就是這么做的,不過這樣還是不太方便,因?yàn)槟忝繉懸粋€接口都要添加一個BindingResult參數(shù),然后再提取錯誤信息返回給前端(簡單看一下)。
@PostMapping("/addUser")
public String addUser(@RequestBody @Validated User user, BindingResult bindingResult) {
// 如果有參數(shù)校驗(yàn)失敗,會將錯誤信息封裝成對象組裝在BindingResult里
List
2、Validator + 自動拋出異常(使用)
內(nèi)置參數(shù)校驗(yàn)如下:
首先Validator可以非常方便的制定校驗(yàn)規(guī)則,并自動幫你完成校驗(yàn)。首先在入?yún)⒗镄枰r?yàn)的字段加上注解,每個注解對應(yīng)不同的校驗(yàn)規(guī)則,并可制定校驗(yàn)失敗后的信息:
@Data
public class User {
@NotNull(message = "用戶id不能為空")
private Long id;
@NotNull(message = "用戶賬號不能為空")
@Size(min = 6, max = 11, message = "賬號長度必須是6-11個字符")
private String account;
@NotNull(message = "用戶密碼不能為空")
@Size(min = 6, max = 11, message = "密碼長度必須是6-16個字符")
private String password;
@NotNull(message = "用戶郵箱不能為空")
@Email(message = "郵箱格式不正確")
private String email;
}
校驗(yàn)規(guī)則和錯誤提示信息配置完畢后,接下來只需要在接口僅需要在校驗(yàn)的參數(shù)上加上@Valid
注解(去掉BindingResult后會自動引發(fā)異常,異常發(fā)生了自然而然就不會執(zhí)行業(yè)務(wù)邏輯):
@RestController
@RequestMapping("user")
public class ValidationController {
@Autowired
private ValidationService validationService;
@PostMapping("/addUser")
public String addUser(@RequestBody @Validated User user) {
return validationService.addUser(user);
}
}
現(xiàn)在我們進(jìn)行測試,打開knife4j文檔地址,當(dāng)輸入的請求數(shù)據(jù)為空時,Validator會將所有的報(bào)錯信息全部進(jìn)行返回,所以需要與全局異常處理一起使用。
// 使用form data方式調(diào)用接口,校驗(yàn)異常拋出 BindException
// 使用 json 請求體調(diào)用接口,校驗(yàn)異常拋出 MethodArgumentNotValidException
// 單個參數(shù)校驗(yàn)異常拋出ConstraintViolationException
// 處理 json 請求體調(diào)用接口校驗(yàn)失敗拋出的異常
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResultVO
3、分組校驗(yàn)和遞歸校驗(yàn)
分組校驗(yàn)有三個步驟:
- 定義一個分組類(或接口)
- 在校驗(yàn)注解上添加groups屬性指定分組
- Controller方法的
@Validated
注解添加分組類
public interface Update extends Default{
}
@Data
public class User {
@NotNull(message = "用戶id不能為空",groups = Update.class)
private Long id;
......
}
@PostMapping("update")
public String update(@Validated({Update.class}) User user) {
return "success";
}
如果Update不繼承Default,@Validated({Update.class})
就只會校驗(yàn)屬于Update.class
分組的參數(shù)字段;如果繼承了,會校驗(yàn)了其他默認(rèn)屬于Default.class
分組的字段。
對于遞歸校驗(yàn)(比如類中類),只要在相應(yīng)屬性類上增加@Valid
注解即可實(shí)現(xiàn)(對于集合同樣適用)
4、自定義校驗(yàn)
Spring Validation允許用戶自定義校驗(yàn),實(shí)現(xiàn)很簡單,分兩步:
- 自定義校驗(yàn)注解
- 編寫校驗(yàn)者類
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {HaveNoBlankValidator.class})// 標(biāo)明由哪個類執(zhí)行校驗(yàn)邏輯
public @interface HaveNoBlank {
// 校驗(yàn)出錯時默認(rèn)返回的消息
String message() default "字符串中不能含有空格";
Class?[] groups() default { };
Class? extends Payload[] payload() default { };
/**
* 同一個元素上指定多個該注解時使用
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
public @interface List {
NotBlank[] value();
}
}
public class HaveNoBlankValidator implements ConstraintValidator<HaveNoBlank, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// null 不做檢驗(yàn)
if (value == null) {
return true;
}
// 校驗(yàn)失敗
return !value.contains(" ");
// 校驗(yàn)成功
}
}
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7256瀏覽量
91827 -
URL
+關(guān)注
關(guān)注
0文章
141瀏覽量
15862 -
后端
+關(guān)注
關(guān)注
0文章
32瀏覽量
2401 -
SpringBoot
+關(guān)注
關(guān)注
0文章
175瀏覽量
398
發(fā)布評論請先 登錄
SpringBoot應(yīng)用啟動運(yùn)行run方法
什么是 SpringBoot?

SpringBoot的核心注解1

SpringBoot的核心注解2

SpringBoot 后端接口規(guī)范(中)

SpringBoot 后端接口規(guī)范(下)
前后端分離必備的接口規(guī)范

評論