SpringBoot项目实现接口参数校验(含分组校验)与全局异常处理

Java技术 潘老师 3年前 (2021-06-17) 1905 ℃ (0) 扫码查看

我们在开发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;
}

hibernate-validator框架支持的注解如下:
SpringBoot项目实现接口参数校验(含分组校验)与全局异常处理

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})

以上,就实现了分组校验啦~


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/java/3273.html
喜欢 (6)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】