Java Freemarker 2.3.23是否正确处理变量?

Java Freemarker 2.3.23是否正确处理变量?,java,freemarker,Java,Freemarker,此(可怕;不问;我无法修改数据模型或配置)表达式不起作用: ${statics["java.nio.file.Files"].write(statics["java.nio.file.Paths"].get("/foo/bar.stuff"), statics["java.nio.charset.Charset"].forName("UTF-8").encode(someStringContent).array(), enums["java.nio.file.StandardOpenOption

此(可怕;不问;我无法修改数据模型或配置)表达式不起作用:

${statics["java.nio.file.Files"].write(statics["java.nio.file.Paths"].get("/foo/bar.stuff"), statics["java.nio.charset.Charset"].forName("UTF-8").encode(someStringContent).array(), enums["java.nio.file.StandardOpenOption"].WRITE)}
型号代码:

    model.addAttribute("statics", new BeansWrapperBuilder(Configuration.VERSION_2_3_23).build().getStaticModels());
    model.addAttribute("enums", new BeansWrapperBuilder(Configuration.VERSION_2_3_23).build().getEnumModels());
简单地说,这是一种(总体)方法,可以获取一些Freemarker字符串内容,将其转换为
字节[]
数组,然后从Freemarker中将其写入
/foo/bar.stuff
路径

错误表明Freemarker无法选择正确的varargs方法:

Error executing FreeMarker template
FreeMarker template error:
When trying to call the non-varargs overloads:
No compatible overloaded variation was found; can't convert (unwrap) the 3rd argument to the desired Java type.
The FTL type of the argument values were: extended_hash+string (sun.nio.fs.UnixPath wrapped into f.e.b.StringModel), sequence (byte[] wrapped into f.t.DefaultArrayAdapter$ByteArrayAdapter), extended_hash+string (java.nio.file.StandardOpenOption wrapped into f.e.b.StringModel).
When trying to call the varargs overloads:
Multiple compatible overloaded variations were found with the same priority.
The Java type of the argument values were: sun.nio.fs.UnixPath, byte[], java.nio.file.StandardOpenOption.
The matching overload was searched among these members:
    static java.nio.file.Files.write(java.nio.file.Path, Iterable, java.nio.file.OpenOption...),
    static java.nio.file.Files.write(java.nio.file.Path, Iterable, java.nio.charset.Charset, java.nio.file.OpenOption...),
    static java.nio.file.Files.write(java.nio.file.Path, byte[], java.nio.file.OpenOption...)
我也尝试过其他方法,包括使用
java.lang.reflect.array#newInstance(Class,int)
创建一个正确类型的数组,但没有任何帮助


我假设这是不可能的?

您可以将对
Files.write()
方法的调用封装在自己明确的方法中

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;

public class UnambiugousMethodWrappers{
    public static Path writeBytes (Path path, byte[] bytes, OpenOption... options) throws IOException {
        return Files.write(path, bytes, options);
    }
}

我想这将是重载方法选择中的一个小故障,它被模拟为100%向后兼容。因此,您应该将FreeMarker配置的
不兼容\u改进设置增加到至少2.3.21,以便激活修复程序(或者如果您没有使用
对象包装器的默认设置,则使用您正在创建的
对象包装器的类似设置)。但是,你说你不能触摸FreeMarker配置


我还在另一个答案中看到,您也不能添加自己的静态助手类…

假设您的
statics
模型字段是使用
EXPOSE\u ALL
构建的,您可以深入反射兔子洞:

<#assign class = statics["java.lang.Class"]>
<#assign openOptionClass = class.forName("java.nio.file.OpenOption")>
<#assign filesClass = class.forName("java.nio.file.Files")>
<#assign method = filesClass.getMethod("write", class.forName("java.nio.file.Path"),class.forName("[B"),class.forName("[Ljava.nio.file.OpenOption;"))>
<#assign path = statics["java.nio.file.Paths"].get("/foo/bar.stuff")>
<#assign utf8 = statics["java.nio.charset.Charset"].forName("UTF-8")>
<#assign writeOptions = enums["java.nio.file.StandardOpenOption"].WRITE>
<#assign writeOptionsArray = statics["java.lang.reflect.Array"].newInstance(openOptionClass,1)>
<#assign ignoreThisVoid = statics["java.lang.reflect.Array"].set(writeOptionsArray, 0, writeOptions)>
${method.invoke(null, path, utf8.encode(someStringContent).array(), writeOptionsArray)}

谢谢出于一些在这里并不重要的原因,我可以使用的只是Freemarker模板本身-(你有权访问定义静态的代码吗?你能粘贴它吗?如果你不介意的话,我正在粘贴模型代码以获得你看到的错误。如果它与你的不一样,请更正它。莱尔德,你的静态BeanRapper是用EXPOSE_ALL exposure级别构建的吗?嗨;谢谢你的兴趣和帮助!将内容填充到数据模型读取:
dataModel.put(“statics”,beansWrapper.getStaticModels())
追溯到这一点,
beansWrapper
是使用构建的
DefaultObjectWrapper
的一个子类。虽然子类允许您设置自定义的
ModelFactory
实例,但它似乎没有太大的魔力。这些实例在这里不起作用。所以我并没有完全做到这一点,但它反映了我所做的事情。我发现无论涉及
java.lang.reflect.Array
(为了“伪造”vargars)的咒语是什么,我发现调用
java.lang.reflect.Array#newInstance(Class,int)
都不会起作用(Freemarker仍然感到困惑).啊,但是你使用
getConstructor
是出于我没有想到的任何原因!这应该可以让我走出这个兔子洞。:-)谢谢。我在本地尝试了这两种方法,它们都为meSorry工作;我不清楚。没有将
文件#write()
java.lang.reflect.Array#newInstance()
组合使用(以识别varargs参数)。我还没有尝试过反射方法,并假设(如您所示)它会起作用。再次感谢你的帮助;我有点跛脚了。:-)感谢您的帮助(以及Freemarker的维护!)。它肯定比我使用过的任何其他模板引擎都更灵活。
<#assign class = statics["java.lang.Class"]>
<#assign fileOutputStreamClass = class.forName("java.io.FileOutputStream")>
<#assign fileOutputStreamConstructor = fileOutputStreamClass.getConstructor(class.forName("java.lang.String"))>
<#assign fileOutputStream = fileOutputStreamConstructor.newInstance("/foo/bar.stuff")>
<#assign ignoreThisVoid = fileOutputStream.write(utf8.encode(someStringContent).array())>