相信我們在處理接口參數校驗時,都不會使用大量的if,else 進行來處理,這樣顯得太繁瑣,下面就來介紹一下如何能夠簡單而有效的處理方式:
一、使用注解來處理參數校驗
1、實體類
package com.dongl.bean.mybean; import com.dongl.utils.annotation.CheckField; import lombok.Data; import org.hibernate.validator.constraints.Range; import javax.validation.constraints.NotNull; import java.util.Date;
@Data public class User { /**主鍵*/ private Long id; /**姓名*/ @NotNull private String name; /**性別*/ @CheckField(fieldValues = {"男", "女"}) private String sex; /**出生日期*/ private Date birthDay; /**年齡*/ @Range(min = 20 , max = 99) private Short age; /**詳細地址*/ private String address; }
2、Controller層
package com.dongl.controller; import com.dongl.bean.mybean.User; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; /** * @author D-L * @Classname AnnotationController * @Version 1.0 * @Description 接口參數校驗異常處理 * @Date 2020/8/26 */ @RestController @RequestMapping("Annotation") public class AnnotationController { @PostMapping(value = "user") public String test(@Validated @RequestBody User user /*, BindingResult bindingResult*/) { System.out.println(user); return "do something you like ------"; } }
3、響應結果
測試參數:
{ "name":"admin", "sex":"男", "age":120, "address":"杭州市西湖區" }
response:
{ "timestamp": "2020-08-26T07:25:45.547+0000", "status": 400, "error": "Bad Request", "errors": [ { "codes": [ "Range.user.age", "Range.age", "Range.java.lang.Short", "Range" ], "arguments": [ { "codes": [ "user.age", "age" ], "arguments": null, "defaultMessage": "age", "code": "age" }, 99, 20 ], "defaultMessage": "需要在20和99之間", "objectName": "user", "field": "age", "rejectedValue": 120, "bindingFailure": false, "code": "Range" } ], "message": "Validation failed for object='user'. Error count: 1", "trace": "org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public java.lang.String com.dongl.controller.AnnotationController.test(com.dongl.bean.mybean.User): [Field error in object 'user' on field 'age': rejected value [120]; codes [Range.user.age,Range.age,Range.java.lang.Short,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.age,age]; arguments []; default message [age],99,20]; default message [需要在20和99之間]] \r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.lang.Thread.run(Thread.java:748)\r\n", "path": "/Annotation/user" }
【結論】:這樣的響應結果顯然有點不夠優雅,太繁瑣,有沒有更好的處理方式,當然有,下面使用 BindResult 處理。
二、針對接口處理 Validator + BindResult進行校驗
1、處理響應結果
package com.dongl.controller; import com.dongl.bean.mybean.User; import org.springframework.validation.BindingResult; import org.springframework.validation.ObjectError; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; /** * @author D-L * @Classname AnnotationController * @Version 1.0 * @Description 處理參數校驗異常 * @Date 2020/8/24 */ @RestController @RequestMapping("Annotation") public class AnnotationController { @PostMapping(value = "user") public String test(@Validated @RequestBody User user , BindingResult bindingResult) { List<ObjectError> allErrors = bindingResult.getAllErrors(); // 如果有參數校驗失敗,會將錯誤信息封裝成對象組裝在BindingResult里 for(ObjectError error : allErrors){ return error.getDefaultMessage(); } System.out.println(user); return "do something you like ------"; } }
2、響應結果
需要在20和99之間
【結論】當然這種方式已經解決了返回體繁瑣的問題,但是每一處理接口參數都需要添加,還是有點不盡人意,有沒有更好的解決方法,當然有,下面通過全局的方式處理。
三、全局異常處理 Validator + 自動拋出異常
1、全局處理響應結果
首先,我們需要新建一個類,在這個類上加上@ControllerAdvice或@RestControllerAdvice注解,這個類就配置成全局處理類了。(這個根據你的Controller層用的是@Controller還是@RestController來決定)
這里就以@RestController為例:
package com.dongl.utils.error; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; /** * @author D-L * @Classname ExceptionControllerAdvice * @Version 1.0 * @Description 全局處理參數校驗異常返回提示 * @Date 2020/8/26 */ @RestControllerAdvice public class ExceptionControllerAdvice { @ExceptionHandler(MethodArgumentNotValidException.class) public String MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) { // 從異常對象中拿到ObjectError對象 ObjectError objectError = e.getBindingResult().getAllErrors().get(0); // 然后提取錯誤提示信息進行返回 return objectError.getDefaultMessage(); } }
2、測試結果:
需要在20和99之間
【注釋】:這里說明一下如果你進行了全局的處理,但在接口上又進行了手動處理,這時命中的是接口上的,也就是全局配置不生效了。