String
Java中是否有任何替换机制,我可以在其中传递带有文本的对象,并在出现字符串时替换它。
例如,文本为:
Hello ${user.name},
Welcome to ${site.name}.
我拥有的对象是"user"
和"site"
。我想${}
用对象的等效值替换内部给定的字符串。这与我们替换速度模板中的对象相同。
Hello ${user.name}
,not like Hello %s
或Hello {0}
。
String
Java中是否有任何替换机制,我可以在其中传递带有文本的对象,并在出现字符串时替换它。
例如,文本为:
Hello ${user.name},
Welcome to ${site.name}.
我拥有的对象是"user"
和"site"
。我想${}
用对象的等效值替换内部给定的字符串。这与我们替换速度模板中的对象相同。
Hello ${user.name}
,not like Hello %s
或Hello {0}
。
Answers:
使用StringSubstitutor
Apache的共享文本。
https://commons.apache.org/proper/commons-text/
它将为您(及其开源...)
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}.";
StringSubstitutor sub = new StringSubstitutor(valuesMap);
String resolvedString = sub.replace(templateString);
Map<String, String> valuesMap = new HashMap<String, String>();
。
StrSubstitutor
现在已在https://commons.apache.org/proper/commons-lang/中弃用。使用者使用https://commons.apache.org/proper/commons-text/代替
StrSubstitutor
从1.3版开始弃用,请StringSubstitutor
改用。此类将在2.0中删除。导入的Gradle依赖项StringSubstitutor
是org.apache.commons:commons-text:1.4
看一看java.text.MessageFormat
该类,MessageFormat接收一组对象,对它们进行格式化,然后将格式化后的字符串插入模式中的适当位置。
Object[] params = new Object[]{"hello", "!"};
String msg = MessageFormat.format("{0} world {1}", params);
format
还需要使用Object...
可变参数,因此您可以在需要的地方使用这种更简洁的语法format("{0} world {1}", "Hello", "!");
MessageFormat
只能可靠地用于其名称,显示消息,而不能用于技术格式化很重要的输出。例如,数字将根据区域设置进行格式化,从而使它们对于技术用途无效。
我的首选方式是String.format()
因为它是一个单行,并且不需要第三方库:
String message = String.format("Hello! My name is %s, I'm %s.", name, age);
我经常使用它,例如在异常消息中:
throw new Exception(String.format("Unable to login with email: %s", email));
提示:您可以输入任意多个变量,因为format()
使用了Varargs
String.format("Hello! My name is %s, I'm %s. Why is my name %s you ask? Well I'm only %s years old so I don't know", name, age, name, age);
。此处的其他答案仅需要指定每个参数一次。
String.format("Hello! My name is %1$s, I'm %2$s. Why is my name %1$s you ask? Well I'm only %2$s years old so I don't know", name, age)
我整理了一个小的测试实现。基本思想是调用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,所以我希望这个答案是有意义的。
有两种表达式语言实现可为您完成此操作,如果您的需求不断增长,则最好使用自己的实现,例如,请参见JUEL和MVEL
我喜欢并且已经在至少一个项目中成功使用了MVEL。
另请参阅非JSP(独立)上下文中的Stackflow发布JSTL / JSP EL(表达语言)
因为速度是为了解决这个问题而写的,所以没有什么比速度快的东西了。您可以尝试的最接近的方法是查看格式化程序
但是,据我所知,格式化程序是为在Java中提供C格式设置选项而创建的,因此它可能无法完全解决您的问题,但是欢迎您尝试:)。
我在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);
String.format("Hello %s", username);