我想要一个与this问题非常相似的东西,但是我的情况有点复杂。
我有什么可爱的方法可以替换文本中的动态占位符?
例如,解析屏蔽的密码,然后将其替换为属性文件中的已解码密码:
encoded.url=jdbc:oracle:thin:SCHEMA/${password:abtBKwUnmBfTDCz04k83ew==}@host:port:sid
答案 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;
}
我相信这是一个简单的解决方案,但是请记住,该解决方案仅适用于与示例字符串格式相同的字符串。