整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

FreeMarker基本语法

.FreeMarker介绍

FreeMarker是一种模板引擎,通过定义的模板和数据来生成文本(包括但不局限于html,js,java等文本格式),通俗的讲就是先定义一下模板,然后传入不同的数据,动态的生成不同的文本,但它不是面向用户的,而是面向程序员的,可以直接自动的生成代码,减少程序员重复的劳动。FreeMarker最重要的两部分是模板和数据:模板:FreeMarker Template Language,简称FTL,模板文件以ftl为后缀,组成:

  • 文本,包括HTML标签与静态文本等静态内容,会原样输出;

  • 插值:这部分的输出会被计算的数据来替换,使用${}这种语法;

  • 标签:给FreeMarker的指示,可以简单与指令等同,不会打印在内容中;

  • 注释:由<#--和-->表示,不会被freemarker处理 数据结构: 树状结构:HashMap,Scalar,Sequence

2.基本使用

从http://freemarker.org/ 下载FreeMarker的压缩包,将其中的freemarker.jar加到项目的构建路径下从maven仓库中引入maven依赖的jar包,注意两个核心类:

<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.24-atlassian-2</version></dependency>
  • Configuration:读取模板文件

  • Template:模板

 Configuration cfg = new Configuration(Configuration.VERSION_2_3_21); Map<String,String> root= new HashMap<String,String>(); root.put("name", "Java开发日记"); try { cfg.setDirectoryForTemplateLoading(new File("src/ftl")); Template template = cfg.getTemplate("helloworld.ftl"); Writer writer = new FileWriter(new File("src/finish/helloworld.html")); template.process(root, writer); } catch (Exception e) { e.printStackTrace(); }

使用Configuration读取配置文件,使用Map填充数据,给配置文件配置模板文件夹路径,读取模板文件,设置输出文件路径helloworld.html,执行输出文件,执行完之后就会在src目录下的finish文件夹中生成一个helloworld的html文件。模板文件如下:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>${name}</title></head><body>这是我的第一个程序,${name}</body></html>

3.模板

3.1 数据类型与变量

模板中的数据类型:

  • 标量:字符串,数字,布尔值,日期;

  • 容器:哈希表,序列;

  • 子程序:方法和函数,用户自定义指令; 模板中的变量: 简单变量,局部变量,循环变量,使用赋值指令:assign 示例:

<#assign num=10>${num}<#assign name="Java开发日记">${name}<#assign b=true>${b?c}<#assign map={"name":"张三","age":15}>${map.name}<#assign list = [1,3,5]>${list[2]}

freemarker中使用指令时必须要在指令前面用#(如果是自定义指令用@,后面说),assign指令是用来声明变量的,注意:如果是布尔值,输出时一定要带?c,表示定义的变量是布尔值,不然会报错。

3.2运算符

模板中支持运算符:

  • 算术运算符

  • 比较运算符

  • 逻辑运算符

  • 空值处理运算符

<#assign b=1==2>${b?c}<#assign b=1 gt 2>${b?c}

均输出false,gt表示大于。

3.3 插值

插值是用来给插入具体值然后转换为文本,说白了,插值就是使用${}在那占个坑。使用位置:

  • 文本区(如

    Hello ${name}!

  • 字符串表达式(如<#include "/footer/${company}.html">) 语法:${表达式} 注意:插值表达式的结果必须是字符串,数字或日期类型。

3.4指令

  • 条件指令

<#assign score=50><#if score gt 90>优秀<#elseif score gt 70>良好<#elseif score gt 60>及格<#else>渣渣</#if><#assign level="B"><#switch level> <#case "A"> 优秀 <#break > <#case "B"> 良好 <#break > <#case "C"> soso <#break > <#default> 渣渣</#switch>

需要注意的是switch语句需要有break,不然一直往下执行。

  • 循环指令

<#assign nums=[1,2,3,4,5]><#list nums as num> ${num_index},${num},${num_has_next?c}</#list><#list nums as num> ${num}<#if num_has_next>,</#if></#list>

定义一个集合nums,使用list指令遍历,${别名index}获取遍历的索引值,${别名has_next}判断后面是否还有值,根据这个特性,可以结合if指令拼接不同的值(自动生成mybatis的配置文件时,不同字段最后一个后面不要逗号,用这个特性很好用)。

  • 包含指令

<#include "condition.ftl">从这里开始是自己的内容

使用include引入指令可以引入其它的模板页面。如果页面路径写不好可以用通配符,<#include "*/condition.ftl">

  • 其它 原样输出指令noparse:它里面的内容是原样输出的; 压缩指令compress:压缩所有的空格; 设置指令setting:设置影响FreeMarker的值。

<#noparse> <#assign num=1> ${num}</#noparse><#assign s=" test \n\n"><#compress> ${s} Compress</#compress><#setting locale="hu">${1.2}
  • 自定义指令 可以将模版中重复的内容进行复用 定义: 使用macro指令定义或者使用Java实现。 参数的声明:直接跟在指令名后,可以指定默认值 嵌套内容:使用nested指令 调用: 使用<@指令>来调用(调用freemarker自带的指令用#命令)。

<#macro mydirect name age=20> 你好,${name},你今年${age}</#macro><@mydirect name="Java开发日记" age=1/>

自定义一个指令名为mydirect,它有两个参数name和age,其中age有默认值20,使用自定义指令时用@+自定义指令,同时为参数赋值即可。注意自定义指令是闭口的,不要漏掉最后的斜杠。

3.5 空处理

有时候对象是空的,不进行判断就贸然进行处理会报错,所以要提前进行判空处理。

  • null对象的处理方式:使用!,只会做最后一个属性的判断;

  • 变量不存在的处理方式:使用!或??做判断。

${user.name!}<#if user.name??> 名称存在 <#else> 名称不存在</#if>

我认为是在插值时使用!,在其它指令内使用??。

3.6名称空间

在编写可重复使用的模板时为了避免命名冲突,使用import指令导入命名空间。命名空间有点类似于java的包,即使类名相同,只要位于不同的包下,也是可以的。

test.ftl模板:<#macro mydirective name> 你好,${name}</#macro>namespace.ftl模板<#import "test.ftl" as ns><@ns.mydirective name="Java开发日记" />

在这里我定义两个模板,在namespace.ftl中使用import指令导入test.ftl模板并为它起一个名为ns的命名空间,调用时我使用命令空间调用,即使namespace.ftl模板中有其它同名的也不至于混淆。另外在test.ftl中使用的是自定义指令定义了名为mydirective的指令,并为其制定一个参数name。

3.7函数

FreeMarker中函数有如下几种:

  • 字符串函数;

  • 数字,日期布尔类型的函数;

  • 序列(list,set)与哈希的函数;

  • 自定义函数 而且FreeMarker中的函数与java中函数调用有个很大的区别,在java中调用函数使用点号(.),而在FreeMarker中使用问号(?),这一点一定要记清。下面分别说上面提到的几种函数:

3.7.1字符串函数

${"abcdef"?substring(2)} <#--从角标是2的位置开始截取到字符串结束-->${"abcdef"?substring(2,4)} <#--从角标是2的位置开始截取到角标是4的位置,包括2不包括4(包前不包后)-->${"abcd mn"?cap_first} <#--将整个字符串的首字母转大写-->${"Abcd"?uncap_first} <#--将整个字符串的首字母转小写-->${"fden eb"?capitalize} <#--将字符串的每个单词首字母转大写-->${"abcd"?ends_with("d")?c} <#--是否以字符d结尾,这个结果是布尔值,不能直接输出,不然会报错,用?c转化成字符串-->${"abcd"?starts_with("d")?c} <#--是否以字符d开头-->${"abac"?index_of("a")} <#--字符a首次出现的位置-->${"abac"?last_index_of("a")} <#--字符a最后一次出现的位置-->${"ab"?left_pad(15,"xy")} <#--将字符串ab填充成15位,如果不够15位,则左边循环填充xy-->${"ab"?right_pad(15,"xy")} <#--将字符串ab填充成15位,如果不够15位,则右边循环填充xy-->${"abac"?contains("ab")?c} <#--判断字符串abac是否包含ab-->${"abac"?replace("ab","AB")} <#--将ab替换成AB--><#list "abcabcabc"?split("c") as s> ${s} <#--将字符串以c字符进行分割,结果是个数组,进行遍历--></#list>${" abc "?trim} <#--去掉字符串空格--><#list " Hello FreeMarker Yes"?word_list as s>${s} <#--将字符串分割成一个个的单词,存在多个空格时,这个跟上面的split分割有一点区别--></#list>

3.7.2数字,日期布尔类型的函数

${4.2?c} <#--以字符串的形式输出,上面说的布尔类型不能直接输出只能转化成字符串这种-->${4.2?string} <#--与?c一样-->${0.42?string.percent} <#--以百分号输出42%-->${4.2?string.currency} <#--以货币形式输出¥4.20-->${4.7?round} <#--四舍五入 -->${4.7?floor} <#--向下取整,floor地板 -->${4.7?ceiling} <#--向上取整,ceiling天花板-->${date?string("yyyy-MM-dd")} <#--传入日期date,以yyyy-MM-dd形式输出,2017-11-18-->${date?date} <#--输出年月日2017-11-18-->${date?time} <#-- 输出时分秒20:41:49-->${date?datetime} <#--输出年月日时分秒-->${false?string("yes","no")} <#--条件如果成功输出yes,否则输出no-->${4.2355?string("0.##")} <#--保留小数点后两位-->

3.7.3 序列(list,set)与哈希的函数

<#assign seq=[1,2,3,4,5,3,10]>${seq?first} <#-- 输出序列seq的第一个-->${seq?last} <#-- 输出序列seq的最后一个-->${seq?seq_contains(6)?c} <#--判断序列是否包含6-->${seq?seq_index_of(3)} <#--3在序列中首次出现的位置-->${seq?seq_last_index_of(3)} <#--3在序列中最后一次出现的位置--><#list seq?reverse as num> <#--翻转序列seq,结果还是一个序列,进行遍历-->${num}</#list>${seq?size} <#--序列seq的长度--><#list seq?sort as num> <#--对序列进行排序-->${num}</#list><#assign seq1=[{"name":"Tom","age":23},{"name":"Jack","age":22},{"name":"Rose","age":21},{"name":"Tim","age":24}]><#list seq1?sort_by("age") as u> <#--以age对哈希seq1进行排序并遍历-->${u.name}+","+${u.age}</#list><#assign users={"name":"Tim","age":24}><#list users?keys as key> <#--获取到哈希users所有的键-->${key}</#list>

3.7.4 自定义函数

<#function add num1 num2> <#return num1+num2></#function><#function addAll nums...> <#local total=0> <#list nums as num> <#local total=total+num> </#list> <#return total></#function><#--使用function指令定义函数add,有两个参数num1和num2,使用return返回计算之后的结果,使用${add(1,3)}调用函数 -->${add(1,3)}<#--使用function指令定义函数addAll,参数个数不固定,定义局部变量total来存储临时计算的结果,遍历所有的参数并进行运算,使用return返回计算之后的结果,使用${addAll(1,2,3,4,5)}调用函数 -->${addAll(1,2,3,4,5)}

4.数据模型

4.1数据类型

使用基本数据类型来派生数字类型使用java.lang.String来构建字符串。使用java.lang.Number来派生数字类型。使用java.lang.Boolean来构建布尔值。使用java.util.List,java.util.Set或Java数组来构建序列。使用java.util.Map来构建哈希表。

 Map root=new HashMap(); root.put("d1", 100); root.put("d2", 100.99); root.put("d3", 'a'); root.put("d4", true); root.put("d5", new Integer(200)); root.put("d6", new Boolean(false)); List<String> names= Arrays.asList("abc","def","ghi"); root.put("d7", names); Set<String> names1=new HashSet<>(); names1.add("ABC"); names1.add("DEF"); names1.add("GHI"); root.put("d8", names1); root.put("d9", new String[]{"a","b","c"}); Map map=new HashMap(); map.put("name", "Java开发日记"); map.put("age", 18); root.put("map", map);

就是java中常见的整型,浮点型,布尔型,字符,数组,list,set,map,不再多说

4.2 加载模板

使用Configuration的方法加载模版:1,void setDirectoryForTemplateLoading(File dir);2,void setClassForTemplateLoading(Class cl, String prefix);3,void setServletContextForTemplateLoading(Object servletContext, String path);加载多个位置的模版:1,FileTemplateLoader2,ClassTemplateLoader3,TemplateLoader4,MultiTemplateLoader5,setTemplateLoader(MultiTemplateLoader mtl);

 Configuration cfg = new Configuration(Configuration.VERSION_2_3_22); //cfg.setClassForTemplateLoading(TemplateLoad.class, "../../../ftl"); FileTemplateLoader ftl1=new FileTemplateLoader(new File("src/ftl")); FileTemplateLoader ftl2=new FileTemplateLoader(new File("src/ftl2")); ClassTemplateLoader ctl=new ClassTemplateLoader(TemplateLoad.class, "../../../ftl3"); TemplateLoader[] loaders={ctl,ftl2}; MultiTemplateLoader mtl=new MultiTemplateLoader(loaders); cfg.setTemplateLoader(mtl); Template template=cfg.getTemplate("ftl2.ftl"); System.out.println(template);

javase项目中使用setDirectoryForTemplateLoading来加载模板所在文件夹,javaee项目中使用setClassForTemplateLoading路径,servlet中可以使用setServletContextForTemplateLoading来加载模板路径。

4.3其它配置

配置就是在对象中存储常用的设置和定义某些想在所有模板中可用的变量,配置对象是freemarker.template.Configuration的实例,可以通过构造方法来创建它。而且一个应用程序通常只使用一个共享的Configuration实例。

  • 设置共享变量:setSharedVariable()

  • 国家地区:setLocale();

  • 数字格式:setNumberFormat("0.##");

  • 通用设置:setSetting(String name, String value)方法

  • 缓存:设置缓存:setCacheStorage(new freemarker.cache.MruCacheStorage(20, 250)) 或setSetting(Configuration.CACHESTORAGEKEY, "strong:20, soft:250");

  • 清空缓存:clearTemplateCache

Configuration cfg=new Configuration(Configuration.VERSION_2_3_22); cfg.setDirectoryForTemplateLoading(new File("src/ftl")); //设置共享便令 cfg.setSharedVariable("site", "Java开发日记"); //设置小数点后保留两位 cfg.setNumberFormat("0.##");、 //设置缓存,一级缓存20个,2级缓存250个 cfg. setCacheStorage(new freemarker.cache.MruCacheStorage(20, 250)); //cfg.setSetting(Configuration.CACHE_STORAGE_KEY, "strong:20, soft:250"); //cfg.clearTemplateCache(); //清楚缓存 Template template = cfg.getTemplate("config.ftl"); Writer writer = new FileWriter(new File("src/finish/config.html"));

总结:上面这些就是FreeMarker模板引擎的基本操作,首先需要进入jar包,之后设置模板所在的路径并引入模板,然后组装数据(实际操作中通过jdbc连接数据库来操作),所以主要学的就两方面内容:模板和数据,而模板又与这许许多多的指令相关,所以必须要掌握这些指令。

家好,本篇文章分享企业项目介绍的布局设计,这种样式设计通常用于企业网站上方的项目介绍或者服务介绍,可以更好的突出企业的核心特点和品牌形象。

话不多说,直接看效果图:

企业项目介绍的布局样式

HTML代码 :

<div class="tpt-list cl">
<div class="tpt-wp cl">
<div class="tpt-md-3">
<div class="a">
<i class="layui-icon"></i>
<h3>HTML网页设计</h3>
<p>感谢您使用本套网站内容管理系统,致力于为您创建一个高效简洁但稳定实用的网站程序。</p>
</div>
</div>
<div class="tpt-md-3">
<div class="a">
<i class="layui-icon"></i>
<h3>HTML网页设计</h3>
<p>感谢您使用本套网站内容管理系统,致力于为您创建一个高效简洁但稳定实用的网站程序。</p>
</div>
</div>
<div class="tpt-md-3">
<div class="a">
<i class="layui-icon"></i>
<h3>HTML网页设计</h3>
<p>感谢您使用本套网站内容管理系统,致力于为您创建一个高效简洁但稳定实用的网站程序。</p>
</div>
</div>
<div class="tpt-md-3">
<div class="a">
<i class="layui-icon"></i>
<h3>HTML网页设计</h3>
<p>感谢您使用本套网站内容管理系统,致力于为您创建一个高效简洁但稳定实用的网站程序。</p>
</div>
</div>
<div class="tpt-md-3">
<div class="a">
<i class="layui-icon"></i>
<h3>HTML网页设计</h3>
<p>感谢您使用本套网站内容管理系统,致力于为您创建一个高效简洁但稳定实用的网站程序。</p>
</div>
</div>
<div class="tpt-md-3">
<div class="a">
<i class="layui-icon"></i>
<h3>HTML网页设计</h3>
<p>感谢您使用本套网站内容管理系统,致力于为您创建一个高效简洁但稳定实用的网站程序。</p>
</div>
</div>
</div>
</div>

部分CSS代码分析:

首先我们给网页定义一个白色背景

body {
	background: #fff;
}

定义整个布局的宽度为1200像素,并居中显示

.tpt-wp {
	width: 1200px;
	margin: 0 auto
}

使布局分成三个相等的宽度,各占百分之三十三点三,并往左浮动

.tpt-md-3 {
	width: 33.3%;
	float: left
}

给每份布局定义外边距20像素,内边距为上下50像素,左右20像素

.tpt-list .a {
	margin: 20px;
	padding: 50px 20px;
}

给上方的图标标签定义一个56像素的大小,颜色为红色

.tpt-list i {
	font-size: 56px;
	color: #ff5722;
}

给h3标题定义20像素的大小,黑色的字体颜色,行高为30像素,内边距为上下10像素

.tpt-list h3 {
	color: #333;
	font-size: 20px;
	line-height: 30px;
	padding: 10px 0
}

最后给文字介绍14像素的大小,灰色的字体颜色,行高为24像素

.tpt-list p {
	color: #999;
	font-size: 14px;
	line-height: 24px;
}

当然,布局的方式有很多种,这只是其中一个方法,也欢迎大家留言分享一下其他的布局方式,点击下面了解更多获取全部CSS代码。

导专家:

谢 晶 上海海洋大学食品学院院长、教授

沈 群 中国农业大学食品科学与营养工程学院教授

黄忠民河南农业大学食品科学技术学院教授

元宵节是中国农历春节后第一个重要节日,人们在当天有食用元宵(汤圆)的传统。“包汤圆”和“滚元宵”所用的原料、配料基本相同,但制作工艺略有不同,口感亦有所区别。面对市场上琳琅满目的元宵产品,消费者该如何选购呢?国家市场监督管理总局从阅读元宵包装食品标签角度提示如下。

一、标签信息要齐全,“9+”要素不可缺

消费者在超市等正规食品销售场所或渠道购买元宵,需仔细查看包装上食品标签内容是否齐全。按照国家相关标准要求,直接向消费者提供的预包装食品标签标示应包括:食品名称、配料表、净含量和规格、生产者和(或)经销者的名称、地址和联系方式、生产日期和保质期、贮存条件、食品生产许可证编号、产品标准代号等9大项目,及其他需要标示的内容。不要购买或食用无标签或标签信息不全、内容不清晰,掩盖、补印或篡改标示的元宵。

二、配料顺序有讲究,致敏信息勿漏读

按照有关国家食品安全标准要求,在制造或加工食品时使用的,并存在于产品中的任何物质(包括食品添加剂),都需要在食品配料表中一一标示。加入量超过2%的配料,应按制造或加工食品时加入量从高到低依次排列。因此,消费者在选购元宵时,可以先察看配料表,了解产品的配料使用情况,再决定购买哪种产品。

配料中若含有可能导致过敏的食品及其制品,如含有麸质的谷物及其制品、花生及其制品等,厂家一般会(不是必须)在配料表中使用易辨识的名称,或在配料表邻近位置加以提示;加工过程中可能带入上述食品或其制品,也宜在配料表临近位置加以提示。因此,易敏人群在挑选或食用元宵时需注意仔细查阅配料表,以及配料表邻近位置是否有提示信息。

三、两个日期要细看,贮存烹煮遵说明

产品标签上的生产日期和保质期要重点查看。选购元宵时,建议购买保质期内的品质稳定产品,不要购买已过保质期的产品。

按照法规要求,在预包装元宵的标签上都标示着贮存条件。如速冻汤圆一般要求在-18℃条件下储存,无论在选购产品时还是购买后,都应确保产品贮存在标签标示的贮存条件下。

此外,通常在元宵包装标签上,厂家一般会给出合理的烹煮建议,消费者可参考以获得最佳口感。

四、营养标签细阅读,参照购买更合适

根据国家相关标准要求,元宵标签上还会提供营养标签。营养标签主要包括:表格形式的“营养成分表”,以及解释营养成分水平高低的“营养声称”和解释健康作用的“营养成分功能声称”。其中,营养成分表至少应标出5个要素(能量、蛋白质、脂肪、碳水化合物、钠)的含量及其占营养素参考值(NRV)的百分比。消费者可根据营养素参考值和自身状况选择食用。

五、元宵味虽美,特殊人群需注意

消费者可根据自己的喜好,按照预包装上标示的名称,选购元宵。一般来说,甜味元宵的主要配料包括糯米粉、变性淀粉、白砂糖等。由于糖和油的含量相对较高,建议消费者要适量食用,消化系统相对较弱的老年人和儿童更要注意食用量,糖尿病和心脑血管病等特殊疾病患者谨慎食用。

针对元宵的选购要点、食用建议、储藏方法等方面提示,已于2018年3月1日在原食品药品监管总局网站发布的《元宵节饮食安全的消费提示》中,消费者可在此链接中查看http://samr.cfda.gov.cn/WS01/CL1680/225704.html。(中国食品科学技术学会提供技术支持)