Spring?Boot項(xiàng)目傳參校驗(yàn)的最佳實(shí)踐指南
場景還原
簡單業(yè)務(wù)場景模擬:
假如你現(xiàn)在在做一個(gè)成績錄入系統(tǒng),你愉快地用Spring Boot框架寫了一個(gè)后臺接口,用于接收前臺瀏覽器傳過來的 Student對象,并插入后臺數(shù)據(jù)庫。
我們將傳入的 Student對象定義為:
public class Student { private String name; // 姓名 private Integer score; // 考試分?jǐn)?shù)(滿分100分) private String mobile; // 電話號碼(11位) }
然后寫一個(gè)Post請求的后臺接口,來接收網(wǎng)頁端傳過來的 Student對象:
@RestController public class TestController { @Autowired private StudentService studentService; @PostMapping("/add") public String addStudent( @RequestBody Student student ) { studentService.addStudent( student ); // 將student對象存入數(shù)據(jù)庫 return "SUCCESS"; } }
此時(shí)我想你一定看出來了上面這段代碼的漏洞,因?yàn)槲覀儾]有對傳入的 Student對象做任何數(shù)據(jù)校驗(yàn),比如:
Student對象里三個(gè)字段的某一個(gè)忘傳了,為 null怎么辦?Student的 score分?jǐn)?shù),假如寫錯(cuò)了,寫成 101分怎么辦?Student的 mobile11位手機(jī)號碼,假如填錯(cuò)了,多寫了一位怎么辦?...等等
這些數(shù)據(jù)雖然在前端頁面一般會做校驗(yàn),但我們作為一個(gè)嚴(yán)謹(jǐn)且良心的后端開發(fā)工程師,我們肯定要對傳入的每一項(xiàng)數(shù)據(jù)做嚴(yán)格的校驗(yàn),所以我們應(yīng)該怎么寫?
@PostMapping("/add") public String addStudent( @RequestBody Student student ) { if( student == null ) return "傳入的Student對象為null,請傳值"; if( student.getName()==null || "".equals(student.getName()) ) return "傳入的學(xué)生姓名為空,請傳值"; if( student.getScore()==null ) return "傳入的學(xué)生成績?yōu)閚ull,請傳值"; if( (student.getScore()<0) || (student.getScore()>100) ) return "傳入的學(xué)生成績有誤,分?jǐn)?shù)應(yīng)該在0~100之間"; if( student.getMobile()==null || "".equals(student.getMobile()) ) return "傳入的學(xué)生電話號碼為空,請傳值"; if( student.getMobile().length()!=11 ) return "傳入的學(xué)生電話號碼長度有誤,應(yīng)為11位"; studentService.addStudent( student ); // 將student對象存入MySQL數(shù)據(jù)庫 return "SUCCESS"; }
寫是寫完了,就是感覺手有點(diǎn)酸,并且心有點(diǎn)累,這個(gè) Student對象倒還好,畢竟內(nèi)部僅3個(gè)字段,假如一個(gè)復(fù)雜的對象有30個(gè)字段怎么辦?簡直不敢想象!
神注解加持
其實(shí)Spring框架很早版本開始,就通過注解的方式,來方便地為我們提供了各項(xiàng)交互數(shù)據(jù)的校驗(yàn)工作,比如上面的例子,我們只需要在傳入的 Student實(shí)體類的字段中加入對應(yīng)注解即可方便的解決問題:
public class Student { @NotNull(message = "傳入的姓名為null,請傳值") @NotEmpty(message = "傳入的姓名為空字符串,請傳值") private String name; // 姓名 @NotNull(message = "傳入的分?jǐn)?shù)為null,請傳值") @Min(value = 0,message = "傳入的學(xué)生成績有誤,分?jǐn)?shù)應(yīng)該在0~100之間") @Max(value = 100,message = "傳入的學(xué)生成績有誤,分?jǐn)?shù)應(yīng)該在0~100之間") private Integer score; // 分?jǐn)?shù) @NotNull(message = "傳入的電話為null,請傳值") @NotEmpty(message = "傳入的電話為空字符串,請傳值") @Length(min = 11, max = 11, message = "傳入的電話號碼長度有誤,必須為11位") private String mobile; // 電話號碼 }
當(dāng)然,于此同時(shí),我們還需要在對象入口處,加上注解 @Valid來開啟對傳入 Student對象的驗(yàn)證工作:
@PostMapping("/add") public String addStudent( @RequestBody @Valid Student student ) { // 棒棒噠!原先各種繁雜的參數(shù)校驗(yàn)工作統(tǒng)統(tǒng)都省了!一行代碼不用寫 studentService.addStudent( student ); // 將student對象存入MySQL數(shù)據(jù)庫 return "SUCCESS"; }
這時(shí)候,如果某個(gè)字段傳入錯(cuò)誤,比如我傳數(shù)據(jù)的時(shí)候,將學(xué)生的成績誤傳為 101分,則接口返回結(jié)果便會提示出錯(cuò)誤詳情:
當(dāng)然,關(guān)于這個(gè)事情的原理,既然用到了注解,無非用的也就是Java里的各種反射等知識來實(shí)現(xiàn)的,感興趣的小伙伴可以借此機(jī)會研究一下!
數(shù)據(jù)異常統(tǒng)一攔截
上面利用注解的方式做統(tǒng)一數(shù)據(jù)校驗(yàn)感覺十分美好,但唯一美中不足的就是返回的結(jié)果太過繁雜,不一定使我們需要的格式,我們需要做統(tǒng)一處理,比如:我只想將具體參數(shù)校驗(yàn)的錯(cuò)誤提示信息給摳出來返回給前端即可。
為此,我們?yōu)轫?xiàng)目配置全局統(tǒng)一異常攔截器來格式化所有數(shù)據(jù)校驗(yàn)的返回結(jié)果。
@ControllerAdvice @ResponseBody public class GlobalExceptionInterceptor { @ExceptionHandler(value = Exception.class) public String exceptionHandler(HttpServletRequest request, Exception e) { String failMsg = null; if (e instanceof MethodArgumentNotValidException) { // 拿到參數(shù)校驗(yàn)具體異常信息提示 failMsg = ((MethodArgumentNotValidException) e).getBindingResult().getFieldError().getDefaultMessage(); } return failMsg; // 直接吐回給前端 } }
如上面代碼所示,我們全局統(tǒng)一攔截了參數(shù)校驗(yàn)異常 MethodArgumentNotValidException,并僅僅只拿到對應(yīng)異常的詳細(xì) Message信息吐給前端,此時(shí)返回給前端的數(shù)據(jù)就清楚得多:
可以的,非常優(yōu)雅!
總結(jié)
到此這篇關(guān)于Spring Boot項(xiàng)目傳參校驗(yàn)的文章就介紹到這了,更多相關(guān)SpringBoot項(xiàng)目傳參校驗(yàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot如何優(yōu)雅的處理校驗(yàn)參數(shù)的方法
- SpringBoot中自定義注解實(shí)現(xiàn)參數(shù)非空校驗(yàn)的示例
- 詳解SpringBoot中的參數(shù)校驗(yàn)(項(xiàng)目實(shí)戰(zhàn))
- SpringBoot集成validation校驗(yàn)參數(shù)遇到的坑
- SpringBoot @Validated注解實(shí)現(xiàn)參數(shù)分組校驗(yàn)的方法實(shí)例
- SpringBoot參數(shù)校驗(yàn)與國際化使用教程
- SpringBoot參數(shù)校驗(yàn)的方法總結(jié)
- springboot 參數(shù)格式校驗(yàn)操作
相關(guān)文章
java 數(shù)據(jù)結(jié)構(gòu)與算法 (快速排序法)
這篇文章主要介紹了java 數(shù)據(jù)結(jié)構(gòu)與算法(快速排序法),,快速排序法是實(shí)踐中的一種快速的排序算法,在c++或?qū)ava基本類型的排序中特別有用,下面我們一起進(jìn)入文章學(xué)習(xí)更詳細(xì)的內(nèi)容吧,需要的朋友可以參考下2022-02-02idea企業(yè)開發(fā)之新建各類型項(xiàng)目的詳細(xì)教程
這篇文章主要介紹了idea企業(yè)開發(fā)之新建各類型項(xiàng)目的詳細(xì)教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12JAVA技術(shù)實(shí)現(xiàn)上傳下載文件到FTP服務(wù)器(完整)
這篇文章主要介紹了JAVA技術(shù)實(shí)現(xiàn)上傳下載文件到FTP服務(wù)器(完整),本文使用 Apache Jakarta Commons Net(commons-net-3.3.jar) 基于FileZilla Server服務(wù)器實(shí)現(xiàn)FTP服務(wù)器上文件的上傳/下載/刪除等操作,需要的朋友可以參考下2015-07-07SpringCloud客戶端報(bào)錯(cuò):- was unable to send&nb
這篇文章主要介紹了SpringCloud客戶端報(bào)錯(cuò):- was unable to send heartbeat!的問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05【Redis緩存機(jī)制】詳解Java連接Redis_Jedis_事務(wù)
這篇文章主要介紹了【Redis緩存機(jī)制】詳解Java連接Redis_Jedis_事務(wù),詳細(xì)的介紹了Jedis事務(wù)和實(shí)例,有興趣的可以了解一下。2016-12-12詳解java8在Collection中新增加的方法removeIf
這篇文章主要介紹了詳解java8在Collection中新增加的方法removeIf的相關(guān)資料,需要的朋友可以參考下2018-01-01