java中的字符串替换,类似于velocity模板

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3655424/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 03:13:46  来源:igfitidea点击:

String replacement in java, similar to a velocity template

javastringreflectionvelocity

提问by Joe

Is there any Stringreplacement mechanism in Java, where I can pass objects with a text, and it replaces the string as it occurs.
For example, the text is :

StringJava 中是否有任何替换机制,我可以在其中传递带有文本的对象,并在字符串出现时替换它。
例如,文本是:

Hello ${user.name},
    Welcome to ${site.name}. 

The objects I have are "user"and "site". I want to replace the strings given inside ${}with its equivalent values from the objects. This is same as we replace objects in a velocity template.

我拥有的对象是"user""site"。我想${}用对象中的等效值替换内部给出的字符串。这与我们替换速度模板中的对象相同。

采纳答案by JH.

Use StringSubstitutorfrom Apache Commons Text.

使用StringSubstitutorApache的共享文本。

https://commons.apache.org/proper/commons-text/

https://commons.apache.org/proper/commons-text/

It will do it for you (and its open source...)

它会为你做这件事(和它的开源......)

 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);

回答by casablanca

Here's an outline of how you could go about doing this. It should be relatively straightforward to implement it as actual code.

以下是如何进行此操作的概述。将其实现为实际代码应该相对简单。

  1. Create a map of all the objects that will be referenced in the template.
  2. Use a regular expression to find variable references in the template and replace them with their values (see step 3). The Matcherclass will come in handy for find-and-replace.
  3. Split the variable name at the dot. user.namewould become userand name. Look up userin your map to get the object and use reflectionto obtain the value of namefrom the object. Assuming your objects have standard getters, you will look for a method getNameand invoke it.
  1. 创建将在模板中引用的所有对象的映射。
  2. 使用正则表达式在模板中查找变量引用并将它们替换为它们的值(参见步骤 3)。该匹配器类会派上用场的查找和替换。
  3. 在点处拆分变量名称。user.name将成为usernameuser在地图中查找以获取对象并使用反射name从对象中获取 的值。假设您的对象具有标准的 getter,您将寻找一个方法getName并调用它。

回答by RealHowTo

Take a look at the java.text.MessageFormatclass, MessageFormat takes a set of objects, formats them, then inserts the formatted strings into the pattern at the appropriate places.

看一看这个java.text.MessageFormat类,MessageFormat 接受一组对象,将它们格式化,然后将格式化的字符串插入到模式中的适当位置。

Object[] params = new Object[]{"hello", "!"};
String msg = MessageFormat.format("{0} world {1}", params);

回答by jjnguy

I threw together a small test implementation of this. The basic idea is to call formatand pass in the format string, and a map of objects, and the names that they have locally.

我把这个的一个小测试实现放在一起。基本思想是调用format并传入格式字符串、对象映射以及它们在本地的名称。

The output of the following is:

以下输出是:

My dog is named fido, and Jane Doe owns him.

我的狗叫 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));
    }
}

Note: This doesn't compile due to unhandled exceptions. But it makes the code much easier to read.

注意:由于未处理的异常,这不会编译。但它使代码更容易阅读。

Also, I don't like that you have to construct the map yourself in the code, but I don't know how to get the names of the local variables programatically. The best way to do it, is to remember to put the object in the map as soon as you create it.

另外,我不喜欢您必须自己在代码中构建映射,但我不知道如何以编程方式获取局部变量的名称。最好的方法是记住在创建对象后立即将其放入地图中。

The following example produces the results that you want from your example:

以下示例从示例中生成您想要的结果:

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));
}

I should also mention that I have no idea what Velocity is, so I hope this answer is relevant.

我还应该提到我不知道 Velocity 是什么,所以我希望这个答案是相关的。

回答by Mike Milkin

There is nothing out of the box that is comparable to velocity since velocity was written to solve exactly that problem. The closest thing you can try is looking into the Formatter

没有任何开箱即用的东西可以与速度相媲美,因为速度是为了解决这个问题而编写的。您可以尝试的最接近的事情是查看格式化程序

http://cupi2.uniandes.edu.co/site/images/recursos/javadoc/j2se/1.5.0/docs/api/java/util/Formatter.html

http://cupi2.uniandes.edu.co/site/images/recursos/javadoc/j2se/1.5.0/docs/api/java/util/Formatter.html

However the formatter as far as I know was created to provide C like formatting options in Java so it may not scratch exactly your itch but you are welcome to try :).

然而,据我所知,格式化程序是为了在 Java 中提供类似 C 的格式化选项而创建的,因此它可能不会完全满足您的需求,但欢迎您尝试:)。

回答by Christoffer Soop

There are a couple of Expression Language implementations out there that does this for you, could be preferable to using your own implementation as or if your requirments grow, see for example JUELand MVEL

有几种表达式语言实现可以为您执行此操作,可能比使用您自己的实现更可取,或者如果您的需求增长,请参见例如JUELMVEL

I like and have successfully used MVEL in at least one project.

我喜欢并至少在一个项目中成功使用了 MVEL。

Also see the Stackflow post JSTL/JSP EL (Expression Language) in a non JSP (standalone) context

另请参阅非 JSP(独立)上下文中的 Stackflow 帖子JSTL/JSP EL(表达式语言)

回答by artgrohe

My preferred way is String.format()because its a oneliner and doesn't require third party libraries:

我的首选方式是String.format()因为它是一个单行程序并且不需要第三方库:

String message = String.format("Hello! My name is %s, I'm %s.", name, age); 

I use this regularly, e.g. in exception messages like:

我经常使用它,例如在异常消息中,例如:

throw new Exception(String.format("Unable to login with email: %s", email));

Hint: You can put in as many variables as you like because format()uses Varargs

提示:您可以放入任意数量的变量,因为format()使用Varargs

回答by Kan

I use GroovyShell in java to parse template with Groovy GString:

我在 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);