Springboot中请求参数校验

目录

1.添加依赖

2.添加拦截器

3.添加拦截配置

4.请求参数属性规则定义

5.添加校验注解

6.测试参数校验

7.注解说明

8.常见问题


1.添加依赖

<!-- 参数校验 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2.添加拦截器

拦截器用来拦截校验参数统一封装响应数据

package com.hhmt.delivery.handler;

import com.hhmt.delivery.ocpx.bean.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;

/**
 * 辉煌明天
 * FileName: ValidatedAdvice
 * Author:   huachun
 * email: huachun_w@163.com
 * Date:     2022/3/11 11:52
 * Description:
 */
@ControllerAdvice
@Slf4j
public class ValidatedAdvice {

    //处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常,详情继续往下看代码
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public ResultVo BindExceptionHandler(BindException e) {
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return ResultVo.error(message);
    }

    //处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是javax.validation.ConstraintViolationException
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public ResultVo ConstraintViolationExceptionHandler(ConstraintViolationException e) {
        String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
        return ResultVo.error(message);
    }

    //处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常。
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResultVo MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return ResultVo.error(message);
    }
}

3.添加拦截配置

如果多个请求参数都校验失败,则遇到第一个校验失败就抛出异常,接下来的异常参数不做校验,配置如下

package com.hhmt.delivery.config;

import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

/**
 * 辉煌明天
 * FileName: WebValidateConfig
 * Author:   huachun
 * email: huachun_w@163.com
 * Date:     2022/3/11 14:27
 * Description:
 */
@Configuration
public class WebValidateConfig {

    @Bean
    public Validator validator() {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                //failFast的意思只要出现校验失败的情况,就立即结束校验,不再进行后续的校验。
                .failFast(true)
                .buildValidatorFactory();

        return validatorFactory.getValidator();
    }

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator());
        return methodValidationPostProcessor;
    }
}

4.请求参数属性规则定义

package com.hhmt.delivery.entity;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

/**
 * 辉煌明天
 * FileName: BaseMediaDto
 * Author:   huachun
 * email: huachun_w@163.com
 * Date:     2022/1/12 11:35
 * Description:
 */
@Data
public class BaseMediaDto extends BaseOcpxInfo {

    @ApiModelProperty(value = "链路编码,由辉煌明天提供", example = "00000", required = true)
    @Length(max = 6, message = "chainCode不能超过6位")
    private String chainCode;

    @ApiModelProperty(hidden = true)
    @Length(max = 256, message = "source不能超过256位")
    private String source;

    @ApiModelProperty(value = "设备id(imei或idfa的加密值)", example = "d4b8f3898515056278ccf78a7a2cca2d")
    private String muid;*/

    @Override
    public String toString() {
        return "BaseMediaDto{" +
                "chainCode='" + chainCode + '\'' +
                ", source='" + source + '\'' +
                "} " + super.toString();
    }
}

5.添加校验注解

在方法请求处添加 @Validated注解,否则参数不能被校验

package com.hhmt.delivery.controller;

import com.hhmt.delivery.entity.BaseMediaDto;
import com.hhmt.delivery.ocpx.bean.ResultVo;
import com.hhmt.delivery.ocpx.service.common.McService;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

/**
 * 辉煌明天
 * FileName: MediaCommonController
 * Author:   huachun
 * email: huachun_w@163.com
 * Date:     2021/12/29 19:04
 * Description:
 */
@Api(tags = "辉煌明天OCPX接口")
@RestController(value = "第三方接入")
@RequestMapping(value = "/cpa", name = "媒体公共调用控制器")
public class OcpxCommonController {

    @Autowired
    private McService mcService;

    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "成功"),
            @ApiResponse(responseCode = "CPA.00010000", description = "Request exception!"),
            @ApiResponse(responseCode = "CPA.00010001", description = "Request parameter exception!"),
    })

    @Operation(summary = "POST方式OCPX上报")
    @PostMapping(value = "/media", name = "媒体上报")
    public ResultVo click(@RequestBody @Validated BaseMediaDto mediaDto) {
        return mcService.reportCustomer(mediaDto);
    }

    @Operation(summary = "GET方式OCPX上报")
    @GetMapping(value = "/media", name = "媒体上报")
    public ResultVo mediaClick(@Validated BaseMediaDto mediaDto) {
        return mcService.reportCustomer(mediaDto);
    }

    @GetMapping(value = "/{chain}/call", name = "客户回传")
    public ResultVo call(@RequestParam Map<String, String> map, @PathVariable(value = "chain") String chain) {
        return mcService.call(map, chain);
    }

}

6.测试参数校验

第一次chainCode超过6位会直接提示

第二次更改chainCode长度提示os参数长度问题

 

7.注解说明

注解                                                            说明
@AssertFalse                                            被注释的元素必须为 false
@AssertTrue                                              被注释的元素必须为 true
@DecimalMax(value)                                 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)                                  被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Digits (integer, fraction)                           被注释的元素必须是一个数字,其值必须在可接受的范围内
@Null                                                          被注释的元素必须为 null
@NotNull                                                     被注释的元素必须不为 null
@Min(value)                                                被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)                                               被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min)                                         被注释的元素的大小必须在指定的范围内
@Past                                                          被注释的元素必须是一个过去的日期
@Future                                                       被注释的元素必须是一个将来的日期
@Pattern(value)                                           被注释的元素必须符合指定的正则表达式

8.常见问题

1.只提示异常信息,没有提示具体到参数名称

org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.hhmt.delivery.core.domain.model.ResultVo<java.lang.Integer> com.hhmt.delivery.controller.HhChainMediaParamsController.add(com.hhmt.delivery.pojo.entity.HhChainMediaParams): [Field error in object 'hhChainMediaParams' on field 'mediaId': rejected value [null]; codes [NotNull.hhChainMediaParams.mediaId,NotNull.mediaId,NotNull.java.lang.Long,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [hhChainMediaParams.mediaId,mediaId]; arguments []; default message [mediaId]]; default message [ Can't be empty]] 

问题原因:服务中有两个地方拦截了校验参数,其中一个处理时候没有处理细节信息

解决办法:删除多余的 MethodArgumentNotValidException 拦截

原文参考:Spring 捕捉校验参数异常并统一处理_weixin_40820739的博客-CSDN博客

如何使用springboot优雅地校验请求参数_stryang的博客-CSDN博客_springboot 请求参数校验

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Spring Boot ,可以使用 Hibernate Validator 来进行请求参数校验。具体步骤如下: 1. 引入 Hibernate Validator 依赖: ```xml <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.5.Final</version> </dependency> ``` 2. 在需要校验请求参数实体类添加校验注解,例如: ```java public class User { @NotBlank(message = "用户名不能为空") private String username; @NotBlank(message = "密码不能为空") private String password; @Email(message = "邮箱格式不正确") private String email; // 省略 getter 和 setter 方法 } ``` 3. 在请求处理方法添加 @Validated 注解,并在参数上添加 @Valid 注解,例如: ```java @RestController @RequestMapping("/user") @Validated public class UserController { @PostMapping("/login") public Result login(@RequestBody @Valid User user) { // 处理登录逻辑 } } ``` 4. 当请求参数不符合校验规则时,会抛出 ConstraintViolationException 异常。可以在全局异常处理器对该异常进行处理,例如: ```java @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ConstraintViolationException.class) public Result handleConstraintViolationException(ConstraintViolationException e) { List<String> errorMessages = e.getConstraintViolations().stream() .map(ConstraintViolation::getMessage) .collect(Collectors.toList()); return Result.error(String.join(",", errorMessages)); } } ``` 这样就可以自定义请求参数校验了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值