接口开发有一个铁律
不要相信外部的任何入参 不要相信外部的任何入参 不要相信外部的任何入参
所以,接口开发必然少不了接口校验。
一般接口简单参数校验如下,该不会还在使用 if ==null 吧!!!
@PostMapping("/auth/jwt/token")
public ReturnBo login(@RequestBody @Validated LoginReq req, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return ReturnBo.creErrorResult(bindingResult);
}
// 处理
}
以上,只是对单个接口校验,如果项目中存在n个接口,则需要重复n次,效率太低;
不过Spring的强大可不是吹出来的,AOP即可搞定简单通用处理(Spring的切面真的非常非常好用),代码如下
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@RestControllerAdvice
public class BadRequestExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
ReturnBo response = ReturnBo.creErrorResult(ex.getBindingResult());
return new ResponseEntity<>(response, headers, status);
}
}
至此解放Controller中的BindingResult,只需要简单加上@Validated注解即可
@PostMapping("/api/auth/jwt/token")
public ReturnBo login(@RequestBody @Validated LoginReq req) {
// 处理
}
对比之前
@PostMapping("/auth/jwt/token")
public ReturnBo login(@RequestBody @Validated LoginReq req, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return ReturnBo.creErrorResult(bindingResult);
}
// 处理
}
附上 ReturnBo.java
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
@Data
public class ReturnBo implements Serializable {
private static final long serialVersionUID = 2454950041375201365L;
private String resCode;
private String msg;
private Object obj;
public static ReturnBo creErrorResult(BindingResult result) {
ReturnBo returnBo = new ReturnBo();
returnBo.setResCode(AppCode.ERROR.getResCode());
returnBo.setMsg(processErrorMsg(result));
return returnBo;
}
private static String processErrorMsg(BindingResult result) {
List<FieldError> list = result.getFieldErrors();
StringBuilder msg = new StringBuilder();
for (FieldError fieldError : list) {
msg.append("[");
msg.append(fieldError.getField());
msg.append(":");
msg.append(fieldError.getDefaultMessage());
msg.append("]");
}
return msg.toString();
}
}
以上 processErrorMsg 会暴露字段名 去除fieldError.getField()即可