一、背景

最近公司有业务,需要传递数据将其生成静态HTML,然后HTML可转PDF,也可打印。网上查阅了一下freemarker,颇感兴趣,
学习使用后,记录过程,方便回顾,同时也希望能帮到各位猿友。

二、涉及技术

freemarker、springboot、lodop、itext

三、业务步骤

1.freemarker的maven依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

2.freemarker的配置(我用的是yml文件)

# 配置数据源
spring:freemarker:allow-request-override: falsecache: falsecheck-template-location: truecharset: UTF-8content-type: text/htmlexpose-request-attributes: falseexpose-session-attributes: falseexpose-spring-macro-helpers: falsesuffix: .htmlsettings:default_encoding: UTF-8enabled: truerequest-context-attribute: rctemplate-path : D:/yxhData/staticData/res/template/html

其中template-path为模版的路径

3.freemarker的宏

import java.io.IOException;
import java.util.Map;import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;import com.chongdong.common.exception.APIException;
import com.chongdong.common.util.JacksonUtils;
import com.chongdong.common.util.freemarker.Freemarker;
import com.chongdong.data.entity.OrdBase;
import com.chongdong.data.entity.OrdExtend;
import com.chongdong.service.order.biz.OrdBaseBiz;import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.WrappingTemplateModel;
/*** 订单宏* @author yanxh**/
@Repository
public class OrderDetail implements TemplateDirectiveModel {@Autowiredprivate OrdBaseBiz ordBaseBiz;/*** @param env 系统环境变量,通常用它来输出相关内容,如Writer out = env.getOut();* @param map 自定义标签传过来的对象,其key=自定义标签的参数名,value值是TemplateModel类型,而TemplateModel是一个接口类型,通常我们都使用TemplateScalarModel接口来替代它获取一个String 值,如TemplateScalarModel.getAsString();当然还有其它常用的替代接口,如TemplateNumberModel获取number,TemplateHashModel等* @param loopVars 循环替代变量* @param body 用于处理自定义标签中的内容;当标签是<@myDirective />格式时,body=null*/@Overridepublic void execute(Environment env, Map map, TemplateModel[] loopVars,TemplateDirectiveBody body) throws TemplateException, IOException {/*** 订单ID字符串*/Long orderId = Freemarker.getLong(map, "orderId");/*** 获取订单信息*/OrdBase ordBase = null;try {ordBase = ordBaseBiz.getDetail(orderId);} catch (APIException e) {e.printStackTrace();}/*** 获取dataJson*/Map<String, Object> jsonMap = null;try {OrdExtend ordExtend = ordBase.getOrdExtend();if(ordExtend != null) {String dataJson = ordExtend.getDataJson();if(!StringUtils.isBlank(dataJson)) {jsonMap = JacksonUtils.json2map(dataJson);}}} catch (Exception e) {e.printStackTrace();}loopVars[0]=WrappingTemplateModel.getDefaultObjectWrapper().wrap(ordBase);loopVars[1]=WrappingTemplateModel.getDefaultObjectWrapper().wrap(jsonMap);body.render(env.getOut()); }}

这是一个订单详情的宏定义,参数为订单的ID,返回值为订单详细信息和订单扩展信息

4.freemarker的配置类

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;import javax.annotation.PostConstruct;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;import com.chongdong.service.order.biz.macro.OrdBatchDetail;
import com.chongdong.service.order.biz.macro.OrdBatchDetailWithField;
import com.chongdong.service.order.biz.macro.OrderDetail;import freemarker.template.Configuration;
import freemarker.template.TemplateModelException;@org.springframework.context.annotation.Configuration
public class FreemarkerConfig {@Autowiredprivate Configuration configuration;@Autowiredprivate OrderDetail orderDetail;@Autowiredprivate OrdBatchDetail ordBatchDetail;@Autowiredprivate OrdBatchDetailWithField ordBatchDetailWithField;@Value("${spring.freemarker.template-path}")private String templateLoaderPath; // 模板物理路径@PostConstructpublic void setSharedVariable() throws TemplateModelException {configuration.setSharedVaribles(getSharedVaribles());configuration.setClassicCompatible(true); // 处理页面空值// 使用物理地址作为模版路径try {configuration.setDirectoryForTemplateLoading(new File(templateLoaderPath));} catch (IOException e) {e.printStackTrace();}}public Map<String, Object> getSharedVaribles() {Map<String, Object> sharedVaribles = new HashMap<String, Object>();sharedVaribles.put("_order", orderDetail);sharedVaribles.put("_ordBatch", ordBatchDetail);sharedVaribles.put("_ordBatchWithField", ordBatchDetailWithField);return sharedVaribles;}}

配置类设置freemarker的一些参数,同时将宏加入到配置中

5.模版

<!DOCTYPE HTML>
<html>
<head><meta charset="utf-8" /><link rel="stylesheet" href="../../res/css/reset.css" type="text/css" media="screen" /><script type="text/javascript" src="../../res/js/jquery-1.9.1.min.js"></script>
</head>
<body><div class="printList_box"><#list orderIds?split(",") as orderId><@_order orderId="${orderId}"; ordBase, jsonMap><div class="pb_logo"><img src="../../res/images/Buyers/pb_logo.png" /></div><h2 class="plb_h2">${ordBase.orgName}电子签收单</h2><table class="plb_table"><tr><td class="plb_td_w10">订单编号</td><td>${ordBase.id?c}</td><td class="plb_td_w10">订单金额</td><td class="plb_td_w10" colspan="2">¥${ordBase.amount?c}</td></tr><tr><td class="plb_td_w10">报销批次</td><td>${batchNo}</td><td class="plb_td_w10">采购时间</td><td colspan="2">${ordBase.createTime?string('yyyy-MM-dd HH:mm:ss')}</td></tr><tr><td class="plb_td_w10">采购人(学号)</td><td>${ordBase.buyerName}(${jsonMap.buyerNo})</td><td class="plb_td_w10">所属实验室</td><td colspan="2">${jsonMap.byraccountDep}</td></tr><tr><td class="plb_td_w10">实验室负责人(工号)</td><td>${jsonMap.byraccountDirect2UerName}(${jsonMap.byraccountDirect2UerNo})</td><td class="plb_td_w10"></td><td colspan="2"></td></tr><tr class="y_tr_h50"><td class="plb_td_w10">收货地址</td><td colspan="4">${ordBase.ordAddress.provinceName}${ordBase.ordAddress.cityName}${ordBase.ordAddress.address}</td></tr><tr><td class="plb_td_w10">供应商名称</td><td>${ordBase.prvName}</td><td class="plb_td_w10">经费出处</td><td colspan="2">${jsonMap.byraccountName}</td></tr><tr><td class="plb_td_w10">商品编号</td><td class="plb_td_w10">商品名称</td><td class="plb_td_w10">数量</td><td class="plb_td_w10">单价</td><td class="plb_td_w10">小计</td></tr><#list ordBase.ordProducts as prd><tr><td>${prd.code}</td><td>${prd.name}&nbsp;&nbsp;&nbsp;${prd.nameEnglish}</td><td>${prd.prodCount?c}</td><td>¥${prd.tradePrice?c}</td><td>¥${(prd.prodCount * prd.tradePrice)?c}</td></tr></#list><tr class="td_b_none"><#list jsonMap.approvalPoints as node><td>${node.approvalOrg}:${node.approvalerName}<br />${node.approvalTime!''}</td></#list><td>签收人:${jsonMap.signerName}<br />${jsonMap.signTime!''}</td></tr></table><br/><br/></@_order></#list></div>
</body>
</html>
<style>body{font-family:SimSun}.printList_box{width: 90%;margin: 0 auto;height: auto;position: relative;padding-bottom: 50px;}.plb_h2{text-align: center;line-height: 40px;font-size: 20px;padding-top: 20px;font-weight: bold;}.plb_table{width: 100%;border-collapse:collapse;}.plb_table tr{}.plb_table tr td{text-align: center;border: 1px solid #ccc;font-size: 12px;line-height: 16px;padding: 5px;word-break: break-all;word-wrap:break-word;}.plb_table tr.td_b_none td{border: none;text-align: left;}.plb_table tr.plb_tr01{height: 28px;}.plb_table tr.plb_tr01 td{font-size: 14px;font-weight: bold;text-align: left;border: none;}.plb_table tr.plb_tr02{height: 34px;}.plb_table tr td.b_r_none{border-right: none;}.plb_table tr td.b_l_none{border-left: none;}.table_Remarks{width: 100%;padding: 50px 0;font-size: 14px;line-height: 24px;}.plb_td_w70{width: 70px;}.plb_td_w100{width: 100px;}.plb_td_w10{width: 120px;}.plb_purpose{width: 90%;height: 100%;padding-left: 5%;text-align: left;}.plb_box{padding: 10px;}.plb_text_p01{height: 100px;text-align: left;}.plb_text_p02{text-align: right;}.plb_text_p02 span{display: inline-block;padding: 0 50px 0 100px;}.Total_box{width: 100%;height: auto;}.Total_box p{line-height: 40px;text-align: right;}.Total_box div{}.Total_box div span{float: left;display: inline-block;width: 18%;font-weight: bold;font-size: 14px;}.Total_box div em{float: right;font-weight: bold;font-size: 14px;}.pb_left{position: absolute;left: -20px;top: 88px;width: 10px;}.pb_right{position: absolute;right: -20px;top: 88px;width: 10px;}.pb_logo{position: absolute;right: 0;top: 20px;width: 170px;opacity: 0.7;}.pb_logo img{display: block;width: 100%;}.pb_right span{padding-bottom: 20px;}.plb_com_text{width: 200px;}.plb_table tr td.pb_ta_left{text-align: left;font-weight: bold;}.pb_data_box{width: 150px;}.pb_data_box span{display: inline-block;width: 50px;text-align: left;font-weight: bold;}.ys_box01{text-align: left;padding: 20px 0 20px 20px;overflow: hidden;}.ys_box01 span{float: left;padding: 0 5px;margin-right: 20px;}.ys_box01 input{float: left;margin-top: 3px;}.ys_box02{text-align: left;padding-bottom: 50px;padding-left: 20px;}.ys_box02 p{padding: 10px 0;}.ys_box02 span{float: left;padding-right: 20px;}.ys_box02 input{float: left;margin-top: 3px;margin-right: 5px;}.ys_box02 font{display: inline-block;padding: 0 200px 100px 0;}.y_tr_h50{height: 50px;}
</style>

6.生成html

 /*** 生成html* @param freemarkerCfg freemarker的默认配置* @param data 需要传递至模版页面的参数* @param templatePath 模版页面的名称* @param htmlPath 生成HTML的存放路径* @throws TemplateNotFoundException* @throws MalformedTemplateNameException* @throws ParseException* @throws IOException* @throws TemplateException*/public static void createHTML(Configuration freemarkerCfg,Map<String,Object> data,String templatePath,String htmlPath) throws TemplateNotFoundException,MalformedTemplateNameException, ParseException, IOException, TemplateException{Template template = freemarkerCfg.getTemplate(templatePath,"UTF-8");File htmlFile = new File(htmlPath);if(!htmlFile.getParentFile().exists()) {htmlFile.getParentFile().mkdirs();}Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(htmlFile), "UTF-8"));template.process(data, out);out.flush();out.close();}

四、过程讲解

调用接口调试工具(我用的是自己搭建的swagger,具体步骤可参考5分钟学会swagger配置-中文界面配置,也可使用postman)访问接口调用第6步的方法,模版接到请求后开始向指定路径输出静态页面,期间调用宏查询相关数据。

使用Freemarker的宏和模板生成html打印相关推荐

  1. itextword加公章 java_使用itext和freemarker来根据Html模板生成PDF文件,加水印、印章...

    org.xhtmlrenderer flying-saucer-pdf-itext5 9.1.18 org.freemarker freemarker 2.3.27-incubating 将html模 ...

  2. freemarker 生成java_半自动化Java代码生成器[利用freemarker模板生成]

    rapid-generator 半自动化Java代码生成器[利用freemarker模板生成] 增加一些定制和扩展, 修改为基于MAVEN的格式. 整体架构保持不变. 增加的特性为: 支持表名前缀去除 ...

  3. 利用Freemarker模板生成doc或者docx文档(转载整理)

    可以直接看主要代码实现 doc作为模板文件生成指定格式的doc文件 实现逻辑 1.把作为模板的doc文件另存为xml文件 2.凡是需要填充的数据用${xxxx}替代 3.利用Template类将数据填 ...

  4. springmvc下解析模板生成Excel ,用freemarker

    工具类解析模板生成Excel public class TemplateParseUtil {/** * 解析模板生成Excel * @param templateDir 模板目录 * @param ...

  5. 利用 freemarker 模板生成 word 小结

    在企业级开发时,不可避免的会遇到生成 word 文档的需求,有两种常用的方案,1.使用 Apache POI 在后台通过代码生成 word 文档:2.使用模板生成 word 文档.第二种方法比较简单, ...

  6. freemarker根据模板生成word文档,换行

    freemarker根据模板生成word文档,其它地方已经说的非常清除了,在此简单再说以下. 1.制作word模板,另存为xml文件.在此我另存为的时windows xml,它和windows 200 ...

  7. Freemarker模板生成排版缩进问题

    在将Freemarker作为模板使用时,生成的目标文件(HTML或xml或其他类型文件)时,往往会出现排版错乱的问题. 主要是:明明没有那么多占位符或缩进,但生成出来的文件却有对应的缩进. 类似下图效 ...

  8. springboot结合Freemarker模板生成docx格式的word文档(附代码)

    首先参考的是这篇文章: java利用Freemarker模板生成docx格式的word文档(全过程) - 旁光 - 博客园参考:https://my.oschina.net/u/3737136/blo ...

  9. JavaWeb(14) 页面静态化之使用freemarker模板生成一个html静态页面

    题外话:        页面静态化(展示数据从JSP页面变成HTML页面)实现方式-->模板技术   从本质上来讲,模板技术是一个占位符动态替换技术.一个完整的模板技术需要四个元素:①模板语言( ...

最新文章

  1. 清理服务器,不可不知的两个指令
  2. Linux挂载iscsi存储
  3. VMware快照管理器
  4. 洛谷3605 Promotion Counting
  5. Spark _24 _读取JDBC中的数据创建DataFrame/DataSet(MySql为例)(三)
  6. R语言和 Python —— 一个错误的分裂
  7. mesh和wifi中继的区别_深度解读Mesh路由和无线中继的差异,谁才是性价比之选?...
  8. php实现身份证号码获取归属地地址的实列教程,含完整全国地区归属数据!
  9. Silverlight+WCF+ArcObjects获取地图服务图层列表的实现
  10. Android内核开发:图解Android系统的启动过程
  11. SpringBoot中Interceptor和Filter的使用
  12. oracle卸载报错,oracle卸载
  13. 鱼类放流标记 PIT鱼类无线射频标记设备|读卡器
  14. 微信小程序--几个常用标签
  15. aws-sdk for JavaScript 官方api文档
  16. GDELT数据库入门与了解(码字中...)
  17. 雨落无声-开博啦........
  18. seacms海洋cms漏洞
  19. 41-fcntl设置文件锁
  20. [code] PTA 胡凡算法笔记 DAY003

热门文章

  1. 设计模式(Java)----装饰模式Decorator
  2. HMI-4-[Qt超内存]:解决qrc文件过大问题
  3. eps倾斜摄影矢量化采集毕业设计_eps倾斜摄影量化dlg采集.doc
  4. 一文搞懂UART通信协议
  5. 超级浏览器的技术原理,超级浏览器的浏览器指纹是什么?
  6. 一篇带你搞懂 java 集合
  7. C# Socket模拟发送接收
  8. Red Hat Enterprise Linux (RHEL) 8.5 发布(含下载)
  9. 强大的版本管理工具 Git
  10. 快递鸟全球物流单号查询api接口