Использование Spring Expression Language для компиляции объекта Pattern - PullRequest
0 голосов
/ 09 января 2019

Можно ли использовать SpEL для компиляции объекта Pattern с использованием выражения регулярного выражения из файла свойств? Я пытаюсь избежать компиляции регулярного выражения каждый раз, когда вызывается метод в этом классе. Я мог бы использовать @Value, чтобы просто установить регулярное выражение в String, затем получить объект Pattern с получателем, а получатель должен выполнить нулевую проверку и только скомпилировать 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;

Ответы [ 4 ]

0 голосов
/ 09 января 2019

Я сделал это, создав собственную аннотацию валидации.

@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 {};
}

И реализация Validator

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 находится в файле свойств и установлен в допустимое регулярное выражение, это будет работать.

0 голосов
/ 09 января 2019

Примерно так:

    @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

0 голосов
/ 09 января 2019

Хотя ответ Артема показывает именно то, о чем вы просили, это тот случай, когда вышеприведенная инъекция поля (, у которой довольно много проблем ) также может обеспечить чистое решение:

private Pattern pattern;

@Value("${some.regex}")
public void setRegex(String regex) {
    this.pattern = Pattern.compile(regex);
}
0 голосов
/ 09 января 2019

Я бы порекомендовал спроектировать от @Value до предоставления шаблона регулярного выражения, а затем где-нибудь в методе инициализации проверить правильность регулярного выражения.

Это дает вам очевидные преимущества:

  • У вас есть ясность в том, что делается и как (SpEL может быть крошечным битным тайным)
  • У вас есть возможность надежно и легко проверить его
  • Вы можете отлаживать его, пока разрабатываете

Мой подход к этому был бы следующим.

@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
}
...