SpringBoot注解校验请求参数

本文介绍了一种使用注解和自定义校验器改进参数校验的方法,通过在实体类属性上添加注解如@NotEmpty、@Pattern和自定义@SizeValidator,结合Spring框架的@Valid注解,实现了更简洁、可读性强的参数校验流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

常规校验

    @RequestMapping(
            value = "test",
            method = RequestMethod.POST)
    public FrogTest test(@RequestBody FrogTest bean) {
        if (bean.getName() == null) {
            throw new MyException("A02", "名称不能为空");
        }
        if (bean.getSize() > 100) {
            throw new MyException("A03", "size值超过允许最大值");
        }
        return bean;
    }

通常通过以上方式,对前端请求参数进行校验,如果请求bean(FrogTest)中需要校验的属性太多时,对每个参数写一个对应的if判断,代码可读性很差,所以可以在请求对象属性加上注解来校验其合法性。

属性加校验注解

public class FrogTest implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @NotEmpty(message = "名称项不能为空")
    private String name;

    private String describ;

    private LocalDateTime date;

    @NotEmpty(message = "状态标识项不能为空")
    @Pattern(regexp = "[012]", message = "无效的状态标志")
    private String state;

    @SizeValidator(maxSize = 100.1, message = "值太大")
    private Double size;
    ...
    省略getter和setter
}

其中@NotEmpty和@Pattern是javax.validation.constraints包中注解,前者表示不为空,后者表示为特定格式,现在表示只能为0、1、2。@SizeValidator是自定义注解,用来校验值得大小(可以用@Size),如下:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
        validatedBy = {SizeValidatorImpl.class}
)
public @interface SizeValidator {

    double maxSize() default 10000.0;

    String message() default "值得大小不合法";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

约束实现类:

public class SizeValidatorImpl implements ConstraintValidator<SizeValidator, Double> {

    private double maxSize;

    @Override
    public void initialize(SizeValidator constraintAnnotation) {
        maxSize = constraintAnnotation.maxSize();
    }

    @Override
    public boolean isValid(Double value, ConstraintValidatorContext context) {
        if (value > 0 && value < maxSize) {
            return true;
        }
        return false;
    }
}

修改Controller

请求参数增加@Valid注解

    @RequestMapping(
            value = "test",
            method = RequestMethod.POST)
    public FrogTest test(@RequestBody @Valid FrogTest bean) {
        /*不需要通过if判断校验
        if (bean.getName() == null) {
            throw new MyException("A02", "名称不能为空");
        }
        if (bean.getSize() > 100) {
            throw new MyException("A03", "size值超过允许最大值");
        }*/
        return bean;
    }

异常拦截与返回

SpringBoot项目通用返回值与全局异常处理的基础上修改

@RestControllerAdvice
public class MyExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @ExceptionHandler(Exception.class)
    public Object handleException(Exception e, HttpServletRequest request, HttpServletResponse response){

        logger.error("请求:{}发生异常:{}", request.getRequestURI(), e);

        Result result = new Result();
        result.setSuccess(false);
        if (e instanceof MyException) {
            result.setErrorCode(((MyException) e).getErrorCode());
            result.setErrorMsg(((MyException) e).getErrorMsg());
        } else {
            result.setErrorCode(MyExceptionEnum.SYSTEM_ERROR.getCode());
            result.setErrorMsg(MyExceptionEnum.SYSTEM_ERROR.getMsg());
        }

        return result;
    }

    /**
     * 自定义注解异常拦截
     */
    @ExceptionHandler({BindException.class, ConstraintViolationException.class, MethodArgumentNotValidException.class})
    public Object handleMethodArgumentNotValidException(Exception e, HttpServletRequest request) {

        logger.error("请求:{}发生异常:{}", request.getRequestURI(), e);

        // 错误信息
        StringBuilder sb = new StringBuilder("参数校验失败:");
        // 错误信息map
        Map<String, String> error = new HashMap<>();

        String msg = "";
        if (!(e instanceof BindException) && !(e instanceof MethodArgumentNotValidException)) {
            for (ConstraintViolation cv: ((ConstraintViolationException)e).getConstraintViolations()) {
                msg = cv.getMessage();
                sb.append(msg).append(";");

                Iterator<Path.Node> it = cv.getPropertyPath().iterator();
                Path.Node last = null;
                while (it.hasNext()) {
                    last = (Path.Node)it.next();
                }
                /*for(last = null; it.hasNext(); last = (Path.Node)it.next()) {
                }*/
                error.put(last != null ? last.getName() : "", msg);
            }
        } else {
            List<ObjectError> allErrors = null;
            if (e instanceof BindException) {
                allErrors = ((BindException)e).getAllErrors();
            } else {
                allErrors = ((MethodArgumentNotValidException)e).getBindingResult().getAllErrors();
            }
            // 拼接错误信息
            for (ObjectError oe : allErrors) {
                msg = oe.getDefaultMessage();
                sb.append(msg).append(";");
                if (oe instanceof FieldError) {
                    error.put(((FieldError)oe).getField(), msg);
                } else {
                    error.put(oe.getObjectName(), msg);
                }
            }
        }

        Result<Map> result = new Result<>(error);
        result.setSuccess(false);
        result.setErrorCode(MyExceptionEnum.REQUESTPARAM_ERROR.getCode());
        result.setErrorMsg(MyExceptionEnum.REQUESTPARAM_ERROR.getMsg() + sb.toString());
        return result;
    }
}

测试

在这里插入图片描述

在这里插入图片描述
提示了错误信息,以及每个属性的校验失败信息,可以根据需要调整是否显示或记录到日志中。

### Spring Boot 中使用注解进行参数校验 在Spring Boot应用程序中,为了确保接收到的请求参数符合预期格式和规则,可以利用内置的校验机制。这种做法有助于提升系统的安全性和稳定性[^1]。 #### 添加依赖项 要启用Spring Boot中的参数校验功能,需先向`pom.xml`文件添加必要的Maven依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> ``` 此依赖集成了Hibernate Validator——JSR 380 (Bean Validation 2.0) 的一种实现方案,它扩展了基本的标准并增加了更多实用的约束注解,如 `@Email`, `@Length` 等[^2]。 #### 创建数据传输对象(DTO) 定义一个用于接收HTTP请求的数据模型类,在字段上应用合适的验证注解: ```java import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; public class UserDTO { @NotBlank(message = "用户名不能为空") private String username; @Size(min=6, max=30, message="密码长度应在6到30之间") private String password; @Email(message="请输入有效的电子邮件地址") private String email; // Getters and Setters... } ``` 上述代码片段展示了如何通过简单的注解来规定属性的有效范围或模式匹配条件。 #### 控制器层集成校验逻辑 当创建RESTful API端点时,可以在方法签名处声明`@Valid` 或者更灵活的 `@Validated` 注解以触发自动化的输入检查过程;如果检测到任何违反既定规则的情况,则会立即终止处理链并向客户端反馈详细的错误描述信息。 ```java @RestController @RequestMapping("/api/users") public class UserController { @PostMapping("") public ResponseEntity<String> createUser(@RequestBody @Valid UserDTO user){ // 正常情况下继续执行业务操作... return new ResponseEntity<>("User created successfully", HttpStatus.CREATED); } } ``` 一旦发生校验失败的情形,默认行为是由框架内部抛出`MethodArgumentNotValidException`异常,并最终由全局异常处理器负责捕捉此类事件以便统一响应格式化输出给前端使用者查看[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值