如何在freemarker中检查两个java对象是否相同

如何在freemarker中检查两个java对象是否相同,freemarker,Freemarker,我需要比较freemarker中的两个java对象是否相同。是否有任何方法可以检查freemarker中两个java对象的相等性?不幸的是,从2.3.19开始,没有这种现成的可能性;可能会在2.3.20左右。您必须编写一个TemplateMethodModelEx来实现这一点,类似于sameObjects(p1,p2)。在这种情况下,您必须从参数TemplateModel-s中提取原始对象。为此,必须检查参数是否实现了AdapterTemplateModel,然后调用AdapterTemplat

我需要比较freemarker中的两个java对象是否相同。是否有任何方法可以检查freemarker中两个java对象的相等性?不幸的是,从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]