发布时间:2024-06-20 12:01
1.前言
在开发电商等web应用时,难免要对前端传来的参数进行校验,如果大量的使用if else会增加代码的复杂性,java提供了标准类库,可以如下操作
public class CartAddForm {
@NotNull
private Integer productId;
private Boolean selected = true;
}
2.在controller层中校验参数
在controller层中通过@Valid注解校验前端的参数
@RestController
public class CartController {
@PostMapping("/carts")
public ResponseVo<CartVo> add(@Valid @RequestBody CartAddForm cartAddForm) {
return null;
}
}
3.参数校验错误会导致什么
在postman中测试,参数CartForm设置为空,postman界面如下
提示用户未登录,这是拦截器的问题,将url加入到添加到白名单中
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
//将自己写的拦截器注册上去,然后配置对应的url
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UserLoginInterceptor())
//默认对所有接口拦截,除了登录和注册接口
.addPathPatterns("/**")
.excludePathPatterns("/carts","/user/login", "/user/register","/categories","/products","/products/*");
}
}
测试后还是提示用户未登录,利用debug模式在preHandle处打个断点,重新在postman中测试后断点处数据如下
出现了url为"/error",这是因为前端传来的数据校验错误,spring把这个错误重定向到“/error”,然后这个地址被登录拦截器拦截了,最终导致前端出现用户未登录的界面
4.BindingResult的使用
第一种方法,我们可以直接在controller中通过BindingResult类,然后根据这个校验返回看是否有参数错误
//非空校验
if (bindingResult.hasErrors()) {
log.error("注册提交的参数有误, {} {}",
bindingResult.getFieldError().getDefaultMessage());
return ResponseVo.error(PARAM_ERROR, bindingResult);
}
第二种方法,当项目中多处出现参数校验的时候,就可以使用统一异常处理,参数校验错误后,会抛出一个MethodArgumentNotValidException异常,我们可以捕获这个异常并处理
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public ResponseVo notValidExceptionHandle(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
Objects.requireNonNull(bindingResult.getFieldError());
return ResponseVo.error(ResponseEnum.PARAM_ERROR,
bindingResult.getFieldError().getField() + " " + bindingResult.getFieldError().getDefaultMessage());
}
上述程序中,在异常处理的时候先通过异常类获得了 BindingResult,然后先获取到校验错误的变量,随后get到错误的信息,并返回给前台。