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

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

一、定义restful统一结果返回

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

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来配置更好,此处为了简单直接采用枚举定义。这里定义的错误仅供参考,不同公司每个应用在实际情况下可能都不大一样。

/**
 * 错误代码枚举类
 *
 */
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 "[" + this.code + "]" + this.desc;
    }
}

三、静态封装CommonResult

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

/**
 * 公共响应结果成功失败的静态方法调用
 *
 */
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来处理验证错误自定义错误码返回

/**
 * 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);
        }
    }
}

五、验证实例

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

Controller继承上面写的BaseController

/**
 * 关于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代码

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

}

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

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

总结

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

本文同步博客:https://my.oschina.net/u/1760791/blog/1842315

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot 提供了多种方式来验证 RESTful API 返回的 JSON。 1. 手动验证 手动验证是最基本的验证方式。通过使用 Postman 或类似的工具发送请求,然后手动比较返回的 JSON 和预期的 JSON 是否一致。这种方法适用于简单的 API,但对于复杂的 API,手动验证将变得非常困难。 2. 单元测试 单元测试是验证 RESTful API 返回的 JSON 的最佳方式之一。通过使用 Spring Boot 的测试框架,可以编写测试用例来模拟 API 请求,并验证返回的 JSON 是否符合预期。这种方法可以自动化测试,并在代码变更时自动运行测试用例,确保 API 的正确性。 3. 集成测试 集成测试是测试整个系统的功能的最佳方式,包括 RESTful API。通过使用集成测试,可以验证 API 返回的 JSON 是否符合预期,并确保整个系统的正确性。集成测试可以使用自动化测试框架,例如 Selenium、Cucumber 或 Robot Framework。 4. Swagger UI Swagger UI 是一个流行的 API 文档和测试工具,可以使用它来验证 RESTful API 返回的 JSON。Swagger UI 可以在 API 文档中直接测试 API,并验证返回的 JSON 是否符合预期。此外,Swagger UI 还提供了自动生成 API 文档的功能,使得 API 的文档化变得非常容易。 5. JSON 校验工具 最后,可以使用 JSON 校验工具来验证 RESTful API 返回的 JSON。这些工具可以检查 JSON 是否符合规范,并提供有关 JSON 中错误的详细信息。一些流行的 JSON 校验工具包括 JSONLint、JSON Validator 和 JSON Formatter。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值