前後端交互經常遇到參數多,不同開發人員返回數據結構不統一的問題,今天分享一種跟更優雅的方式,讓研發人員跳出格式限制,把更多的經歷放在邏輯處理上。
1、參數校驗:Validator + BindResult進行校驗
1.1 構建User實體類,通過註解形式校驗參數。
@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;
}
1.2 controller增加@Valid註解,即可啓用校驗。校驗失敗,會拋出MethodArgumentNotValidException異常。
@RestController
@RequestMapping("user2")
public class UserController2 {
@PostMapping("/addUser")
public User addUser(@RequestBody @Valid User user) {
return user;
}
}
2、統一返回數據結構
2.1 全局異常處理
定義ExceptionControllerAdvice,使用全局註解@RestControllerAdvice(basePackages = "com.example.demo.controller"),接受異常註解@ExceptionHandler(MethodArgumentNotValidException.class),即可統一處理異常。
@RestControllerAdvice(basePackages = "com.example.demo.controller")
public class ExceptionControllerAdvice {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResultVO<String> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
// 從異常對象中拿到ObjectError對象
ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
// 然後提取錯誤提示信息進行返回
return new ResultVO<>(ResultCode.VALIDATE_FAILED, objectError.getDefaultMessage());
}
}
2.2 全局數據結構處理
定義ResponseControllerAdvice,使用全局註解@RestControllerAdvice(basePackageClasses = {UserController2.class,UserController.class}),實現ResponseBodyAdvice<Object>,即可處理全局返回結果。
@RestControllerAdvice(basePackageClasses = {UserController2.class,UserController.class})
public class ResponseControllerAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
// 如果接口返回的類型本身就是ResultVO那就沒有必要進行額外的操作,返回false
System.out.println(methodParameter.getGenericParameterType().equals(ResultVO.class));
return !methodParameter.getGenericParameterType().equals(ResultVO.class);
}
@Override
public Object beforeBodyWrite(Object data, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
// String類型不能直接包裝,所以要進行些特別的處理
if (methodParameter.getGenericParameterType().equals(String.class)) {
ObjectMapper objectMapper = new ObjectMapper();
try {
// 將數據包裝在ResultVO裏後,再轉換爲json字符串響應給前端
return objectMapper.writeValueAsString(new ResultVO<>(data));
} catch (JsonProcessingException e) {
throw new APIException("返回String類型錯誤");
}
}
// 將原本的數據包裝在ResultVO裏
return new ResultVO<>(data);
}
}
3、結果測試
3.1 異常測試
3.2 正常結果測試
簡單易學,搞定!