使用 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
在属性文件中并设置为有效的正则表达式,这就会起作用。
是否可以使用 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
在属性文件中并设置为有效的正则表达式,这就会起作用。