Remplacement de chaîne de caractères en java, similaire à un modèle velocity

Existe-t-il un mécanisme de remplacement String en Java, où je peux passer des objets avec un texte, et il remplace la chaîne de caractères telle qu'elle apparaît.

Par exemple, le texte est :

Hello ${user.name},
    Welcome to ${site.name}. 

les objets que j'AI sont "user" et "site" . Je veux remplacer les chaînes données dans ${} par les valeurs équivalentes des objets. C'est la même chose que nous remplaçons les objets dans un modèle de vitesse.

59
demandé sur Joe 2010-09-07 06:48:46

6 réponses

l'Utilisation d'apache commons lang.

https://commons.apache.org/proper/commons-lang /

il le fera pour vous (et son open source...)

 Map<String, String> valuesMap = new HashMap<String, String>();
 valuesMap.put("animal", "quick brown fox");
 valuesMap.put("target", "lazy dog");
 String templateString = "The ${animal} jumped over the ${target}.";
 StrSubstitutor sub = new StrSubstitutor(valuesMap);
 String resolvedString = sub.replace(templateString);
102
répondu JH. 2015-09-26 02:16:20

regardez la classe java.text.MessageFormat , MessageFormat prend un ensemble d'objets, les formate, puis insère les chaînes formatées dans le modèle aux endroits appropriés.

Object[] params = new Object[]{"hello", "!"};
String msg = MessageFormat.format("{0} world {1}", params);
94
répondu RealHowTo 2011-02-26 15:37:46

j'ai réuni une petite implémentation d'essai de ceci. L'idée de base est d'appeler format et passer dans la chaîne de format, et une carte des objets, et les noms qu'ils ont localement.

la sortie de ce qui suit est:

mon chien s'appelle fido, et il appartient à Jane Doe.

public class StringFormatter {

    private static final String fieldStart = "\$\{";
    private static final String fieldEnd = "\}";

    private static final String regex = fieldStart + "([^}]+)" + fieldEnd;
    private static final Pattern pattern = Pattern.compile(regex);

    public static String format(String format, Map<String, Object> objects) {
        Matcher m = pattern.matcher(format);
        String result = format;
        while (m.find()) {
            String[] found = m.group(1).split("\.");
            Object o = objects.get(found[0]);
            Field f = o.getClass().getField(found[1]);
            String newVal = f.get(o).toString();
            result = result.replaceFirst(regex, newVal);
        }
        return result;
    }

    static class Dog {
        public String name;
        public String owner;
        public String gender;
    }

    public static void main(String[] args) {
        Dog d = new Dog();
        d.name = "fido";
        d.owner = "Jane Doe";
        d.gender = "him";
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("d", d);
        System.out.println(
           StringFormatter.format(
                "My dog is named ${d.name}, and ${d.owner} owns ${d.gender}.", 
                map));
    }
}

Note: cela ne se compile pas en raison d'exceptions non compilées. Mais il fait le code beaucoup plus facile à lire.

en outre, je n'aime pas que vous ayez à construire la carte vous-même dans le code, mais je ne sais pas comment obtenir les noms des variables locales programatiquement. La meilleure façon de le faire, est de vous mettre l'objet dans la carte dès que vous créez.

L'exemple suivant produit les résultats que vous voulez à partir de votre exemple:

public static void main(String[] args) {
    Map<String, Object> map = new HashMap<String, Object>();
    Site site = new Site();
    map.put("site", site);
    site.name = "StackOverflow.com";
    User user = new User();
    map.put("user", user);
    user.name = "jjnguy";
    System.out.println(
         format("Hello ${user.name},\n\tWelcome to ${site.name}. ", map));
}

je devrais aussi mentionner que je n'ai aucune idée de la Vitesse, donc j'espère que cette réponse est pertinente.

15
répondu jjnguy 2010-09-07 04:20:06

voici un aperçu de la façon de procéder. Il devrait être relativement simple de l'appliquer en tant que code réel.

  1. Créer une carte de tous les objets qui seront référencés dans le modèle.
  2. utilisez une expression régulière pour trouver des références variables dans le modèle et les remplacer par leurs valeurs (voir étape 3). La classe Matcher sera pratique pour trouver-et-remplacer.
  3. divise le nom de la variable au point. user.name devient user et name . Recherchez user dans votre carte pour obtenir l'objet et l'utilisation réflexion pour obtenir la valeur de name de l'objet. En supposant que vos objets ont des getters standards, vous chercherez une méthode getName et l'invoquerez.
4
répondu casablanca 2010-09-07 03:01:05

il y a quelques implémentations de langage D'Expression là-bas qui fait cela pour vous, pourrait être préférable d'utiliser votre propre implémentation comme ou si vos exigences augmentent, voir par exemple JUEL et MVEL

j'aime et ai utilisé avec succès MVEL dans au moins un projet.

Also see the Stackflow post JSTL / JSP EL (Expression Language) in a non JSP (standalone) contexte

4
répondu Christoffer Soop 2017-05-23 12:34:45

il n'y a rien dans la boîte qui soit comparable à la vitesse puisque la vitesse a été écrite pour résoudre exactement ce problème. La chose la plus proche que vous pouvez essayer est de regarder dans le Formatteur

http://cupi2.uniandes.edu.co/site/images/recursos/javadoc/j2se/1.5.0/docs/api/java/util/Formatter.html

cependant le formatteur autant que je sache a été créé pour fournir des options de formatage C comme en Java donc il ne peut pas égratigner exactement votre démangeaisons, mais vous êtes les bienvenus pour essayer :).

0
répondu Mike Milkin 2010-09-07 03:55:32