【问题标题】:Javax.Validation - allow null but validate if the value is notJavax.Validation - 允许 null 但如果值不是则验证
【发布时间】:2018-11-08 11:46:37
【问题描述】:

我正在使用 javax Validation.constraints 并且我想验证输入但允许它为空,我的 POJO:

public class somePOJO{
    @NotNull
    @Size(min =2, max=50)
    @Pattern(regexp="^[A-Za-z \\s\\-]*$")
    private String country;

    @Size(min =2,max=50)
    @Pattern(regexp="^[A-Za-z \\s\\-]*$")
    private String state;
    //gettes, setters.....

}

我想验证state,例如使用@Pattern@size,前提是它不是null

有没有办法使用custom annotations来做到这一点?

【问题讨论】:

  • 你确定你已经导入了这个吗?导入 javax.validation.constraints.NotNull;
  • 所有导入来自 - import javax.validation.constraints.*;
  • 你是如何创建这个 pojo 对象的?是 REST 服务吗?
  • 是 Spring-boot 控制器。
  • 请出示您的控制器代码

标签: java validation


【解决方案1】:

正如您所期望的那样,这开箱即用,例如在 Spring Boot 2.1.0(以及 Quarkus FWIW)中。

这是 POJO 的完整版本(请注意,我推广的是不可变类):

package sk.ygor.stackoverflow.q53207105;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

public class SomePOJO {

    @NotNull
    @Size(min =2, max=50)
    @Pattern(regexp="^[A-Za-z \\s\\-]*$")
    private final String country;

    @Size(min =2,max=50)
    @Pattern(regexp="^[A-Za-z \\s\\-]*$")
    private final String state;

    public SomePOJO(String country, String state) {
        this.country = country;
        this.state = state;
    }

    public String getCountry() {
        return country;
    }

    public String getState() {
        return state;
    }

}

如果您关心空字符串,您可以通过在正则表达式中添加尾随管道来接受它们(这将意味着“此表达式或空字符串”),尽管这会违反 Size() 要求:

@Pattern(regexp="^[A-Za-z \\s\\-]*$|")

完整版控制器:

package sk.ygor.stackoverflow.q53207105;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
public class ExampleController {

    @RequestMapping(path = "/q53207105", method = RequestMethod.POST)
    public void test(@Valid @RequestBody SomePOJO somePOJO) {
        System.out.println("somePOJO.getCountry() = " + somePOJO.getCountry());
        System.out.println("somePOJO.getState() = " + somePOJO.getState());
    }

}

调用 http://localhost:8080/q53207105 :

{
    "country": "USA",
    "state": "California" 
}

打印:

somePOJO.getCountry() = USA
somePOJO.getState() = California

调用 http://localhost:8080/q53207105 :

{
    "country": "USA",
}

打印:

somePOJO.getCountry() = USA
somePOJO.getState() = null

如果您告诉我您的 Spring Boot 版本,我可能会提供更多帮助。

【讨论】:

  • 你可以在这里找到代码:github.com/ygor-sk/stackoverflow/tree/master/…
  • 当传递一个空字符串时,这将不起作用。当从客户端传递空字符串或 null 时,您必须在控制器中设置 StringTrimmerEditorInitBinder 才能在这两种情况下工作。
【解决方案2】:

您可以在正则表达式中使用交替构造来分隔多个模式。只需使用管道'|'分隔模式即根据您对现有正则表达式的要求为空/空字符串附加正则表达式。示例如下:

^(?:[A-Za-z \\s\\-]*|)$

可能不准确,但希望你明白。

【讨论】:

  • 有可能,但我需要删除@Size 验证。
  • 您也可以在正则表达式本身中输入 {2,50} 进行大小验证。
  • 我也想知道。如果它适合您,请尝试并接受作为答案。
  • 如果没有黄油答案,这是一种解决方法。
【解决方案3】:

InitBinder 中设置了 StringTrimmerEditor 时,您的 POJP 将按预期工作。

您可以拥有一个应用程序范围的 InitBinder,在您的项目中拥有如下所示的类。

@ControllerAdvice
public class CustomControllerAdvice {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 2019-08-20
    • 1970-01-01
    相关资源
    最近更新 更多