使用 Spring 表达式语言编译模式对象

Using Spring Expression Language to compile a Pattern object

是否可以使用 SpEL 通过属性文件中的正则表达式编译 Pattern 对象?我试图避免每次调用此 class 中的方法时都编译正则表达式。我可以使用 @Value 将正则表达式设置为一个字符串,然后有一个带有 getter 的 Pattern 对象并让 getter 进行空检查,并且只在这种情况下编译 Patter。但似乎应该有更简洁的方法来完成这个。

我希望替换这个:

    @Value("${some.regex}")
    private String regex;

    private Pattern PATTERN = null;

    public Pattern getPattern() {
        if (PATTERN == null)
            PATTERN = Pattern.compile(regex);
        return PATTERN;
    }
与此类似:
    @Value("#{Pattern.compile('${some.regex}')}")
    private Pattern pattern;

我建议将您的 @Value 设计为 提供 正则表达式模式,然后在某处的初始化方法中验证正则表达式是否正确。

这会给您带来一些明显的好处:

  • 您清楚地知道正在做什么以及如何做(SpEL 可以是 wee 位奥术)
  • 您有能力可靠且轻松地对其进行测试
  • 边开发边调试

我的做法是这样的。

@Component
public class FooClass {
    @Value("${some.regex}")
    private String regex;

    private Pattern pattern;

    @PostConstruct
    public void init() {
        pattern = Pattern.compile(regex);
    }
    // rest of code here
}

像这样:

    @Value("#{T(java.util.regex.Pattern).compile('${some.regex}')}")

重点是使用 T 运算符来访问 static 方法。在参考手册中查看更多信息:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions-types

虽然 Artem 的回答完全符合您的要求,但在这种情况下,上述字段注入 (which has quite a few problems) 也可以提供一个干净的解决方案:

private Pattern pattern;

@Value("${some.regex}")
public void setRegex(String regex) {
    this.pattern = Pattern.compile(regex);
}

我这样做的方法是创建我自己的验证注释。

@Documented
@Retention(RUNTIME)
@Target({METHOD,FIELD})
@Constraint(validatedBy=PropertyPatternValidator.class)
public @interface PropertyPattern {
    String property();
    String message() default "{validator.propertypattern}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

以及验证器实现

public class PropertyPatternValidator implements ConstraintValidator<PropertyPattern, CharSequence> {

private Map<String, Pattern> patterns = new HashMap<>();
private Pattern pattern;

@Override
public void initialize(PropertyPattern propPattern) {
    String property = propPattern.property();
    pattern = patterns.computeIfAbsent(property, prop -> {
        Properties applicationProps = (Properties) ApplicationContextProvider.getApplicationContext()
                .getBean("applicationProps");
        String p = applicationProps.getProperty(prop);
        return Pattern.compile(p);
    });
}

@Override
public boolean isValid(CharSequence inputToValidate, ConstraintValidatorContext ctx) {
    CharSequence input = inputToValidate != null ? inputToValidate : "";
    Matcher m = pattern.matcher(input);
    return m.matches();
}
}

用法:

@PropertyPattern(property ="pattern.account")
private String accountNumber;

然后只要 pattern.account 在属性文件中并设置为有效的正则表达式,这就会起作用。