关于spring web应用中关于如何使用 Bean Validation API和hibernate-validator的文章已经不少,本文就再也不重复叙述,今天要介绍的重点是在SpringBoot restful服务中如何根据不一样验证错误响应不一样的自定义错误码。下面直接上代码。java
阿里java开发手册中定义的一段参考【“对于公司外的 http/api 开放接口必须使用“错误码”; 而应用内部推荐异常抛出;跨应用间 RPC 调用优先考虑使用 Result 方式,封装 isSuccess()方法、 “错误码”、 “错误简短信息”。】。所以这里也定义个返回结构。git
public class CommonResult<T> implements Serializable { /** * serialVersionUID:. */ private static final long serialVersionUID = -7268040542410707954L; /** * 是否成功 */ private boolean success = false; /** * 返回信息 */ private String message; /** * 装在数据 */ private T data; /** * 错误代码 */ private String code; /** * 默认构造器 */ public CommonResult() { } /** * @param success 是否成功 * @param message 返回的消息 */ public CommonResult(boolean success, String message) { this.success = success; this.message = message; } /** * @param success 是否成功 */ public CommonResult(boolean success) { this.success = success; } /** * @param code error code * @param message success or error messages */ public CommonResult(String code, String message) { this.code = code; this.message = message; } /** * @param success 是否成功 * @param message 消息 * @param data 数据 */ public CommonResult(boolean success, String message, T data) { this.success = success; this.message = message; this.data = data; } //省略get set }
在有须要国际化的项目,固然选择经过i18n来配置更好,此处为了简单直接采用枚举定义。这里定义的错误仅供参考,不一样公司每一个应用在实际状况下可能都不大同样。github
/** * 错误代码枚举类 * */ public enum ErrorCodeEnum { SUCCESS("0000", "success"), PARAM_EMPTY("1001", "必选参数为空"), PARAM_ERROR("1002", "参数格式错误"), UNKNOWN_ERROR("9999", "系统繁忙,请稍后再试...."); private String code; private String desc; ErrorCodeEnum(String code, String desc) { this.code = code; this.desc = desc; } public String getCode() { return this.code; } public String getDesc() { return desc; } @Override public String toString() { return "ErrorCodeEnum{" + "code='" + code + '\'' + ", desc='" + desc + '\'' + '}'; } }
静态封装CommonResult主要是方便在项目中快速根据逻辑写返回结果代码。web
/** * 公共响应结果成功失败的静态方法调用 * */ public class ResultUtil { /** * return success * * @param data * @return */ public static <T> CommonResult<T> returnSuccess(T data) { CommonResult<T> result = new CommonResult(); result.setCode(ErrorCodeEnum.SUCCESS.getCode()); result.setSuccess(true); result.setData(data); result.setMessage(ErrorCodeEnum.SUCCESS.getDesc()); return result; } /** * return error * * @param code error code * @param msg error message * @return */ public static CommonResult returnError(String code, String msg) { CommonResult result = new CommonResult(); result.setCode(code); result.setData(""); result.setMessage(msg); return result; } /** * use enum * * @param status * @return */ public static CommonResult returnError(ErrorCodeEnum status) { return returnError(status.getCode(), status.getDesc()); } }
/** * BaseController * */ public abstract class BaseController { private static final Logger LOGGER = LoggerFactory.getLogger(BaseController.class); /** * validate params * * @param bindingResult * @return */ protected CommonResult validParams(BindingResult bindingResult) { if (bindingResult.hasErrors()) { FieldError fieldError = bindingResult.getFieldError(); return processBindingError(fieldError); } return ResultUtil.returnSuccess(""); } /** * 根据spring binding 错误信息自定义返回错误码和错误信息 * * @param fieldError * @return */ private CommonResult processBindingError(FieldError fieldError) { String code = fieldError.getCode(); LOGGER.debug("validator error code: {}", code); switch (code) { case "NotEmpty": return ResultUtil.returnError(ErrorCodeEnum.PARAM_EMPTY.getCode(), fieldError.getDefaultMessage()); case "NotBlank": return ResultUtil.returnError(ErrorCodeEnum.PARAM_EMPTY.getCode(), fieldError.getDefaultMessage()); case "NotNull": return ResultUtil.returnError(ErrorCodeEnum.PARAM_EMPTY.getCode(), fieldError.getDefaultMessage()); case "Pattern": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); case "Min": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); case "Max": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); case "Length": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); case "Range": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); case "Email": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); case "DecimalMin": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); case "DecimalMax": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); case "Size": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); case "Digits": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); case "Past": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); case "Future": return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage()); default: return ResultUtil.returnError(ErrorCodeEnum.UNKNOWN_ERROR); } } }
这里直接给出一个简单的参数验证例子。spring
Controller继承上面写的BaseControllerapi
/** * 关于Validator使用测试 * */ @RestController @RequestMapping("validator") public class ValidatorTestController extends BaseController { private static final Logger LOGGER = LoggerFactory.getLogger(ValidatorTestController.class); /** * validate验证测试 * * @param leader * @param bindingResult * @return */ @PostMapping("/test") public CommonResult testSimpleValidate(@Valid @RequestBody Leader leader, BindingResult bindingResult) { LOGGER.debug("ReqParams:{}", JSON.toJSONString(leader)); CommonResult result = validParams(bindingResult); if (!result.isSuccess()) { return result; } return ResultUtil.returnSuccess(""); } }
入参对象Leader代码restful
public class Leader { /** * 姓名 */ @NotEmpty private String name; /** * 生日 */ @Pattern(regexp = "^[0-9]{4}-[0-9]{2}-[0-9]{2}$", message = "出生日期格式不正确") private String birthday; /** * 年龄 */ @Min(value = 0) private Integer age; //省略gettes and setters }
这时项目已经已经彻底能够根据验证错误来返回自定义的错误码和提示了。app
本例所涉及源代码:https://github.com/shalousun/api-doc-testide
在一些对外服务提供restful的应用中,根据不一样的验证错误返回实际上是避免不了的。固然实现的方式能够有种,而本文所采用的方式相对来讲简单易懂。测试
版权申明:转载请注明出处,不然后果自负