【问题标题】:How to check whether two java objects are same or not in freemarker如何在freemarker中检查两个java对象是否相同
【发布时间】:2012-09-06 15:33:54
【问题描述】:

我需要比较 freemarker 中的两个 java 对象是否相同。有没有办法检查freemarker中两个java对象的相等性

【问题讨论】:

    标签: freemarker


    【解决方案1】:

    不幸的是,从 2.3.19 开始就没有这种可能性了;可能会在 2.3.20 左右。你必须写一个TemplateMethodModelEx 来实现这个,比如sameObjects(p1, p2)。在这种情况下,您必须从参数TemplateModel-s 中提取原始对象。为此,您必须检查参数是否实现AdapterTemplateModel,然后调用AdapterTemplateModel.getAdaptedObject(Object.class)。然后您可以将原始对象与== 进行比较,仍然是Java,然后返回true/false

    更新:由于我打算将其贡献给 FreeMarker,因此我进行了更多研究。使用AdapterTemplateModel 对此并不完全正确,因为它可能涉及转换(如 Python 到 Java),然后您会丢失原始对象的身份,从而得到假阴性。使用WrapperTemplateModel 看起来像解决方案,但事实证明它对 Jython 的实现是错误的......所以我看到的唯一解决方案永远不会给出不正确的结果(但可能会给出错误,因为无法进行比较)是BeanModel。具体实现如下:

    package com.example;
    
    import java.util.List;
    
    import freemarker.ext.beans.BeanModel;
    import freemarker.ext.beans.BeansWrapper;
    import freemarker.template.TemplateBooleanModel;
    import freemarker.template.TemplateMethodModelEx;
    import freemarker.template.TemplateModelException;
    
    /**
     * Checks if two values correspond to the same object. This only works if both
     * arguments are wrapped into {@link BeanModel}-s by the object wrapping
     * facility of FreeMarker, which is usually the case for objects that aren't
     * {@code Collection}-s, {@code Map}-s, {@code String}-s, {@code Number}-s,
     * {@code Date-s}, {@code Boolean}-s, Jython objects, Rhino objects or DOM
     * objects. If you are using pure {@link BeansWrapper} for wrapping, this is the
     * case for all objects. If not all the arguments are {@link BeanModel}-s, or
     * some of them are {@code null}-s, this will throw an exception.
     */
    public class IsSameObjectMethodModel implements TemplateMethodModelEx {
    
        public Object exec(List args) throws TemplateModelException {
            if (args.size() != 2) {
                throw new TemplateModelException(
                        "Method expects exactly 2 arguments, but " +
                        args.size() + " was given.");
            }
            return toRawArg("1st", args.get(0)) == toRawArg("2nd", args.get(1)) ?
                    TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    
        /**
         * Extracts the original object from the argument.
         * @param argName Used in error messages
         */
        private Object toRawArg(String argName, Object argVal)
        throws TemplateModelException {
            if (argVal == null) throw new TemplateModelException(
                    "Method doesn't support null arguments, but the " +
                    argName + " argument was null");
            if (argVal instanceof BeanModel) {
                return ((BeanModel) argVal).getWrappedObject(); 
            } else {
                throw new TemplateModelException(
                        "Method only supports arguments that were wrapped by " +
                        "FreeMarker (or something else) so that they extend " +
                        "freemarker.ext.beans.BeanModel, but " +
                        "the " + argName + " argument wasn't like that (class: " +
                        argVal.getClass().getName() + "). To avoid this error, " +
                        "avoid comparing objects that are Collection-s, " +
                        "Map-s, String-s, Number-s, Date-s, Boolean-s, Jython " +
                        "objects, Rhino objects or DOM objects.");
            }
        }
    
    }
    

    要使用它,请将其放入数据模型中,或者假设您有一些用于导入/包含的模板,比如说utils.ftl

    ...
    [#assign isSameObject = "com.example.IsSameObjectMethodModel"?new()]
    ...
    

    然后在模板中:

    [#import "utils.ftl" as u]
    ...
    [#if u.isSameObject(o1, o2)]
      same
    [#else]
      different
    [/#if]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-07
      • 2012-06-23
      • 1970-01-01
      • 1970-01-01
      • 2016-10-22
      • 1970-01-01
      • 1970-01-01
      • 2016-06-27
      相关资源
      最近更新 更多