Frage

Gibt es keine Bibliotheken, die mir die gleiche bekannte Notation verwenden erlauben würden, wie wir in BeanUtils zum Extrahieren von POJO Parametern verwenden, aber für die einfachen Platzhalter in einem String zu ersetzen?

Ich weiß, dass es möglich wäre, meine eigene Rolle, BeanUtils selbst oder andere Bibliotheken mit ähnlichen Funktionen, aber ich wollte nicht, das Rad neu zu erfinden.

Ich möchte einen String nehmen, wie folgt:

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

Und vorbei eine Instanz der Klasse User unter:

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...
}

Um so etwas wie:

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

Würde jeder Platzhalter durch aktuelle Werte ersetzt bekommen.

Irgendwelche Ideen?

War es hilfreich?

Lösung

Ihre eigene mit BeanUtils Roll würde nicht zu viel Rad neu erfunden nehmen (vorausgesetzt, Sie es als Grund sein wollen als gefragt). Diese Implementierung nimmt eine Karte für den Ersatz Kontext, in dem die Karte Schlüssel zu dem ersten Teil der variablen Lookup-Wege gegeben für den Ersatz entsprechen.

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

die Variablen in Ihrer Frage zur Verfügung gestellt Gegeben:

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

Andere Tipps

Sehen Sie die Antwort auf diese ähnliche Frage zu mit Expression Language in einem eigenständigen Kontext .

Spring Framework sollte eine Funktion hat, das dies tut (siehe Frühling JDBC Beispiel unten). Wenn Sie groovy verwenden können (fügen Sie einfach die groovy.jar-Datei) Sie GString Funktion abgefahrene verwenden kann dies sehr gut zu tun.

Groovy Beispiel

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

Frühling JDBC verfügt über eine Funktion, die ich unterstützen Namen verwenden, um und verschachtelt namens Bind-Variablen aus Bohnen wie folgt aus:

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

Ihr String Beispiel ist eine gültige Vorlage in mindestens ein paar Templating Engines, wie Geschwindigkeit oder Freemarker. Diese Bibliotheken bieten eine Möglichkeit, eine Vorlage mit einem Kontext zu verschmelzen einige Objekte, die (wie ‚Benutzer‘ in Ihrem Beispiel).

Siehe http://velocity.apache.org/ oder http://www.freemarker.org/

Einige Beispiel-Code (aus dem Freemarker-Website):

 /* ------------------------------------------------------------------- */    
        /* 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();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top