Spring Boot validator参数验证restful自定义错误码响应

关于spring web应用中关于如何使用 Bean Validation _API_和hibernate-validator的文章已经很多,本文就不再重复叙述,今天要介绍的重点是在SpringBoot restful服务中如何根据不同验证错误响应不同的自定义错误码。下面直接上代码。

一、定义restful统一结果返回

阿里java开发手册中定义的一段参考【“对于公司外的 http/api 开放接口必须使用“错误码”; 而应用内部推荐异常抛出;跨应用间 RPC 调用优先考虑使用 Result 方式,封装 isSuccess()方法、 “错误码”、 “错误简短信息”。】。因此这里也定义个返回结构。

1public class CommonResult<T> implements Serializable { 2 3 /** 4 * serialVersionUID:. 5 */ 6 private static final long serialVersionUID = -7268040542410707954L; 7 8 /** 9 * 是否成功 10 */ 11 private boolean success = false; 12 13 /** 14 * 返回信息 15 */ 16 private String message; 17 18 /** 19 * 装在数据 20 */ 21 private T data; 22 23 /** 24 * 错误代码 25 */ 26 private String code; 27 28 /** 29 * 默认构造器 30 */ 31 public CommonResult() { 32 33 } 34 35 /** 36 * @param success 是否成功 37 * @param message 返回的消息 38 */ 39 public CommonResult(boolean success, String message) { 40 this.success = success; 41 this.message = message; 42 } 43 44 /** 45 * @param success 是否成功 46 */ 47 public CommonResult(boolean success) { 48 this.success = success; 49 } 50 51 /** 52 * @param code error code 53 * @param message success or error messages 54 */ 55 public CommonResult(String code, String message) { 56 this.code = code; 57 this.message = message; 58 } 59 60 /** 61 * @param success 是否成功 62 * @param message 消息 63 * @param data 数据 64 */ 65 public CommonResult(boolean success, String message, T data) { 66 this.success = success; 67 this.message = message; 68 this.data = data; 69 } 70 //省略get set 71}

二、定义一个错误码枚举

在有需要国际化的项目,当然选择通过i18n来配置更好,此处为了简单直接采用枚举定义。这里定义的错误仅供参考,不同公司每个应用在实际情况下可能都不大一样。

1/** 2 * 错误代码枚举类 3 * 4 */ 5public enum ErrorCodeEnum { 6 7 SUCCESS("0000", "success"), 8 9 PARAM_EMPTY("1001", "必选参数为空"), 10 11 PARAM_ERROR("1002", "参数格式错误"), 12 13 UNKNOWN_ERROR("9999", "系统繁忙,请稍后再试...."); 14 15 private String code; 16 17 private String desc; 18 19 ErrorCodeEnum(String code, String desc) { 20 this.code = code; 21 this.desc = desc; 22 } 23 24 public String getCode() { 25 return this.code; 26 } 27 28 29 public String getDesc() { 30 return desc; 31 } 32 33 @Override 34 public String toString() { 35 return "ErrorCodeEnum{" + 36 "code='" + code + '\'' + 37 ", desc='" + desc + '\'' + 38 '}'; 39 } 40}

三、静态封装CommonResult

静态封装CommonResult主要是方便在项目中快速根据逻辑写返回结果代码。

1/** 2 * 公共响应结果成功失败的静态方法调用 3 * 4 */ 5public class ResultUtil { 6 7 8 /** 9 * return success 10 * 11 * @param data 12 * @return 13 */ 14 public static <T> CommonResult<T> returnSuccess(T data) { 15 CommonResult<T> result = new CommonResult(); 16 result.setCode(ErrorCodeEnum.SUCCESS.getCode()); 17 result.setSuccess(true); 18 result.setData(data); 19 result.setMessage(ErrorCodeEnum.SUCCESS.getDesc()); 20 return result; 21 } 22 23 /** 24 * return error 25 * 26 * @param code error code 27 * @param msg error message 28 * @return 29 */ 30 public static CommonResult returnError(String code, String msg) { 31 CommonResult result = new CommonResult(); 32 result.setCode(code); 33 result.setData(""); 34 result.setMessage(msg); 35 return result; 36 37 } 38 39 /** 40 * use enum 41 * 42 * @param status 43 * @return 44 */ 45 public static CommonResult returnError(ErrorCodeEnum status) { 46 return returnError(status.getCode(), status.getDesc()); 47 } 48}

四、定义BaseController来处理验证错误自定义错误码返回

1/** 2 * BaseController 3 * 4 */ 5public abstract class BaseController { 6 7 private static final Logger LOGGER = LoggerFactory.getLogger(BaseController.class); 8 9 /** 10 * validate params 11 * 12 * @param bindingResult 13 * @return 14 */ 15 protected CommonResult validParams(BindingResult bindingResult) { 16 if (bindingResult.hasErrors()) { 17 FieldError fieldError = bindingResult.getFieldError(); 18 return processBindingError(fieldError); 19 } 20 return ResultUtil.returnSuccess(""); 21 } 22 23 /** 24 * 根据spring binding 错误信息自定义返回错误码和错误信息 25 * 26 * @param fieldError 27 * @return 28 */ 29 private CommonResult processBindingError(FieldError fieldError) { 30 String code = fieldError.getCode(); 31 LOGGER.debug("validator error code: {}", code); 32 switch (code) { 33 case "NotEmpty": 34 return ResultUtil.returnError(ErrorCodeEnum.PARAM_EMPTY.getCode(), fieldError.getDefaultMessage()); 35 case "NotBlank": 36 return ResultUtil.returnError(ErrorCodeEnum.PARAM_EMPTY.getCode(), fieldError.getDefaultMessage()); 37 case "NotNull": 38 return ResultUtil.returnError(ErrorCodeEnum.PARAM_EMPTY.getCode(), fieldError.getDefaultMessage()); 39 case "Pattern": 40 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 41 case "Min": 42 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 43 case "Max": 44 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 45 case "Length": 46 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 47 case "Range": 48 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 49 case "Email": 50 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 51 case "DecimalMin": 52 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 53 case "DecimalMax": 54 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 55 case "Size": 56 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 57 case "Digits": 58 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 59 case "Past": 60 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 61 case "Future": 62 return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); 63 default: 64 return ResultUtil.returnError(ErrorCodeEnum.UNKNOWN_ERROR); 65 } 66 } 67}

五、验证实例

这里直接给出一个简单的参数验证例子。

Controller继承上面写的BaseController

1/** 2 * 关于Validator使用测试 3 * 4 */ 5 6@RestController 7@RequestMapping("validator") 8public class ValidatorTestController extends BaseController { 9 10 private static final Logger LOGGER = LoggerFactory.getLogger(ValidatorTestController.class); 11 12 /** 13 * validate验证测试 14 * 15 * @param leader 16 * @param bindingResult 17 * @return 18 */ 19 @PostMapping("/test") 20 public CommonResult testSimpleValidate(@Valid @RequestBody Leader leader, BindingResult bindingResult) { 21 LOGGER.debug("ReqParams:{}", JSON.toJSONString(leader)); 22 CommonResult result = validParams(bindingResult); 23 if (!result.isSuccess()) { 24 return result; 25 } 26 return ResultUtil.returnSuccess(""); 27 } 28}

入参对象Leader代码

1public class Leader { 2 3 /** 4 * 姓名 5 */ 6 @NotEmpty 7 private String name; 8 9 /** 10 * 生日 11 */ 12 @Pattern(regexp = "^[0-9]{4}-[0-9]{2}-[0-9]{2}$", message = "出生日期格式不正确") 13 private String birthday; 14 15 /** 16 * 年龄 17 */ 18 @Min(value = 0) 19 private Integer age; 20 21 //省略gettes and setters 22 23}

这时项目已经已经完全可以根据验证错误来返回自定义的错误码和提示了。

本例所涉及源代码:https://github.com/shalousun/api-doc-test

总结

在一些对外服务提供restful的应用中,根据不同的验证错误返回其实是避免不了的。当然实现的方式可以有种,而本文所采用的方式相对来说简单易懂。

版权申明:转载请注明出处,否则后果自负

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )