spring-boot - Spring Boot : Custom Validation in Request Params

标签 spring-boot validation controller spring-annotations http-request-parameters

我想验证我的 Controller 中的请求参数之一。请求参数应该来自给定值列表之一,如果不是,则应该抛出错误。在下面的代码中,我希望请求参数 orderBy 来自@ValuesAllowed 中存在的值列表。

@RestController
@RequestMapping("/api/opportunity")
@Api(value = "Opportunity APIs")
@ValuesAllowed(propName = "orderBy", values = { "OpportunityCount", "OpportunityPublishedCount", "ApplicationCount",
        "ApplicationsApprovedCount" })
public class OpportunityController {

@GetMapping("/vendors/list")
    @ApiOperation(value = "Get all vendors")

    public ResultWrapperDTO getVendorpage(@RequestParam(required = false) String term,
            @RequestParam(required = false) Integer page, @RequestParam(required = false) Integer size,
            @RequestParam(required = false) String orderBy, @RequestParam(required = false) String sortDir) {

我编写了一个自定义 bean 验证器,但不知何故这不起作用。即使我为查询 param 传递了任何随机值,它也不会验证并抛出错误。

@Repeatable(ValuesAllowedMultiple.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {ValuesAllowedValidator.class})
public @interface ValuesAllowed {

    String message() default "Field value should be from list of ";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

    String propName();
    String[] values();
}

public class ValuesAllowedValidator implements ConstraintValidator<ValuesAllowed, Object> {

    private String propName;
    private String message;
    private String[] values;

    @Override
    public void initialize(ValuesAllowed requiredIfChecked) {
        propName = requiredIfChecked.propName();
        message = requiredIfChecked.message();
        values = requiredIfChecked.values();
    }

    @Override
    public boolean isValid(Object object, ConstraintValidatorContext context) {
        Boolean valid = true;
        try {
            Object checkedValue = BeanUtils.getProperty(object, propName);

            if (checkedValue != null) {
                valid = Arrays.asList(values).contains(checkedValue.toString().toLowerCase());
            } 

            if (!valid) {
                context.disableDefaultConstraintViolation();
                context.buildConstraintViolationWithTemplate(message.concat(Arrays.toString(values)))
                        .addPropertyNode(propName).addConstraintViolation();
            }
        } catch (IllegalAccessException e) {
            log.error("Accessor method is not available for class : {}, exception : {}", object.getClass().getName(), e);
            return false;
        } catch (NoSuchMethodException e) {
            log.error("Field or method is not present on class : {}, exception : {}", object.getClass().getName(), e);
            return false;
        } catch (InvocationTargetException e) {
            log.error("An exception occurred while accessing class : {}, exception : {}", object.getClass().getName(), e);
            return false;
        }
        return valid;
    }
}

最佳答案

情况1:如果根本没有触发注释ValuesAllowed,可能是因为没有用@Validated 注释 Controller 。

@Validated
@ValuesAllowed(propName = "orderBy", values = { "OpportunityCount", "OpportunityPublishedCount", "ApplicationCount", "ApplicationsApprovedCount" })
public class OpportunityController {
@GetMapping("/vendors/list")
public String getVendorpage(@RequestParam(required = false) String term,..{
}
情况2:如果触发并抛出错误,可能是因为BeanUtils.getProperty不解析属性并抛出异常。
如果上述解决方案不起作用,您可以尝试将注解移至方法级别并更新验证器以使用 OrderBy 的有效值列表。范围。这对我有用。下面是示例代码。
@RestController
@RequestMapping("/api/opportunity")
@Validated
public class OpportunityController {
    @GetMapping("/vendors/list")
    public String getVendorpage(@RequestParam(required = false) String term,
            @RequestParam(required = false) Integer page, @RequestParam(required = false) Integer size,
            @ValuesAllowed(propName = "orderBy", values = { "OpportunityCount", "OpportunityPublishedCount", "ApplicationCount",
                    "ApplicationsApprovedCount" }) @RequestParam(required = false) String orderBy, @RequestParam(required = false) String sortDir) {
        return "success";
    }
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { ValuesAllowed.Validator.class })
public @interface ValuesAllowed {

    String message() default "Field value should be from list of ";

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

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

    String propName();

    String[] values();

    class Validator implements ConstraintValidator<ValuesAllowed, String> {
        private String propName;
        private String message;
        private List<String> allowable;

        @Override
        public void initialize(ValuesAllowed requiredIfChecked) {
            this.propName = requiredIfChecked.propName();
            this.message = requiredIfChecked.message();
            this.allowable = Arrays.asList(requiredIfChecked.values());
        }

        public boolean isValid(String value, ConstraintValidatorContext context) {
            Boolean valid = value == null || this.allowable.contains(value);

            if (!valid) {
                context.disableDefaultConstraintViolation();
                context.buildConstraintViolationWithTemplate(message.concat(this.allowable.toString()))
                        .addPropertyNode(this.propName).addConstraintViolation();
            }
            return valid;
        }
    }
}

关于spring-boot - Spring Boot : Custom Validation in Request Params,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59422883/

相关文章:

spring-boot - Spring WebFlux - 如何从请求中获取数据?

flutter - 在 Flutter 中使用 TextFormField 添加项目列表

java - Spring Boot Controller 未被映射

java - 如何使用重定向传递复杂的 ModelAttribute : in Spring MVC 3. 0

java - 如何授予CHMOD 0755对Jar中所有文件的权限

spring-boot - NoClassDefFoundError : ConfigurationPropertySources

java - Spring .Boot Mustache 如何在模型中导航 Java Map

c# - Enterprise Library 6 验证不是从配置中读取?

php - codeigniter 表单验证错误消息不显示

validation - CakePHP 2.1 - 自定义验证规则 - 检查唯一字段值组合