Замена строки в java, аналогично шаблону скорости


есть String механизм замены в Java, где я могу передать объекты с текстом, и он заменяет строку, как это происходит.
Например, текст :

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

объекты у меня есть "user" и "site". Я хочу заменить строки, приведенные внутри ${} С эквивалентными значениями из объектов. Это то же самое, что мы заменяем объекты в шаблоне скорости.

6 59

6 ответов:

используйте 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 принимает набор объектов, форматирует их, а затем вставляет отформатированные строки в шаблон в соответствующих местах.

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

я собрал небольшую тестовую реализацию этого. Основная идея состоит в том, чтобы позвонить format и передать в строке формата и карту объектов, и имена, которые они имеют локально.

вывод следующего:

мою собаку зовут Фидо, и она принадлежит Джейн Доу.

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

я должен также упомянуть, что я понятия не имею, что такое скорость, поэтому я надеюсь, что этот ответ уместен.

вот набросок того, как вы могли бы это сделать. Это должно быть относительно просто реализовать его как фактический код.

  1. создайте карту всех объектов, на которые будут ссылаться в шаблоне.
  2. используйте регулярное выражение, чтобы найти ссылки на переменные в шаблоне и заменить их своими значениями (см. Шаг 3). Элемент Matcher класс пригодится для поиска и замены.
  3. разделить имя переменной в точка. user.name станет user и name. Посмотри вверх user в вашей карте, чтобы получить объект и использовать отражение чтобы получить значение name из объекта. Предполагая, что ваши объекты имеют стандартные геттеры, вы будете искать способ getName и вызывать его.

есть несколько реализаций языка выражений, которые делают это для вас, может быть предпочтительнее использовать вашу собственную реализацию, как или если ваши требования растут, см. например JUEL и MVEL

Я люблю и успешно использовал MVEL по крайней мере в одном проекте.

Также см. сообщение Stackflow JSTL / JSP EL (язык выражений) в не JSP (автономном) контексте

нет ничего из коробки, что сопоставимо с скоростью так как скорость была написана, чтобы решить именно эту проблему. Самое близкое, что вы можете попробовать, это заглянуть в форматер

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

однако форматер, насколько я знаю, был создан для обеспечения C, как параметры форматирования в Java, так что он не может поцарапать точно ваш зуд, но вы добро пожаловать, чтобы попробовать :).