【问题标题】:How would I iterate through a list of [[tokens]] and replace them with textbox input?我将如何遍历 [[tokens]] 列表并用文本框输入替换它们?
【发布时间】:2010-01-19 10:00:25
【问题描述】:

这是我正在尝试制作的基本代码:

Field fields[] = SalesLetter.class.getDeclaredFields();
String fieldName;

for (int j = 0, m = fields.length; j < m; j++) {
       fieldName = fields[j].getName(); //example fieldname [[headline]]
       templateHTML = templateHTML.replace(fieldName, Letter.fieldName());
}

我相信我尝试 getDeclaredFields 是错误的(这甚至在语法上都不正确)。当我完成我的标题时,它提出了一些其他的 stackoverflow 问题,我在写这篇文章之前阅读了这些问题。他们是:

Best way to replace tokens in a large text template Replacing tokens in a string from an array

它给了我从文本文件中读取所有合法 [[tokens]] 的想法,将它们放入散列中(错误我的意思是映射,这是 java :D),然后创建一个同名的对象引用那个令牌。

我无法弄清楚我将如何在 java 中专门做这样的事情,或者这是否可行。请帮忙。

提前致谢,

科迪·古德曼

注意:我正在努力使一切尽可能灵活,所以也许将来我可以添加诸如“[[tokenname]]:这是令牌名称,您需要真正考虑客户想要什么在文本文件中提出一个好的令牌名称”,然后在我的表单上生成这些字段,一切正常:)

【问题讨论】:

    标签: java templates oop hashmap


    【解决方案1】:

    为了从某个类型的非静态字段中读取值,您需要对该类型的实例的引用:

    public class ReflectFields {
      static class Letter {
        public int baz = 100;
      }
    
      static class SalesLetter extends Letter {
        public String foo = "bar";
      }
    
      public static void main(String[] args) throws Exception {
        // TODO: better exception handling, etc.
        SalesLetter instance = new SalesLetter();
        for (Field field : instance.getClass().getFields()) {
          System.out.format("%s = %s%n", field.getName(), field.get(instance));
        }
      }
    }
    

    您还必须注意私有字段等。一般来说,应该避免这种方法,因为它会通过查看类内部来破坏封装。

    考虑使用 JavaBean API。

    public class BeanHelper {
      private final Object bean;
      private final Map<String, Method> getters = new TreeMap<String, Method>();
    
      public BeanHelper(Object bean) {
        this.bean = bean;
        for (PropertyDescriptor pd : Introspector.getBeanInfo(bean.getClass(),
              Object.class).getPropertyDescriptors()) {
          getters.put(pd.getName(), pd.getReadMethod());
        }
      }
    
      public Set<String> getProperties() { return getters.keySet(); }
    
      public Object get(String propertyName) {
        return getters.get(propertyName).invoke(bean);
      }
    
      public static void main(String[] args) {
        BeanHelper helper = new BeanHelper(new MyBean());
        for (String prop : helper.getProperties()) {
          System.out.format("%s = %s%n", prop, helper.get(prop));
        }
      }
    
      public static class MyBean {
        private final String foo = "bar";
        private final boolean baz = true;
        public String getFoo() { return foo; }
        public boolean isBaz() { return baz; }
      }
    }
    

    为简洁起见省略了异常处理,因此您需要添加一些 try/catch 块(我建议将捕获的异常包装在 IllegalStateExceptions 中)。

    【讨论】:

    • 刚开始使用java,所以我想我必须先阅读一些javadocs,然后才能完全理解这个答案。谢谢您的帮助!我看看我能不能把这段代码放在一起。
    【解决方案2】:

    使用Freemarker、Velocity 或StringTemplate 之类的模板引擎怎么样:

    • 将[[ 替换为${ 和]] 替换为}
    • 从包含替换的属性文件创建模型
    • 处理模板HTML

    这里是 Freemarker 的示例(没有异常处理)

    Configuration config = new Configuration();
    StringTemplateLoader loader = new StringTemplateLoader();
    config.setTeplateLoader(loader);
    
    Map model = Properites.load(new FileInputStream("tokens.properties"));
    loader.putTemplate("html.ftl", templateHTML);
    Template template = config.getTemplate("html.ftl");
    
    Writer out = new StringWriter();
    template.process(root, out);
    String result = out.toString();
    

    StringTemplate 可能更简单(将[[ 和]] 替换为$),但我不熟悉它:

    Map model = Properites.load(new FileInputStream("tokens.properties"));
    StringTemplate template = new StringTemplate(templateHTML);
    template.setAttributes(model);
    String result = template.toString();
    

    tokens.properties 文件如下所示:

    tokenname:this is token name
    

    【讨论】:

    • 这看起来很有趣,而且非常灵活。我会看看我是否不能把代码和这个放在一起。不过喜欢这里的简单。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-26
    • 1970-01-01
    • 2023-03-19
    • 2021-04-24
    • 2014-11-14
    • 2021-06-19
    • 2022-11-20
    相关资源
    最近更新 更多