2

POJO パラメータを抽出するために BeanUtils で使用しているのと同じ既知の表記法を使用できるが、文字列内のプレースホルダーを簡単に置き換えることができるライブラリはありますか?

BeanUtils 自体または同様の機能を備えた他のライブラリを使用して、独自のロールを作成できることはわかっていますが、車輪の再発明はしたくありませんでした。

次のように String を取得したいと思います。

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 クラスの 1 つのインスタンスを渡します。

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

3 に答える 3

2

BeanUtils を使用して独自のロールを作成する場合、車輪の再発明はあまり必要ありません (必要な基本的なものにしたい場合)。この実装は、置換コンテキストのマップを受け取ります。マップ キーは、置換のために指定された変数ルックアップ パスの最初の部分に対応する必要があります。

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));
于 2008-09-28T03:55:47.493 に答える
1

文字列の例は、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();
于 2008-09-28T08:23:27.803 に答える
1

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);
}
于 2008-09-28T03:40:34.083 に答える