使用@Valid+BindingResult進行controller參數(shù)校驗方式
@Valid+BindingResult進行controller參數(shù)校驗
由于controller是調(diào)用的第一層,經(jīng)常參數(shù)校驗將在這里完成,常見有非空校驗、類型校驗等,常見寫法為以下偽代碼:
public void round(Object a){ if(a.getLogin() == null){ return "手機號不能為空!"; } }
但是調(diào)用對象的位置會有很多,而且手機號都不能為空,那么我們會想到把校驗方法抽出來,避免重復(fù)的代碼。但有框架支持我們通過注解的方式進行參數(shù)校驗。
先立個場景,為往動物園添加動物,動物對象如下,時間節(jié)點大概在3030年,我們認為動物可登陸動物專用的系統(tǒng),所以有password即自己的登錄密碼。
public class Animal { private String name; private Integer age; private String password; private Date birthDay; }
調(diào)用創(chuàng)建動物的controller層如下,簡潔明了,打印下信息后直接返回。
@RestController @RequestMapping("/animal") public class AnimalController { @PostMapping public Animal createAnimal(@RequestBody Animal animal){ logger.info(animal.toString()); return animal; } }
偽造Mvc調(diào)用的測試類。
@RunWith(SpringRunner.class) @SpringBootTest public class TestAnimal { private final static Logger logger = LoggerFactory.getLogger(TestAnimal.class); @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void initMock(){ mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); } @Test public void createAnimal() throws Exception { String content = "{\"name\":\"elephant\",\"password\":null,\"birthDay\":"+System.currentTimeMillis()+"}"; String result = mockMvc.perform(MockMvcRequestBuilders.post("/animal") .content(content) .contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(MockMvcResultMatchers.status().isOk()) .andReturn().getResponse().getContentAsString(); logger.info(result); } }
以上代碼基于搭建的springboot項目,想搭建的同學(xué)可以參考搭建篇 http://www.dbjr.com.cn/article/226998.htm
代碼分析,日期格式的參數(shù)建議使用時間戳傳遞,以上birthDay傳遞 "2018-05-08 20:00:00",將會拋出日期轉(zhuǎn)換異常,感興趣的同學(xué)可以試試。
由于密碼很重要,現(xiàn)在要求密碼為必填,操作如下,添加@NotBlank注解到password上:
@NotBlank private String password;
但光加校驗注解是不起作用的,還需要在方法參數(shù)上添加@Valid注解,如下:
@Valid @RequestBody Animal animal
此時執(zhí)行測試方法,拋出異常,返回狀態(tài)為400:
java.lang.AssertionError: Status
Expected :200
Actual :400
<Click to see difference>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:54)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:81)
說明對password的非空校驗已經(jīng)生效了,直接拋出異常。如果不想拋出異常,想返回校驗信息給前端,這個時候就需要用到BindingResult了,修改創(chuàng)建動物的方法,添加BindingResult參數(shù):
@PostMapping public Animal createAnimal(@Valid @RequestBody Animal animal, BindingResult bindingResult){ if (bindingResult.hasErrors()){ bindingResult.getAllErrors().forEach(o ->{ FieldError error = (FieldError) o; logger.info(error.getField() + ":" + error.getDefaultMessage()); }); } logger.info(animal.toString()); return animal; }
此時,執(zhí)行測試,可以看到日志中的錯誤信息:
2018-05-09 00:59:37.453 INFO 14044 --- [ main] c.i.s.d.web.controller.AnimalController : password:may not be empty
為了滿足我們編碼需要我們需要進行代碼改造,1.不能直接返回animal。2.返回的提示信息得是用戶可讀懂的信息。
controller方法改造如下,通過Map對象傳遞請求成功后的信息或錯誤提示信息。
@PostMapping public Map<String,Object> createAnimal(@Valid @RequestBody Animal animal, BindingResult bindingResult){ logger.info(animal.toString()); Map<String,Object> result = new HashMap<>(); if (bindingResult.hasErrors()){ FieldError error = (FieldError) bindingResult.getAllErrors().get(0); result.put("code","400");//錯誤編碼400 result.put("message",error.getDefaultMessage());//錯誤信息 return result; } result.put("code","200");//成功編碼200 result.put("data",animal);//成功返回數(shù)據(jù) return result; }
返回的密碼提示信息如下:
@NotBlank(message = "密碼不能為空!") private String password;
執(zhí)行測試方法,返回結(jié)果
com.imooc.security.demo.TestAnimal : {"code":"400","message":"密碼不能為空!"}
最后貼一個,設(shè)置password值返回成功的信息
com.imooc.security.demo.TestAnimal : {"code":"200","data":{"name":"elephant","age":null,"password":"lalaland","birthDay":1525799768955}}
由于篇幅有限,下次會以這個實例為基礎(chǔ),實現(xiàn)一個自定義的注解實現(xiàn),該篇文章到此結(jié)束。
Controller層方法的參數(shù)校驗
import com.example.demo.pojo.Student; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.validation.Valid; @Controller @RequestMapping("/stu") public class StudentController { @PostMapping("/addStu") @ResponseBody public String addStudent(@Valid Student student){ System.out.println("存儲student對象"); System.out.println(student); return "ok"; } }
import org.hibernate.validator.constraints.Length; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; public class Student { @NotNull(message = "傳入的是空值,請傳值") @Min(value = 0,message = "傳入學(xué)生分數(shù)有誤,分數(shù)在0-100之間") @Max(value = 100,message = "傳入學(xué)生分數(shù)有誤,分數(shù)在0-100之間") private Integer score; @NotEmpty(message = "傳入的是空字符串,請傳值") @NotNull(message = "傳入的是空值,請傳值") private String name; @NotNull(message = "傳入的是空值,請傳值") @NotEmpty(message = "傳入的是空字符串,請傳值") @Length(min = 11,max = 11,message = "號碼有誤,長度應(yīng)為11位") private String mobile; public Integer getScore() { return score; } public void setScore(Integer score) { this.score = score; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } @Override public String toString() { return "Student{" + "score=" + score + ", name='" + name + '\'' + ", mobile='" + mobile + '\'' + '}'; } }
全局統(tǒng)一異常攔截器
import org.springframework.validation.BindException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @ControllerAdvice public class GlobalExceptionInterceptor { @ExceptionHandler(value = Exception.class) @ResponseBody public String exceptionHandler(Exception e){ String failMessage=null; if(e instanceof BindException){ failMessage=((BindException) e).getBindingResult().getFieldError().getDefaultMessage(); } return failMessage; } }
當我們傳入的參數(shù)有誤時,就會被異常攔截器捕獲,返回給我們錯誤信息。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot tomcat的maxHttpFormPostSize參數(shù)示例解析
這篇文章主要介紹了springboot tomcat的maxHttpFormPostSize參數(shù)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08SpringBoot入坑筆記之spring-boot-starter-web 配置文件的使用
本篇向小伙伴介紹springboot配置文件的配置,已經(jīng)全局配置參數(shù)如何使用的。需要的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-01-01SpringBoot2.0 整合 SpringSecurity 框架實現(xiàn)用戶權(quán)限安全管理方法
Spring Security是一個能夠為基于Spring的企業(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架。這篇文章主要介紹了SpringBoot2.0 整合 SpringSecurity 框架,實現(xiàn)用戶權(quán)限安全管理 ,需要的朋友可以參考下2019-07-07Springboot整合實現(xiàn)郵件發(fā)送的原理詳解
SpringBoot集成郵件服務(wù)非常簡單,通過簡單的學(xué)習(xí)即可快速掌握郵件業(yè)務(wù)類的核心邏輯和企業(yè)郵件的日常服務(wù),本文給大家分享Springboot整合實現(xiàn)郵件發(fā)送的原理,一起看看吧2021-06-06Java二維數(shù)組實現(xiàn)數(shù)字拼圖效果
這篇文章主要為大家詳細介紹了Java二維數(shù)組實現(xiàn)數(shù)字拼圖效果,控制臺可以對空格進行移動,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07