补充:集成于Spring
一.在resources目录下创建ftl路径引用文件
文件名为freemarker.properties
out_put_path=D:/IdeaProjects/czjk_parent/health_parent/health_mobile/src/main/webapp/pages
二.创建在Spring配置文件中添加集成配置
此处以provider的’spring-service.xml’为例子
要添加到配置文件中的内容:
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<!--指定模板文件所在目录-->
<property name="templateLoaderPath" value="/WEB-INF/ftl/" />
<!--指定字符集-->
<property name="defaultEncoding" value="UTF-8" />
<property name="freemarkerSettings">
<props>
<!--用于解决前端报空指针问题-->
<prop key="classic_compatible">true</prop>
</props>
</property>
</bean>
<!--加载属性文件,后期在java代码中会使用到属性文件中定义的key和value-->
<context:property-placeholder location="classpath:freemarker.properties"/>
集成后的全部内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 指定应用名称 -->
<dubbo:application name="health_service_provider"/>
<!--指定暴露服务的端口,如果不指定默认为20880-->
<dubbo:protocol name="dubbo" port="20887"/>
<!--指定服务注册中心地址-->
<dubbo:registry address="zookeeper://localhost:21321"/>
<!--批量扫描,发布服务-->
<dubbo:annotation package="cn.health.service"/>
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<!--指定模板文件所在目录-->
<property name="templateLoaderPath" value="/WEB-INF/ftl/" />
<!--指定字符集-->
<property name="defaultEncoding" value="UTF-8" />
<property name="freemarkerSettings">
<props>
<!--用于解决前端报空指针问题-->
<prop key="classic_compatible">true</prop>
</props>
</property>
</bean>
<!--加载属性文件,后期在java代码中会使用到属性文件中定义的key和value-->
<context:property-placeholder location="classpath:freemarker.properties"/>
</beans>
中文路径,注意编码格式:
<context:property-placeholder location="classpath:freemarker.properties" file-encoding="UTF-8"/>
注意,如果有多个property-placeholder,只能写在一个地方,同时用逗号进行分隔:
<context:property-placeholder location="classpath:freemarker.properties,classpath:redis.properties" file-encoding="UTF-8"/>
三.在Java类中引用FreeMarker的Spring集成对象
Freemarker介绍
FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与 Web 容
器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还
可以用于生成 XML,JSP 或 Java 等。
模板
模板文件中有四种元素:
1、文本,直接输出的部分
2、注释,即<#–…-->格式不会输出
3、插值(Interpolation):即${…}部分,
将使用数据模型中的部分替代输出
4、FTL指令:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出
Freemarker的模板文件后缀可以任意,一般建议为ftl
补充资料:
模板引擎总结(Thymeleaf,FreeMarker,Enjoy,Velocity,JSP等)
https://www.cnblogs.com/ywb-articles/p/10627398.html
准备工作
一.导入依赖Jar包
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
定义模板
定义FTL文件模板
以下模板为示例模板,仅供参考
Freemarker的模板文件后缀可以任意,一般建议为ftl
<html>
<head>
<meta charset="utf-8">
<title>Freemarker入门</title>
</head>
<body>
<#--我只是一个注释,我不会有任何输出 -->
${name}你好,${message}
</body>
</html>
定义Java代码模板
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class FreeMarkerTest {
public static void main(String[] args) throws IOException, TemplateException {
//创建freemarker的配置对象
Configuration configurationObj = new Configuration(Configuration.getVersion());
//设置模板文件所在目录
configurationObj.setDirectoryForTemplateLoading(new File("D:\\freemarker"));
//设置字符集
configurationObj.setDefaultEncoding("utf-8");
//加载模板文件,代码将会应用到该模板HTML的ftl格式文件中(格式必须为ftl,最好用Notepate++将文件编码设置为UTF-8无BOM编码格式)
Template templateObj = configurationObj.getTemplate("index.ftl");
//准备所需要给模板文件传递的数据,通常是由HashMap来封装传递.你也可以使用实体类进行封装传递
Map hashMapObj = new HashMap();
//定义要给前端传递的数据键值对
hashMapObj.put("paramname","你好,世界!Hello world" );
hashMapObj.put("password","abc123456" );
//定义输出流 输入一个用于输出成品FreeMarker的静态页面文件绝对路径,静态页面的格式必须为Html
Writer writeObj = new FileWriter("D:\\freemarker\\test.html");
//开启输出流,将成品FreeMarker作为静态页面文件进行输出
templateObj.process(hashMapObj,writeObj );
//关闭输出流
writeObj.close();
}
}
assign指令语法
变量引用语法
assign指令用于在页面上定义一个变量
<#assign linkman="周先生">
联系人:${linkman}
<#assign testname="这里是练习assign指令的语法!">
assign简单指令练习,文本内容为:${testname}
对象(Json)引用语法
经常要复用和修改的内容,就可以在页面上定义变量,这样未来只需要调整变量内容即可
<#assign info={"mobile":"13812345678",'address':'北京市昌平区'} >
电话:${info.mobile} 地址:${info.address}
<#assign objparam={"name":"研一","age":"24","address":"中国北京"}>
assign之对象数据类型引用,姓名为:${objparam.name} 年龄为:${objparam.age} 地址为:${objparam.address}
include指令
include指令用于模板文件的嵌套,即:用于导入其它ftl模板文件.类似于Js中可以导入其它js文件一样.
(1)创建模板文件head.ftl
<h1>黑马程序员</h1>
(2)修改入门案例中的test.ftl,在test.ftl模板文件中使用include指令引入上面的模板文件
<#include "head.ftl"/>
判断指令
if指令用于判断
用法一:直接判断布尔值
(1)在模板文件中使用if指令进行判断
<#--<#assign success=true>--
<#if success=true>
你已通过实名认证
<#else>
你未通过实名认证
</#if>
(2)在java代码中为success变量赋值
map.put("success", true);
在freemarker的判断中,可以使用= 也可以使用==
用法二:判断数据内容(如字符串,数值)
<#if password="abc123456">
密码正确,通过验证!
<#else>
密码错误,无法通过验证!
</#if>
用法三:判断某变量是否存在
OR.双问号’??'判断法
判断某变量是否存在使用 “??”
用法为:变量名??,如果该变量存在,返回true,否则返回false
OR.感叹号’!'文本替换法
如果变量不存在,则代替变量充填为其它内容.
普通变量用法:
例一: ${name!''}
解释:表示如果name为空,显示空字符串。
例二: ${name!'你好!'}
解释:表示如果name为空,显示’你好’字符串。
嵌套对象用法:
例一: ${(stu.bestFriend.name)!''}
如果stu或bestFriend或name为空,默认显示空字符串。
if指令补充说明
<#assign success=false>
<#if success=true>
你已通过实名认证
<#else>
你未通过实名认证
</#if>
如果JAVA代码和模板文件中都有变量,以模板文件中为主
else-if的用法:
<#if success=='0'>
男性
<#elseif success=='1'>
女性
<#else>
未知性别
</#if>
list指令之遍历List集合
很简单,用于遍历输出list集合中的数据.
范例一
ftl文件代码如下:
<#list goodsList as goods>
商品名称: ${goods.name} 价格:${goods.price}<br>
</#list>
java代码如下:
List goodsList=new ArrayList();
Map goods1=new HashMap();
goods1.put("name", "苹果");
goods1.put("price", 5.8);
Map goods2=new HashMap();
goods2.put("name", "香蕉");
goods2.put("price", 2.5);
Map goods3=new HashMap();
goods3.put("name", "橘子");
goods3.put("price", 3.2);
goodsList.add(goods1);
goodsList.add(goods2);
goodsList.add(goods3);
map.put("goodsList", goodsList);
范例二
ftl代码文件如下:
<#list arraylist as forname>
姓名:${forname.name} 年龄:${forname.age} 地址:${forname.address} <br>
</#list>
java代码如下:
Map hashMapObj = new HashMap();
ObjectForArrayList obj1 = new ObjectForArrayList("张三","15","北京");
ObjectForArrayList obj2 = new ObjectForArrayList("李四","18","南京");
ObjectForArrayList obj3 = new ObjectForArrayList("王五","21","东京");
ArrayList<ObjectForArrayList> arrayObj = new ArrayList<>();
arrayObj.add(obj1);
arrayObj.add(obj2);
arrayObj.add(obj3);
hashMapObj.put("arraylist",arrayObj );
list指令之遍历Map集合
java代码如下:
@Controller
@RequestMapping("/freemarker")
public class FreemarkerController {
@Autowired
RestTemplate restTemplate;
@RequestMapping("/test1")
public String freemarker(Map<String, Object> map){
Student studentOne = new Student();
studentOne.setName("张留章");
studentOne.setAge(25);
studentOne.setBirthday(null);
studentOne.setMoney(1000000.0F);
Student studentTwo = new Student();
studentTwo.setName("张仕聪");
studentTwo.setAge(24);
studentTwo.setBirthday(null);
studentTwo.setMoney(1000000.0F);
Map<String,Student> mapForStudent = new HashMap<>();
mapForStudent.put("studentOne",studentOne );
mapForStudent.put("studentTwo",studentTwo );
map.put("mapForStudent", mapForStudent);
//返回模板文件名称 即:返回给templates目录下的'test1'.ftl
return "test1";
}
}
ftl文件代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf‐8">
<title>Hello World!</title>
</head>
<body>
<h2>遍历Map集合中的学生对象信息</h2><br>
其中的'key'为别名.
<#list mapForStudent?keys as key>
${mapForStudent[key].name}<br>
${mapForStudent[key].age}<br>
${mapForStudent[key].money}<br>
</#list>
</body>
</html>
内建函数
一.显示集合长度
格式:${集合变量名?size}
二.显示日期
能够将Date对象转为字符串日期显示在页面.
显示年月日: ${日期变量名?date}
显示时分秒:${日期变量名?time}
显示日期+时间:${日期变量名?datetime}
自定义格式化:${日期变量名?string("yyyy年MM月")
Freemarker静态化步骤模板参考示例
基于模板文件来实现静态化
/基于模板生成静态化文件
@Test
public void testGenerateHtml() throws IOException, TemplateException {
//创建配置类
Configuration configuration=new Configuration(Configuration.getVersion());
//设置模板路径
String classpath = this.getClass().getResource("/").getPath();
configuration.setDirectoryForTemplateLoading(new File(classpath + "/templates/"));
//设置字符集
configuration.setDefaultEncoding("utf‐8");
//加载模板
Template template = configuration.getTemplate("test1.ftl");
//数据模型
Map<String,Object> map = new HashMap<>();
map.put("name","黑马程序员");
//静态化
String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
//静态化内容
System.out.println(content);
InputStream inputStream = IOUtils.toInputStream(content);
//输出文件
FileOutputStream fileOutputStream = new FileOutputStream(new File("d:/test1.html"));
int copy = IOUtils.copy(inputStream, fileOutputStream);
}
基于字符串来实现静态化
//基于模板字符串生成静态化文件
@Test
public void testGenerateHtmlByString() throws IOException, TemplateException {
//创建配置类
Configuration configuration=new Configuration(Configuration.getVersion());
//模板内容,这里测试时使用简单的字符串作为模板
String templateString="" +
"<html>\n" +
" <head></head>\n" +
" <body>\n" +
" 名称:${name}\n" +
" </body>\n" +
"</html>";
//模板加载器
StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
stringTemplateLoader.putTemplate("template",templateString);
configuration.setTemplateLoader(stringTemplateLoader);
//得到模板
Template template = configuration.getTemplate("template","utf‐8");
//数据模型
Map<String,Object> map = new HashMap<>();
map.put("name","黑马程序员");
//静态化
String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
//静态化内容
System.out.println(content);
InputStream inputStream = IOUtils.toInputStream(content);
//输出文件
FileOutputStream fileOutputStream = new FileOutputStream(new File("d:/test1.html"));
IOUtils.copy(inputStream, fileOutputStream);
}
Freemarker真实应用代码
用到三个需要注入的成员变量
model 用于获取到存储在Mongodb的‘dataUrl'的内容 如: {"id":"5a791725dd573c3574ee333f","name":"轮播图","model":[{"key":"banner1","name":"轮播图1地址","url":null,"mapValue":null,"value":"http://www.xuecheng.com/img/widget-bannerB.jpg"},{"key":"banner2","name":"轮播图2地址","url":null,"mapValue":null,"value":"http://www.xuecheng.com/img/widget-bannerA.jpg"},{"key":"banner3","name":"轮播图3地址","url":null,"mapValue":null,"value":"http://www.xuecheng.com/img/widget-banner3.png"}]} template 真的就是用于获取模板,也就是模板html代码。 思路就是将model(dataUrl链接里头请求到的参数内容),填充至template的Html代码里头。
*/
//用于将请求到的内容直接以字符串的形式返回给前端(应用于Freemarker页面静态化)
@Autowired
RestTemplate restTemplateObj;
@Autowired
GridFsTemplate gridFsTemplateObj;
@Autowired
GridFSBucket gridFSBucketObj;
//静态化
public String getPageHtml(String pageId){
//获取数据模型
Map model = this.getModelByPageId(pageId);
if (model==null){
ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_DATAISNULL);
}
//获取模板
String templateByPageId = this.getTemplateByPageId(pageId);
//判断是否为空
if (StringUtils.isEmpty(templateByPageId)){
ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_TEMPLATEISNULL);
}
//执行静态化
String s = this.genereteHtml(templateByPageId, model);
return s;
}
//获取模型数据
private Map getModelByPageId(String pageId){
//取出页面的信息
CmsPage cmsPageObj = getById(pageId);
if (cmsPageObj==null){
ExceptionCast.cast(CmsCode.CMS_PAGE_NOTEXISTS);
}
//判断是否存在dataUrl
String dataUrl = cmsPageObj.getDataUrl();
if (StringUtils.isEmpty(dataUrl)){//如果为空
//不存在则触发可预知异常
ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_DATAURLISNULL);
}
ResponseEntity<Map> forEntity = restTemplateObj.getForEntity(dataUrl,Map.class );
Map body = forEntity.getBody();
return body;
}
//获取页面模板
private String getTemplateByPageId(String pageId){
CmsPage cmsPage = this.getById(pageId);
if (cmsPage==null){
ExceptionCast.cast(CmsCode.CMS_PAGE_NOTEXISTS);
}
//判断页面模板是否为空
String templateId = cmsPage.getTemplateId();
if (StringUtils.isEmpty(templateId)){
ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_TEMPLATEISNULL);
}
//根据模板Id查询模板集合,获取模板信息
Optional<CmsTemplate> optionalObj = cmsTemplateRepositoryObj.findById(templateId);
if (optionalObj.isPresent()){
CmsTemplate cmsTemplate = optionalObj.get();
//根据模板id获取文件id(templateFileId)
String templateFileId = cmsTemplate.getTemplateFileId();
//根据模板文件id来取出文件内容 //此处Query.query所查询的集合是fs.files
GridFSFile gridFSFileObj = gridFsTemplateObj.findOne(Query.query(Criteria.where("_id").is(templateFileId)));
//打开一个下载流
GridFSDownloadStream gridFSDownloadStreamObj = gridFSBucketObj.openDownloadStream(gridFSFileObj.getObjectId());
//创建GridFsResource
GridFsResource gridFsResource = new GridFsResource(gridFSFileObj,gridFSDownloadStreamObj );
try{
String content = IOUtils.toString(gridFsResource.getInputStream());
return content;//将获取到的模板内容(即html代码)返回
}catch (Exception e){
e.printStackTrace();
}
}
return null;
}
//执行静态化
private String genereteHtml(String template,Map model){
try{
//创建模板加载配置器
Configuration configurationObj = new Configuration(Configuration.getVersion());
//Freemarker的模板加载器
StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
stringTemplateLoader.putTemplate("template",template );
//配置模板加载器
configurationObj.setTemplateLoader(stringTemplateLoader);
//获取模板
Template templateObj = configurationObj.getTemplate("template");
String html = FreeMarkerTemplateUtils.processTemplateIntoString(templateObj, model);
return html;
}catch (Exception e){
e.printStackTrace();
}
return null;
}