OFBiz进阶--OFBiz问答之[ftl]文件中{?keys}和{map.keySet()}显示异常分析

阅读更多
一个问题引发的思考
 
来看场景 1
 
我有一个 java 的 Map 变量, 希望在 ftl 文件中被 list 循环迭代显示到页面, 示例如下
java代码片段 1

Map javaMap = new HashMap();
javaMap.put(“a”, “A”);
javaMap.put(“b”, “B”);

 
ftl代码片段 1

<#list javaMap.keySet() as ke>
   

${ke}=${javaMap[ke]}

 
渲染出的ftl代码

a=A

b=B


 
ftl代码片段 2

<#list javaMap?keys as ke>
   

${ke}=${javaMap[ke]}

 
渲染出的ftl代码
模板渲染错误, 在${javaMap[ke]}地方渲染发生错误

 
ftl代码片段 3

<#list javaMap?keys as ke>
    ${ke};
 
渲染出的ftl代码
hashCode;keyOne;getClass;get;values;toString;keyTwo;clone;keySet;containsValue;notifyAll;clear;size;empty;entrySet;isEmpty;class;put;putAll;remove;containsKey;equals;wait;notify;

 
在看场景 2 
java代码片段 2
String javaString = “{'a':'A','b':'B'}”;
 
ftl代码片段 4

<#assign ftlBeanObj = javaString?eval>
验证 , 对象会是Map特性的对象吗
<#list ftlBeanObj.keySet() as ke>
   

${ke}=${ftlBeanObj[ke]}

 
验证 -结果如下,渲染出的html代码
模板渲染错误, 在 ftlBeanObj.keySet() 地方渲染发生错误, 没找到这个方法

ftl代码片段 5

<#assign ftlBeanObj = javaString?eval>
验证 , 对象会是JSON特性的对象吗
<#list ftlBeanObj?keys as ke>  
     

${ke}=${ftlBeanObj[ke]}

 
验证 -结果如下,渲染出的html代码

a=A

b=B


 
分析, 在前文环境中
javaMap是一个java的对象, 
    若想正确的遍历其内存储的键值对, 需要使用对象自身方法 Map.keySet() 方法来遍历
    若使用ftl专属语法 ?keys, 将会把 javaMap 对象这个HashMap类自身的java.method当作对象的属性, 在这里被遍历出来
 
javaString?eval 这个ftl专属语法将构建一个ftl专属的 DefaultObjectWrapper 对象, 
    此时需要使用 ?keys 语法,才能正确的遍历出其内部的实际键值对
    这里构建出来的对象不具有Map性质
 
 
思考
有文章提到 javaMap 的这种遍历现象是因为 ftl 将 java Object 转为 BeansWrapper 对象了, 而不是转为 DefaultObjectWrapper 对象
原文如下
However, some really old FreeMarker integrations use a strange configuration, where the public Map methods (like getClass) appear as keys. That happens as they are using a pure BeansWrapper (instead of DefaultObjectWrapper) whose simpleMapWrapper property was left on false. You should avoid such a setup, as it mixes the methods with real Map entries.
 
要想使用 javaMap.keySet() 方式遍历键值对, 需要调整 ftl 的初始配置(ps: 本人还未尝试,不确定配置改动是否能正常得到后文提到的结果
在配置文件中加入如下配置:
freemarker.ext.beans.BeansWrapper
 
在 OFBiz 中这个配置的初始化如下, 这里是 BeansWrapper 对象
// import freemarker.ext.beans. BeansWrapper;
// import freemarker.ext.beans. BeansWrapperBuilder;
// import freemarker. template. Configuration;
// import freemarker. template. Version;
Version version = Configuration. VERSION_2_3_24;
Configuration newConfig = new Configuration(version);
BeansWrapper wrapper = new BeansWrapperBuilder(version).build();
newConfig.setObjectWrapper(wrapper);
 
若如 OFBiz 中这种配置, 确实会如前文 javaMap.keySet() 遍历正常;  javaMap?keys 遍历出错;
 
 
在 Moqui 中这个配置的初始化如下, 这里是 BeansWrapper 对象
[org.moqui.impl.context.renderer.FtlTemplateRenderer#makeFtlConfiguration]
//
Version FTL_VERSION = Configuration.VERSION_2_3_25;
Configuration newConfig = new MoquiConfiguration ( FTL_VERSION, ecfi );
BeansWrapper defaultWrapper = new BeansWrapperBuilder ( FTL_VERSION ). build ();
newConfig. setObjectWrapper (defaultWrapper );
 
若如 Moqui 中这种配置, 也会如前文 javaMap.keySet() 遍历正常;  javaMap?keys 遍历出错; 
 
 
参考链接
[ https://www.eertime.com/archives/255.html]

[ https://stackoverflow.com/questions/1497777/freemarker-iterating-over-hashmap-keys] 

你可能感兴趣的:(ofbiz,ftl,keys,keyset,map)