优雅的实现前后端交互Validator+@RestControllerAdvice

前后端交互经常遇到参数多,不同开发人员返回数据结构不统一的问题,今天分享一种跟更优雅的方式,让研发人员跳出格式限制,把更多的经历放在逻辑处理上。
1、参数校验:Validator + BindResult进行校验
1.1 构建User实体类,通过注解形式校验参数。

@Data
public class User {
    @NotNull(message = "用户id不能为空")
    private Long id;

    @NotNull(message = "用户账号不能为空")
    @Size(min = 6, max = 11, message = "账号长度必须是6-11个字符")
    private String account;

    @NotNull(message = "用户密码不能为空")
    @Size(min = 6, max = 11, message = "密码长度必须是6-16个字符")
    private String password;

    @NotNull(message = "用户邮箱不能为空")
    @Email(message = "邮箱格式不正确")
    private String email;
}


1.2 controller增加@Valid注解,即可启用校验。校验失败,会抛出MethodArgumentNotValidException异常。

@RestController
@RequestMapping("user2")
public class UserController2 {
    @PostMapping("/addUser")
    public User addUser(@RequestBody @Valid User user) {

        return user;
    }
}

2、统一返回数据结构
2.1 全局异常处理
    定义ExceptionControllerAdvice,使用全局注解@RestControllerAdvice(basePackages = "com.example.demo.controller"),接受异常注解@ExceptionHandler(MethodArgumentNotValidException.class),即可统一处理异常。

@RestControllerAdvice(basePackages = "com.example.demo.controller")
public class ExceptionControllerAdvice {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultVO<String> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        // 从异常对象中拿到ObjectError对象
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        // 然后提取错误提示信息进行返回
        return new ResultVO<>(ResultCode.VALIDATE_FAILED, objectError.getDefaultMessage());
    }
}


2.2 全局数据结构处理
    定义ResponseControllerAdvice,使用全局注解@RestControllerAdvice(basePackageClasses = {UserController2.class,UserController.class}),实现ResponseBodyAdvice<Object>,即可处理全局返回结果。

@RestControllerAdvice(basePackageClasses = {UserController2.class,UserController.class})
public class ResponseControllerAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        // 如果接口返回的类型本身就是ResultVO那就没有必要进行额外的操作,返回false
        System.out.println(methodParameter.getGenericParameterType().equals(ResultVO.class));
        return !methodParameter.getGenericParameterType().equals(ResultVO.class);
    }

    @Override
    public Object beforeBodyWrite(Object data, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        // String类型不能直接包装,所以要进行些特别的处理
        if (methodParameter.getGenericParameterType().equals(String.class)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 将数据包装在ResultVO里后,再转换为json字符串响应给前端
                return objectMapper.writeValueAsString(new ResultVO<>(data));
            } catch (JsonProcessingException e) {
                throw new APIException("返回String类型错误");
            }
        }
        // 将原本的数据包装在ResultVO里
        return new ResultVO<>(data);
    }
}

3、结果测试
3.1 异常测试


3.2 正常结果测试

简单易学,搞定!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值