文
章
目
录
章
目
录
我们在开发SpringBoot项目时,有时候需要对外提供接口,对外暴露的接口在接收到请求参数时,我们无法保障参数是否满足我们的需求,比如是否为空、是否长度太长等等,如果我们自己手工一个个属性去校验,那将是非常的麻烦,因此,我们可以使用一些校验框架帮助我们实现改过程,如果存在不符合规则的属性,我们可以示使用全局异常来进行统一处理。下面,潘老师给大家实现一个案例代码,可供大家参考学习。
1、导入依赖
我们在这里使用hibernate-validator框架进行校验,首先我们需要导入相关依赖:
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.7.Final</version>
</dependency>
2、请求参数
我们先定义一个请求参数类,这里使用了lombok简化了代码,如下:
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@AllArgsConstructor
public class User {
// 用户名
@NotBlank(message = "参数不能为空")
@Length(max = 10,message = "参数长度不能超过10")
private String username;
// 密码
@NotBlank(message = "参数不能为空")
@Length(max = 50,message = "参数长度不能超过50")
private String password;
// 邮箱
@Email(message = "必须为邮箱格式")
private String email;
}
3、接口校验参数
接下来我们队接收到的User 参数进行校验,只需要在方法参数前加上@Validated注解,具体代码如下:
@RestController
@RequestMapping("/api/user")
public class ScheduleApi {
@Autowired
private UserService userService;
/**
* 接收用户信息保存
*/
@PostMapping("/save")
public ResponseResult saveUser(@Validated @RequestBody User user){
// 响应对象-可自行定义
ResponseResult responseResult;
// 执行保存操作
boolean flag = userService.save(user);
if(flag){ // 保存成功
responseResult = ResponseResult.success();
}else { // 保存失败
responseResult = ResponseResult.fail();
}
return responseResult;
}
}
注意:这里面@Validated注解会对user参数根据实体类中的注解信息进行属性校验,如果有任何一个不满足条件就会抛出MethodArgumentNotValidException异常,这个异常我们需要统一处理
4、全局参数异常处理
我们自定义一个全局异常处理类,我这里定义为GlobalExceptionHandler,具体代码如下:
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
/**
* 全局方法参数校验异常处理,只要方法抛出MethodArgumentNotValidException异常,就会被此方法拦截处理
*/
@ExceptionHandler({MethodArgumentNotValidException.class})
public ResponseResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
StringBuilder sb = new StringBuilder("请求参数异常:");
// 遍历拼接所有参数异常信息
List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
fieldErrors.forEach(error->{
sb.append(error.getField()+":"+error.getDefaultMessage()+";");
});
return ResponseResult.fail().setCode(ResponseConstants.PARAM_ERROR_CODE)
.setMsg(ResponseConstants.PARAM_ERROR_MSG);
}
}
注意:这里使用了@ControllerAdvice注解来实现,我们也可以可使用它的basePackages属性指定某个或某些包下的异常进行统一处理,如@ControllerAdvice(basePackages={“com.panziye.controller,com.panziye.thread”})
以上我们就实现了对请求参数的统一校验与统一处理。
5、补充:参数分组校验
有一种特殊的情况就是,如果你的实体类每个属性都写死了校验注解,那么在任何时候只要你在参数前加上@Validated注解都会使用该规则进行校验,但是有时候我们在不同的方法中,可能会对不同的参数有不同的校验情况,比如在保存时要求这3个属性必须非空,且email满足格式要求,在更新时只需要username不为空,其他属性不校验,那么我们就要对这两种情形进行分组:
1)首先我们需要建一个分组类Groups,类中建多个接口,一个组对应一个接口(我这里就写两个):
public class Groups {
// 保存校验组
public interface Insert{}
// 更新校验组
public interface Update{}
}
2)接着我们对参数类属性注解进行分组校验:
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@AllArgsConstructor
public class User {
// 用户名
@NotBlank(message = "参数不能为空",groups = {Groups.Insert.class,Groups.Update.class})
@Length(max = 10,message = "参数长度不能超过10")
private String username;
// 密码
@NotBlank(message = "参数不能为空",groups = Groups.Insert.class)
@Length(max = 50,message = "参数长度不能超过50")
private String password;
// 邮箱
@Email(message = "必须为邮箱格式",groups = Groups.Insert.class)
private String email;
}
3)现在在保存和更新方法中,对参数校验的注解就要有所修改,如下:
// 保存
public ResponseResult saveUser(@Validated(value = Groups.Insert.class) @RequestBody User user){
//省略逻辑...
}
// 更新
public ResponseResult updateUser(@Validated(value = Groups.Update.class) @RequestBody User user){
//省略逻辑...
}
提示:这里@Validated中value也可以指定为数组,综合多个分组,比如:@Validated(value = {Groups.Insert.class, Groups.Update.class})
以上,就实现了分组校验啦~






