在controller里面我们一般都要做参数检验,参数输入不正确可能导致数据不合理或者运行异常,本文主要介绍如何使用@Validated注解做请求参数的校验
@Validated
@RestController
@RequestMapping("/good")
public class ParasCheckController {
}
这里以使用RESTfull风格的API接口为例,下面是对goodNo参数的校验,当goodNo不为6位长度的数字时,会抛出ConstraintViolationException异常
@GetMapping("/good/{goodNo}")
public BRB good(@Pattern(regexp = "^[0-9]{6}$", message = "商品编号不正确") @PathVariable("goodNo") String goodNo) {
log.info("TAG=good, METHOD=get, goodNo={}", goodNo);
return new BRB(BRStatus.SUCCESS, "获取商品goodNo=" + goodNo + "信息");
}
接口如下,
@PostMapping
public BRB good(@RequestBody @Valid GoodReq goodReq, BindingResult bindingResult) {
log.info("TAG=good, METHOD=post, goodNo={}, goodName={}, goodPrice={}", goodReq.getGoodNo(), goodReq.getGoodName(), goodReq.getGoodPrice());
return new BRB(BRStatus.SUCCESS, "增加新商品成功");
}
GoodReq类描述了输入参数的要求,比如输入的goodNo、goodName、goodPrice都不能为空,商品编号goodNo必须为6位长度的数字字符串。如果输入参数不符合要求,则会抛出ConstraintViolationException异常
@Data
public class GoodReq {
@NotBlank(message = "商品编号不能为空")
@Pattern(regexp = "^[0-9]{6}$", message = "商品编号不正确")
private String goodNo;
@NotBlank(message = "商品名不能为空")
@Size(max = 20, message = "商品名不能大于20")
private String goodName;
@NotNull(message = "商品价格不能为空")
private Integer goodPrice;
}
@Validated注解的使用会抛出ConstraintViolationException异常,但上面截图还是正常的httpStatus 200返回,是因为对ConstraintViolationException异常做了处理
核心代码如下,更多请参考GitHub项目
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandlerController {
@ExceptionHandler(ConstraintViolationException.class)
public void handleConstraintViolationException(HttpServletResponse resp, ConstraintViolationException ex) throws IOException {
log.info("ConstraintViolationException");
String msg = ex.getMessage();
String[] msgs = msg.split(": ");
resp.sendError(HttpStatus.OK.value(), BRStatus.PARAS_ERROR.getStatus() + msgs[msgs.length-1]);
}
}
@Slf4j
@Controller
public class MyErrorController extends BasicErrorController {
@Override
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = getStatus(request);
//输出自定义的Json格式
Map<String, Object> map = new HashMap<String, Object>();
map.put("status", status.value());
String message = (String) body.get("message");
if (message == null || message.equals("No message available")) {
map.put("msg", status.getReasonPhrase());
} else {
if (message.startsWith(BRStatus.PARAS_ERROR.getStatus()+"")) {
map.put("status", BRStatus.PARAS_ERROR.getStatus());
map.put("msg", message.substring(3));
} else {
map.put("msg", body.get("message"));
}
}
map.put("timestamp", sdf4.format(new Date()));
return new ResponseEntity<>(map, status);
}
}
GitHub项目