java中的stringreplace,类似于速度模板
在Java中是否存在任何String
replace机制,我可以在其中使用文本传递对象,并在string出现时replacestring。
例如,文本是:
Hello ${user.name}, Welcome to ${site.name}.
我有的对象是"user"
和"site"
。 我想用${}
给出的stringreplace对象中的等价值。 这与我们replace速度模板中的对象相同。
使用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);
看一下java.text.MessageFormat
类,MessageFormat接受一组对象,对它们进行格式化,然后将格式化的string插入到适当位置的模式中。
Object[] params = new Object[]{"hello", "!"}; String msg = MessageFormat.format("{0} world {1}", params);
我把这个小testing实现放在一起。 其基本思想是调用format
并传入格式string,对象映射以及本地名称。
以下的输出是:
我的狗叫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)); } }
注意:由于未处理的exception,这不会编译。 但它使代码更容易阅读。
另外,我不喜欢你必须在代码中自己构造映射,但我不知道如何以编程方式获得本地variables的名称。 要做到这一点,最好的办法是记得一旦创build它就把对象放在地图上。
以下示例根据示例生成所需的结果:
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是什么,所以我希望这个答案是相关的。
以下是你如何能够做到这一点的大纲。 将它作为实际代码来实现应该相对简单。
- 创build将在模板中引用的所有对象的映射。
- 使用正则expression式在模板中查找variables引用,并将其replace为它们的值(请参阅步骤3)。 Matcher类将派上用场,find和replace。
- 在点处拆分variables名称。
user.name
将成为user
和name
。 在地图上查找user
以获取对象并使用reflection从对象中获取name
的值。 假设你的对象有标准的getter,你会查找getName
方法并调用它。
有一些expression式语言实现在那里为您做这个,可能比使用自己的实现更好,或者如果您的需求增长,请参阅例如JUEL和MVEL
我喜欢并至less在一个项目中成功使用了MVEL。
另请参见非JSP(独立)上下文中的Stackflow post JSTL / JSP EL(expression式语言)
没有任何东西可以与速度相比较,因为速度是为了解决这个问题而写的。 你可以尝试的最接近的东西是查看格式化程序
然而,据我所知,格式化程序是为了在Java中提供类似于格式化选项的C语言,所以它可能不会正确地抓取您的痒,但欢迎您尝试:)。