FreeMarker语法
Posted Androider_Zxg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FreeMarker语法相关的知识,希望对你有一定的参考价值。
FreeMarker语法
概述
最近做公司一个需求,代码生成模板,编写用于生成Java Bean的ftl文件。在此记录下使用Freemarker的常用语法
FreeMarker Java使用
- 实例化FreeMarker配置类
Configuration conf = new Configuration();
- 设置配置类路径,也就是将会从该路径下读取模板文件
conf.setDirectoryForTemplateLoading(new File(dir));
- 读取模板文件
Template template = conf.getTemplate("freemarker.html");
- 定义数据模型
将模型放入一个Map中,可以放入对象、基本类型、List、,Map等
Map<String,Object> root = new HashMap<String,Object>();
Person p = new Person();
p.setId("111");
p.setName("哈哈哈");
root.put("person", p);
root.put("world", "世界你好");
//遍历List
List<String> persons = new ArrayList<String>();
persons.add("阿灵罗");
persons.add("罗零");
persons.add("灵罗");
root.put("persons",persons);
- 定义输出文本的文件
Writer out = new FileWriter(new File(dir+"hello.html"));
- 调用模板process方法,传入数据模型及目标文件,生成文本
template.process(root, out);
out.flush();
out.close();
- 在freemarker.html中访问放入map的数据结构,如:
<#list persons as p>
Id:$p.id
Name:$p.name
</#list>
FreeMarker语法
这里我们根据业务需求,自定义数据结构。在ftl文件中解析数据结构,以这个过程为串联,学习FreeMarker语法
数据结构
NetInterface:用于描述网络请求接口
public class NetInterface
// 请求名称
private String interfaceId;
// 请求功能描述
private String caption;
// 备注信息
private String comment;
// 请求相对路径
private String path = "";
// 自定义请求地址
private String customFullPath = "";
// 请求类型(Post 和 Get,会覆盖 service 中配置)
private String request_mode;
// 成功标识
private String succFlag;
// 错误提示信息
private String errorMsg;
// 请求 model
private SCRequestModel requestModel = new SCRequestModel();
// 返回数据 model
private SCResponseModel responseModel = new SCResponseModel();
public SCInterface(String methodName, SCRequestModel request, SCResponseModel response)
this.interfaceId = methodName;
this.requestModel = request;
this.responseModel = response;
RequestModel:描述请求参数
public class RequestModel
private String modelName = "";
// 请求参数
private List<SCParam> fields = new ArrayList<SCParam>();
private Boolean hasCustomModel = false;
//嵌套的子Model
private List<RequestModel> subModels = new ArrayList<SCResponseModel>();
ResponseModel:描述返回数据参数
public class ResponseModel
private String modelName = "";
// 请求参数
private List<SCParam> fields = new ArrayList<SCParam>();
private Boolean hasCustomModel = false;
//嵌套的子Model
private List<ResponseModel> subModels = new ArrayList<SCResponseModel>();
Param:描述一个参数
public class SCParam
//枚举数据类型
public enum ParamEnum
//系统类型 String等
ParamSystem(0),
//系统List 如List<String>
ParamArray_sys(1),
//自定义对象类型
ParamObject(2),
//List 泛型为自定义对象
ParamArray_object(3);
private int mState = 0;
private ParamEnum(int value)
mState = value;
public int getState()
return mState;
// 字段名称
private String paramName;
// 参数类型
private ParamEnum paramType;
// 系统字段类型
private String sysType;
// 备注信息
private String caption;
// 扩展数据类型(当不为默认类型时,使用此字符存储)
private List<SCParam> extendParam;
这里,假设我们已经有了一个List,并把它放入map中,如下:
List<NetInterface> netInterfaces = DataProvider.getInterfaces();
Map<String,Object> root = new HashMap();
root.put("interfaces",netInterfaces)
root.put("Id","abcd")
template.process(root, writer);
这样,我们在ftl文件中就能通过key值interfaces来访问List。下面我们介绍一下常用的语法
注释
<#-- 注释内容 -->
访问值
<#-- result:abcd -->
$Id
List相关
循环list
<#list interfaces as interface>
<#-- 访问interface -->
path:$interface.path
interfaceId:$interface.interfaceId
</#list>
list size判断
<#list interfaces as interface>
<#-- 注意一定要加括号,否则报错 -->
<#if (interface.requestModel.fields?size == 0)>
<#-- gt代表大于 -->
<#elseif (interface.requestModel.fields?size gt 0)>
<#-- lt代表小于 -->
<#elseif (interface.requestModel.fields?size lt 0)>
</#if>
</#list>
下标判断
<#list interfaces as interface>
<#-- 是否是最后一个 -->
<#if interface_has_next>
非最后一个
<#else>最后一个元素
</#if>
<#-- 是否为第一个-->
<#if (interface_index == 0)></#if>
<#if >
</#list>
if条件判断
<#-- 判空-->
<#if interface.request_mode??>
<#if interface.request_mode == "post">
<#-- 输出内容 -->
<#elseif interface.request_mode == "post">
<#-- 输出内容 -->
<#elseif interface.request_mode == "post">
<#-- 输出内容 -->
<#elseif interface.request_mode == "post">
<#-- 输出内容 -->
<#else>
error
</#if>
</#if>
首字母大小写
<#-- 首字母大写 -->
$param.paramName?cap_first
<#-- 首字母小写 -->
$param.paramName?uncap_first
宏定义
可以理解为自定义方法,我们看一个解析字段名的宏
<#-- 解析字段 -->
<#macro parserField target>
<#list target as param>
// $param.caption
<#if param.paramType.getState() == 0>
<#if param.sysType == "string">
public String $param.paramName?uncap_first;
<#elseif param.sysType == "int32">
public int $param.paramName?uncap_first;
<#elseif param.sysType == "boolean">
public boolean $param.paramName?uncap_first;
<#elseif param.sysType == "double">
public double $param.paramName?uncap_first;
<#elseif param.sysType == "int64">
public long $param.paramName?uncap_first;
<#elseif param.sysType == "float">
public float $param.paramName;
<#else>
parserClass error type state:$paramType.getState(),type:$param.sysType
</#if>
<#elseif param.paramType.getState() == 2>
public $param.sysType?trim?cap_firstObject $param.sysType?uncap_firstObject;
<#elseif param.paramType.getState() == 3>
public List<$param.sysType?trim?cap_firstObject> $param.sysType?uncap_firstObjectList = new ArrayList();
<#elseif param.paramType.getState() == 1>
<#if param.paramName == "list">
public List<<@parserType target = param.sysType/>> list = new ArrayList();
<#else>
public List<<@parserType target = param.sysType/>> $param.paramNameList = new ArrayList();
</#if>
</#if>
</#list>
</#macro>
大家可以结合文章上面阐述的数据结构来看,就难理解了
调用方式
<@parserField target=interface.responseModel.fields/>
判空
正确写法
<#if responseModel.subModels??>
错误写法
<#if responseModel?.subModels>
暂时用到的语法就这些
后记
Freemarker比较难调试,是因为暂时没找到IDE提示错误,全部要肉眼来看,靠freemarker的提示来找线索。所以写的时候一定要注意语法规范,错一点就会报错。如果有好的IDE,请安利给我
以上是关于FreeMarker语法的主要内容,如果未能解决你的问题,请参考以下文章