处理文本中的动态占位符

时间:2019-03-20 11:27:37

标签: java

我想要一个与this问题非常相似的东西,但是我的情况有点复杂。

我有什么可爱的方法可以替换文本中的动态占位符?
例如,解析屏蔽的密码,然后将其替换为属性文件中的已解码密码:

encoded.url=jdbc:oracle:thin:SCHEMA/${password:abtBKwUnmBfTDCz04k83ew==}@host:port:sid

2 个答案:

答案 0 :(得分:0)

用法

@Test
public void testResolve() {
    Map<Object, Object> properties = new HashMap<>();
    Function<String, Object> passwordDecoder = (String param) -> {
        return param.replace("en", "de");
    };
    properties.put("property1", "value1");
    properties.put("property2", "value2-!{property1}]");
    properties.put("property3", "3");
    properties.put("property23", "23");
    properties.put("null", null);
    properties.put("special.symbols", "1.1.1");
    properties.put("password", passwordDecoder);

    assertEquals("[value1]", resolve("[!{property1}]", properties));
    assertEquals("[!{property1}]", resolve("[!!{property1}]", properties));
    assertEquals("[23]", resolve("[!{property2!{property3}}]", properties));
    assertEquals("[!{unknown}]", resolve("[!{unknown}]", properties));
    assertEquals("[null]", resolve("[!{null}]", properties));
    assertEquals("[1.1.1]", resolve("[!{special.symbols}]", properties));
    assertEquals("[decoded]", resolve("[!{password:encoded}]", properties));
}

实施

public final class PlaceholderResolver {

    private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("(?<!\\!)\\!\\{(?<name>[^:{}]+):?(?<param>[^{}]+)?\\}");

    private PlaceholderResolver() {}

    @SuppressWarnings("unchecked")
    public static String resolve(String str, Map<Object, Object> properties) {
        if (str == null)
            return null;
        String resolved = str;
        while (true) {
            StringBuffer buffer = new StringBuffer();
            Matcher matcher = PLACEHOLDER_PATTERN.matcher(resolved);
            while (matcher.find()) {
                String name = matcher.group("name");
                if (properties.containsKey(name)) {
                    String param = matcher.group("param");
                    Object value = properties.get(name);
                    if (value instanceof Function)
                        value = ((Function<String, Object>) value).apply(param);
                    matcher.appendReplacement(buffer, quoteReplacement(Objects.toString(value)));
                } else {
                    matcher.appendReplacement(buffer, quoteReplacement(matcher.group()));
                }
            }
            matcher.appendTail(buffer);

            if (buffer.toString().equals(resolved))
                break;
            resolved = buffer.toString();
        }
        return resolved.replace("!!{", "!{");
    }
}

Spring集成

@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        return new MyPropertySourcesPlaceholderConfigurer();
    }
}

MyPropertySourcesPlaceholderConfigurer

import static com.google.common.base.Preconditions.checkNotNull;
import static com.ubs.wma.bmss.common.util.PasswordUtils.decrypt;
import static com.ubs.wma.bmss.common.util.PlaceholderResolver.resolve;
import static java.lang.System.getenv;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

public class MyPropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer {
    public class PasswordDecryptionFunction implements Function<String, String> {
        @Override
        public String apply(String encrypted) {
            return decrypt(encrypted, checkNotNull(getenv("MASTER_PASSWORD"),
                    "Cannot decrypt password in property file because MASTER_PASSWORD environment variable was not set"));
        }
    }

    private Map<Object, Object> properties = new HashMap<>();

    public MyPropertySourcesPlaceholderConfigurer() {
        properties.put("password", new PasswordDecryptionFunction());
    }

    @Override
    protected String convertPropertyValue(String originalValue) {
        return resolve(originalValue, properties);
    }
}

答案 1 :(得分:0)

这是当务之急。 首先,找到仅包含密码的子字符串。然后,复制出现在密码之前的字符串和出现在密码之后的字符串。最后,我们可以简单地将两个复制的字符串放在一起,新密码就在这两个字符串之间。

  private static String changePassword(String str, String newPassword)
  {
    String oldPassword = str.split("password:")[1];
    oldPassword = oldPassword.substring(0, oldPassword.indexOf('}'));
    final String part1 = str.split(oldPassword)[0], part2 = str.split(oldPassword)[1];

    return part1 + newPassword + part2;
  }

我相信这是一个简单的解决方案,但是请记住,该解决方案仅适用于与示例字符串格式相同的字符串。