Самый простой способ использовать "BeanUtils alike" заменить - PullRequest
2 голосов
/ 28 сентября 2008

Существуют ли библиотеки, которые позволили бы мне использовать те же известные обозначения, что и в 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));

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

Есть идеи?

Ответы [ 4 ]

2 голосов
/ 28 сентября 2008

Использование собственного 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));
1 голос
/ 28 сентября 2008

Ваш пример строки является допустимым шаблоном хотя бы в нескольких шаблонизаторах, таких как 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();
1 голос
/ 28 сентября 2008

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

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

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);
}
1 голос
/ 28 сентября 2008
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...