Java中是否有任何String
替换机制,我可以使用文本传递对象,并在发生时替换字符串。
例如,文本是:
Hello ${user.name},
Welcome to ${site.name}.
我拥有的对象是"user"
和"site"
。我想将${}
中给出的字符串替换为对象中的等效值。这与我们在速度模板中替换对象相同。
答案 0 :(得分:112)
使用apache commons lang。
https://commons.apache.org/proper/commons-lang/
它会为你(及其开源......)
Map<String, String> valuesMap = new HashMap<String, String>();
valuesMap.put("animal", "quick brown fox");
valuesMap.put("target", "lazy dog");
String templateString = "The ${animal} jumped over the ${target}.";
StrSubstitutor sub = new StrSubstitutor(valuesMap);
String resolvedString = sub.replace(templateString);
答案 1 :(得分:110)
看一下java.text.MessageFormat
类,MessageFormat获取一组对象,格式化它们,然后将格式化的字符串插入到适当位置的模式中。
Object[] params = new Object[]{"hello", "!"};
String msg = MessageFormat.format("{0} world {1}", params);
答案 2 :(得分:17)
我把这个小测试实现了。基本思想是调用format
并传入格式字符串,对象映射及其本地名称。
以下输出为:
我的狗被命名为fido,Jane Doe拥有他。
public class StringFormatter {
private static final String fieldStart = "\\$\\{";
private static final String fieldEnd = "\\}";
private static final String regex = fieldStart + "([^}]+)" + fieldEnd;
private static final Pattern pattern = Pattern.compile(regex);
public static String format(String format, Map<String, Object> objects) {
Matcher m = pattern.matcher(format);
String result = format;
while (m.find()) {
String[] found = m.group(1).split("\\.");
Object o = objects.get(found[0]);
Field f = o.getClass().getField(found[1]);
String newVal = f.get(o).toString();
result = result.replaceFirst(regex, newVal);
}
return result;
}
static class Dog {
public String name;
public String owner;
public String gender;
}
public static void main(String[] args) {
Dog d = new Dog();
d.name = "fido";
d.owner = "Jane Doe";
d.gender = "him";
Map<String, Object> map = new HashMap<String, Object>();
map.put("d", d);
System.out.println(
StringFormatter.format(
"My dog is named ${d.name}, and ${d.owner} owns ${d.gender}.",
map));
}
}
注意:由于未处理的异常,这不会编译。但它使代码更容易阅读。
另外,我不喜欢你必须自己在代码中构建地图,但我不知道如何以编程方式获取局部变量的名称。最好的方法是记住在创建对象后立即将对象放入地图中。
以下示例从您的示例中生成您想要的结果:
public static void main(String[] args) {
Map<String, Object> map = new HashMap<String, Object>();
Site site = new Site();
map.put("site", site);
site.name = "StackOverflow.com";
User user = new User();
map.put("user", user);
user.name = "jjnguy";
System.out.println(
format("Hello ${user.name},\n\tWelcome to ${site.name}. ", map));
}
我还应该提一下,我不知道Velocity是什么,所以我希望这个答案是相关的。
答案 3 :(得分:5)
以下是您如何做到这一点的概述。将它实现为实际代码应该相对简单。
user.name
将成为user
和name
。在地图中查找user
以获取对象,并使用reflection从对象中获取name
的值。假设您的对象具有标准getter,您将查找方法getName
并调用它。答案 4 :(得分:5)
我的首选方式是 String.format()
,因为它是一个单行:
String result = String.format("Hello! My name is %s, I'm %s.", NameVariable, AgeVariable);
我经常在异常消息中使用它,例如:
throw new Exception(String.format("Unable to login with email: %s", email));
提示:由于format()
使用Varargs
答案 5 :(得分:4)
有几种表达式语言实现可以为您完成此操作,可能更适合使用您自己的实现,或者如果您的需求增长,请参阅JUEL和MVEL
我喜欢并且已经在至少一个项目中成功使用过MVEL。
另请参阅Stackflow帖子JSTL/JSP EL (Expression Language) in a non JSP (standalone) context
答案 6 :(得分:0)
没有任何开箱即可与速度相媲美,因为写入速度来解决这个问题。您可以尝试的最接近的事情是查看Formatter
然而,就我所知,格式化程序是为了在Java中提供类似C的格式化选项而创建的,所以它可能不会划伤你的痒但是欢迎你尝试:)。
答案 7 :(得分:0)
我在Java中使用GroovyShell使用Groovy GString解析模板:
Binding binding = new Binding();
GroovyShell gs = new GroovyShell(binding);
// this JSONObject can also be replaced by any Java Object
JSONObject obj = new JSONObject();
obj.put("key", "value");
binding.setProperty("obj", obj)
String str = "${obj.key}";
String exp = String.format("\"%s\".toString()", str);
String res = (String) gs.evaluate(exp);
// value
System.out.println(str);
答案 8 :(得分:0)
我创建了这个使用 vanilla Java 的实用程序。它将 String.format.... 中的两种格式... {}
和 %s
样式合并到一个方法调用中。请注意,它仅替换空的 {}
括号,而不是 {someWord}
。
public class LogUtils {
public static String populate(String log, Object... objects) {
log = log.replaceAll("\\{\\}", "%s");
return String.format(log, objects);
}
public static void main(String[] args) {
System.out.println(populate("x = %s, y ={}", 5, 4));;
}
}