Question

Y a-t-il des bibliothèques qui me permettraient d'utiliser la même notation connue que celle utilisée dans BeanUtils pour extraire les paramètres POJO, mais pour remplacer facilement des espaces réservés dans une chaîne?

Je sais qu'il serait possible de lancer la mienne en utilisant BeanUtils ou d'autres bibliothèques offrant des fonctionnalités similaires, mais je ne voulais pas réinventer la roue.

Je voudrais prendre une chaîne comme suit:

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

Et en passant une instance de la classe User ci-dessous:

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

À quelque chose comme:

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

Chaque espace réservé serait remplacé par les valeurs réelles.

Des idées?

Était-ce utile?

La solution

Rouler soi-même avec BeanUtils ne prendrait pas trop de choses à réinventer (en supposant que vous souhaitiez qu’il soit aussi élémentaire que demandé). Cette implémentation prend une carte pour le contexte de remplacement, où la clé de carte doit correspondre à la première partie des chemins de recherche de variable donnés pour le remplacement.

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

Étant donné les variables fournies dans votre question:

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

Autres conseils

Voir la réponse à cette question similaire sur utiliser Langage d'expression dans un contexte autonome .

Spring Framework devrait avoir une fonctionnalité qui le fasse (voir l'exemple de Spring JDBC ci-dessous). Si vous pouvez utiliser groovy (ajoutez simplement le fichier groovy.jar), vous pouvez utiliser la fonctionnalité GString de Groovy pour le faire très facilement.

Exemple Groovy

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

Spring JDBC est doté d'une fonctionnalité permettant de prendre en charge les variables de liaison nommées et imbriquées des beans, comme ceci:

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

Votre exemple de chaîne est un modèle valide dans au moins quelques moteurs de modélisation, tels que Velocity ou Freemarker. Ces bibliothèques offrent un moyen de fusionner un modèle avec un contexte contenant des objets (comme "utilisateur" dans votre exemple).

Voir http://velocity.apache.org/ ou http://www.freemarker.org/

Quelques exemples de code (du site 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();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top