Самый простой способ использовать замену «BeanUtils alike»

StackOverflow https://stackoverflow.com/questions/145052

Вопрос

Существуют ли какие-либо библиотеки, которые позволили бы мне использовать ту же известную нотацию, которую мы используем в BeanUtils, для извлечения параметров POJO, но для легкой замены заполнителей в строке?

Я знаю, что можно было бы создать свою собственную версию, используя сам BeanUtils или другие библиотеки с похожими функциями, но я не хотел изобретать велосипед.

Я хотел бы взять строку следующим образом:

String s = "User ${user.name} just placed an order. Deliver is to be
made to ${user.address.street}, ${user.address.number} - ${user.address.city} / 
${user.address.state}";

И передадим один экземпляр класса User ниже:

public class User {
   private String name;
   private Address address; 
   // (...)

   public String getName() { return name; } 
   public Address getAddress() {  return address; } 
}

public class Address {
   private String street;
   private int number;
   private String city;
   private String state;

   public String getStreet() { return street; }
   public int getNumber() {  return number; }
   // other getters...
}

Что-то вроде:

System.out.println(BeanUtilsReplacer.replaceString(s, user));

Будет заменен каждый заполнитель фактическими значениями.

Есть идеи?

Это было полезно?

Решение

Создание собственного приложения с использованием BeanUtils не потребует слишком большого переосмысления колеса (при условии, что вы хотите, чтобы оно было настолько простым, насколько вы просили).Эта реализация использует контекст Map для замены, где ключ карты должен соответствовать первой части путей поиска переменных, заданных для замены.

import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.beanutils.BeanUtils;

public class BeanUtilsReplacer
{
    private static Pattern lookupPattern = Pattern.compile("\\$\\{([^\\}]+)\\}");

    public static String replaceString(String input, Map<String, Object> context)
        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
    {
        int position = 0;
        StringBuffer result = new StringBuffer();

        Matcher m = lookupPattern.matcher(input);
        while (m.find())
        {
            result.append(input.substring(position, m.start()));
            result.append(BeanUtils.getNestedProperty(context, m.group(1)));
            position = m.end();
        }

        if (position == 0)
        {
            return input;
        }
        else
        {
            result.append(input.substring(position));
            return result.toString();
        }
    }
}

Учитывая переменные, указанные в вашем вопросе:

Map<String, Object> context = new HashMap<String, Object>();
context.put("user", user);
System.out.println(BeanUtilsReplacer.replaceString(s, context));

Другие советы

Spring Framework должен иметь функцию, которая делает это (см. пример Spring JDBC ниже).Если вы можете использовать groovy (просто добавьте файл groovy.jar), вы можете использовать функцию GString Groovy, чтобы сделать это довольно хорошо.

Отличный пример

foxtype = 'quick'
foxcolor = ['b', 'r', 'o', 'w', 'n']
println "The $foxtype ${foxcolor.join()} fox"

В Spring JDBC есть функция, которую я использую для поддержки именованных и вложенных именованных переменных связывания из bean-компонентов, например:

public int countOfActors(Actor exampleActor) {

    // notice how the named parameters match the properties of the above 'Actor' class
    String sql = "select count(0) from T_ACTOR where first_name = :firstName and last_name = :lastName";

    SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(exampleActor);

    return this.namedParameterJdbcTemplate.queryForInt(sql, namedParameters);
}

Ваш пример строки является допустимым шаблоном по крайней мере в нескольких системах шаблонов, таких как Velocity или Freemarker.Эти библиотеки предлагают способ объединить шаблон с контекстом, содержащим некоторые объекты (например, «пользователь» в вашем примере).

Видеть http://velocity.apache.org/ или http://www.freemarker.org/

Пример кода (с сайта Freemarker):

 /* ------------------------------------------------------------------- */    
        /* You usually do it only once in the whole application life-cycle:    */    

        /* Create and adjust the configuration */
        Configuration cfg = new Configuration();
        cfg.setDirectoryForTemplateLoading(
                new File("/where/you/store/templates"));
        cfg.setObjectWrapper(new DefaultObjectWrapper());

        /* ------------------------------------------------------------------- */    
        /* You usually do these for many times in the application life-cycle:  */    

        /* Get or create a template */
        Template temp = cfg.getTemplate("test.ftl");

        /* Create a data-model */
        Map root = new HashMap();
        root.put("user", "Big Joe");
        Map latest = new HashMap();
        root.put("latestProduct", latest);
        latest.put("url", "products/greenmouse.html");
        latest.put("name", "green mouse");

        /* Merge data-model with template */
        Writer out = new OutputStreamWriter(System.out);
        temp.process(root, out);
        out.flush();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top