Freemarker
Freemarker是一个用Java开发的模板引擎,用来生成输出文本的工具
模板+数据模型=输出
1、数据模型
基本类型、List、Map、Pojo等复杂类型。
工作原理:
pom中添加freemarker跟common-io依赖
yml文件中配置freemarker
后台拼接完数据后返回模板文件名称(test)
例如:
return "test1";
,访问该controller,会访问test1.ftl页面自动填充数据
代码实现:
使用freemarker中的Configuration类获取到模板文件,接口获取到数据模型map,然后利用
String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
将数据静态化,然后利用common-io包中的IOUtils将HTML数据文件输出即可
指令:
1、注释:<#‐‐和‐‐>
2、取值:即${内容}部分
3、FTL指令:
循环:名字前加#予以区分,例如:<#list stus as stu>遍历该集合
_index:得到循环的下标,使用方法是在stu后边加"_index",它的值是从0开始,例如:${stu_index + 1}
判断:if判断,例如:<#if stu.name =='小明'>style="background:red;"</#if>
空值处理:
判断某变量是否存在:<#if stus??> 如果该变量存在返回true,否则返回false
${name!''}表示如果name为空显示空字符串。
内建函数:
日期格式化:
显示年月日: ${today?date}
显示时分秒:${today?time}
显示日期+时间:${today?datetime}
自定义格式化: ${today?string("yyyy年MM月")}
具体代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello World!</title> </head> <body> <#--取值--> Hello ${name}! <br/> <table> <tr> <td>序号</td> <td>姓名</td> <td>年龄</td> <td>钱包</td> </tr> <#--遍历list集合stus--> <#list stus as stu> <tr> <#--_index:得到循环的下标,从0开始--> <td>${stu_index + 1}</td> <td <#if stu.name =='小明'>style="background:red;"</#if>>${stu.name}</td> <td>${stu.age}</td> <td>${stu.mondy}</td> </tr> </#list> </table> <br/><br/> 输出stu1的学生信息:<br/> <#--输出map集合stuMap中的stu1内容--> 姓名:${stuMap['stu1'].name}<br/> 年龄:${stuMap['stu1'].age}<br/> 输出stu1的学生信息:<br/> <#--遍历对象stu1--> 姓名:${stu1.name}<br/> 年龄:${stu1.age}<br/> 遍历输出两个学生信息:<br/> <table> <tr> <td>序号</td> <td>姓名</td> <td>年龄</td> <td>钱包</td> </tr> <#--遍历map集合stuMap--> <#list stuMap?keys as k> <tr> <td>${k_index + 1}</td> <td>${stuMap[k].name}</td> <td>${stuMap[k].age}</td> <td>${stuMap[k].mondy}</td> </tr> </#list> </table> </br> <table> <tr> <td>姓名</td> <td>年龄</td> <td>出生日期</td> <td>钱包</td> <td>最好的朋友</td> <td>朋友个数</td> <td>朋友列表</td> </tr> <#--判断某变量是否存在使用“??”--> <#if stus??> <#list stus as stu> <tr> <#--给变量设置默认值使用 “!”,当变量为空时显示默认值。--> <td>${stu.name!''}</td> <td>${stu.age}</td> <td>${(stu.birthday?date)!''}</td> <td>${stu.mondy}</td> <#--如果stu或bestFriend或name为空默认显示空字符串。--> <td>${(stu.bestFriend.name)!''}</td> <#--查询某个集合的大小--> <td>${(stu.friends?size)!0}</td> <td> <#if stu.friends??> <#list stu.friends as firend> ${firend.name!''}<br/> </#list> </#if> </td> </tr> </#list> </#if> </table> <br/> <#--将json字符串text转成对象data--> <#assign text="{'bank':'工商银行','account':'10101920201920212'}" /> <#assign data=text?eval /> 开户行:${data.bank} 账号:${data.account} </body> </html>
代码效果:
项目运用
模板信息存储在MongoDB数据库,模板文件存储在GridFS文件系统中
需求:cms系统为了实现快速根据用户需求修改页面内容并上线的需求
以前:之前都是由开发者人工编写html及JS文件,CMS系统是通过程序自动化对页面内容进行修改,通过页面静态化技术生成html页面
如何实现:一个页面等于模板加数据,在添加页面的时候我们选择了页面的模板
具体流程:
1、获取模型数据,先知道数据模型的结构才可以编写模板
2、制作模板
3、将模型和模板组成的页面进行静态化
4、将静态化生成的html页面存放文件系统GridFS中
5、将存放在文件系统中的html文件发布到服务器
如何获取页面的数据模型?
在编辑页面信息时指定一个DataUrl,此url基于Http方式,cms通过Http远程调用的方法请求DataUrl获取数据模型
此页面是轮播图页面,它的DataUrl由开发轮播图管理的前端来提供
DataUrl就是一个请求后端数据的接口,该接口查询数据库获取数据模型
页面静态化流程:
1、静态化程序首先读取页面获取DataUrl
2、静态化程序远程请求DataUrl得到数据模型
3、获取页面模板
4、执行页面静态化
DataUrl:
"dataUrl" : "http://localhost:31001/cms/config/getmodel/5a791725dd573c3574ee333f"
为什么要使用远程请求?
前端是使用ajax去请求接口,后端不同模块之间的调用就会使用到远程调用
远程请求接口:
使用OkHttpClient完成http请求
具体流程:
1、pom中添加okhttp依赖
2、在SpringBoot启动类中配置 RestTemplate
3、调用RestTemplate的getForEntity方法即可请求url获取参数
ResponseEntity<Map> forEntity = restTemplate.getForEntity ("http://localhost:31001/cms/config/get/5a791725dd573c3574ee333f", Map.class);
GridFS介绍
GridFS是MongoDB提供的用于持久化存储文件的模块,CMS使用MongoDB存储数据,使用GridFS可以快速集成开发
工作原理:
GridFS存储文件是将文件分块存储,文件会按照256KB的大小分割成多个块进行存储
GridFS使用两个集合(collection)存储文件,一个集合是chunks, 用于存储文件的二进制数据
一个集合是files,用于存储文件的元数据信息(文件名称、块大小、上传时间等信息)
1、存文件
通过文件输入流读取到该文件
然后使用GridFsTemplate的store方法存储文件
ObjectId objectId = gridFsTemplate.store(fileInputStream, "index_banner.ftl");
存储原理说明:
文件存储成功得到一个文件id
此文件id是fs.files集合中的主键
可以通过文件id查询fs.chunks表中的记录,得到文件的内容
2、读取文件
定义Mongodb的配置类MongoConfig
使用GridFsTemplate中findOne获取到该文件内容
使用GridFSBucket中openDownloadStream获取流对象数据
3、删除文件
通过主键id使用GridFsTemplate中delete删除文件
整个页面静态化的流程:
1、在编辑cms页面信息界面填写DataUrl,将此字段保存到cms_page集合中
2、静态化程序获取页面的DataUrl—通过pageId获取到该DataUrl字段
3、静态化程序远程请求DataUrl获取数据模型
4、静态化程序获取页面的模板信息
5、执行页面静态
通过id到cmsPage表中找到DataUrl字段
通过restTemplate请求dataUrl获取数据
通过id到cmsPage表中找到TemplateId字段
通过TemplateId到CmsTemplate表中找到模板文件TemplateFileId字段
通过TemplateFileId到fs.files表获取到模板文件
通过generateHtml方法执行静态化
其中重要的方法:String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);,传模板文件和模板数据
最后将该方法返回的结果返回;
页面预览开发:
页面在发布前增加页面预览的步骤,方便用户检查页面内容是否正确
页面预览流程:
1、用户进入cms前端,点击“页面预览”在浏览器请求cms页面预览链接
2、cms根据页面id查询DataUrl并远程请求DataUrl获取数据模型
3、cms根据页面id查询页面模板内容
4、cms执行页面静态化
5、cms将静态化内容响应给浏览器
6、在浏览器展示页面内容,实现页面预览的功能
环境配置:
1、pom中引入freemarker依赖
2、在application.yml中配置freemarker
创建CmsPagePreviewController类,用于页面预览;
将静态化后的数据输出到浏览器:
ServletOutputStream outputStream = response.getOutputStream(); outputStream.write(pageHtml.getBytes("utf‐8"));
通过nginx代理进行页面预览:
1、虚拟主机配置:
#页面预览 location /cms/preview/{ proxy_pass http://cms_server_pool/cms/preview/; }
2、配置cms_server_pool将请求转发到cms:
#cms页面预览 upstream cms_server_pool{ server 127.0.0.1:31001 weight=10; }
重启Nginx
从cms_page找一个页面进行测试。注意:页面配置一定要正确,需设置正确的模板id和dataUrl。 在浏览器打开:http://www.xuecheng.com/cms/preview/5a795ac7dd573c04508f3a56 5a795ac7dd573c04508f3a56:轮播图页面的id