还是首先讲一下需求。一个普通的web form表单提交,根据模板自动生成指定格式的结果。form的优势在格式化数据,使得各属性非常直观的展现出来,用户可以更加简单直观的进行输入。但业务上的最终结果却不可以是form,所以就有了这个需求。需求的本质有点类似el表达式的替换,但是这个表达式模板是动态配置的,而不是常见的xml静态文件。

总结一下需求,概括来讲是这样:根据用户的输入,将业务属性填充到实时设置的模板生成最终结果。

不难发现这里的几个关键点。

  1. 模板要实时可以配置,这里采用db方式。
  2. 存在用户输入的行为,也就意味着存在不稳定因素,包括特殊字符,空等。但是因为是填充,可以过滤掉特殊字符,只要处理null即可。(需求上需要处理null)
  3. 既然是填充,就要保证两点。一是填充的对象不能混淆错乱,二是填充的顺序不能出错。
  4. 该模板是当做第三方jar依赖注入的,所以必须规避掉任何业务因素。
想清楚了设计的重点,再来看看设计,先看类图。
实体层:
TemplateEl:el表达式的设计。因为只是简单的文本模板,所以只要关心el的前缀、后缀即可。这里的html配置是为了前台效果展示、编辑用的。propertyMethod是考虑到不同系统、程序员在声明getter、setter方法时可能不一致,所以显示表达了。
TemplateElFormat:针对特殊el属性,有一定的格式约定。我目前只用到了时间格式,后面会有介绍。
Template:常见的group+unique code 唯一标示模板。
TemplateElConfig:就是一张普通的mapping表。
ResultVo:根据业务需求返回指定的VO。这里建议用一个Abstract类来为模板服务。

Service层:

TemplateFactory:常规的工厂类,获取指定生成器。

TemplateGenerator:常规的生成器。

还是老话,结构jar提供,实现在业务层。包括vo。这样的好处是jar与业务完全隔离。坏处是每个业务系统都要写一遍实现,而且存在冲突的风险。

下面补上实现类的generator实现,其他代码没什么特别。

1. Exception是模板jar封装过的几类异常。因为不存在业务代码,所以无法控制调用方的传参,模板可能会不存在。

     //1. 获取模板Template template = this.templateLogic.findByGroupAndCode(groupCode, templateCode);if (null == template) {logger.info("Invalid template access. group code:{}, template code:{}", groupCode, templateCode);result.setException(new TemplateNotExistException("Template not exists! Group code:" + groupCode + ",template code:" + templateCode) );return;}

2. 读取模板配置的el。如果没有任何配置,warning。这里按seq读取,为模板拼接做准备。

     //2. 读取模板配置List<TemplateElConfig> templateElConfigs = this.templateElConfigLogic.findByTemplateId(template.getId());if (null == templateElConfigs || templateElConfigs.isEmpty() ) {logger.info("There's no express configuration for template:{}", template.getName());return;}

3. 解析el的配置,生成最终字符串。

     for (TemplateElConfig templateElConfig : templateElConfigs) {TemplateEl el = this.templateElLogic.findOne(templateElConfig.getElId());if (el == null) {logger.info("Missing el config, template el config id:{}",templateElConfig.getId());continue;}String datasourceValue = "";//3.1 String methodName = el.getPropertyMethod();if (StringUtils.isEmpty(methodName)) {logger.info("Missing property method config for el:{}",el.getId());continue;}try {Method method = null;Object propertyValue;if (el.getEl().contains("Date")) {method = (Method)datasource.getClass().getMethod(methodName);propertyValue = (Date)method.invoke(datasource);}else {method = (Method)datasource.getClass().getMethod(methodName);propertyValue = (String)method.invoke(datasource);}if (propertyValue instanceof Date) {TemplateElFormat elFormat = this.templateElFormatLogic.findByElId(el.getId());String timeFormat = DEFAULT_DATE_FORMAT;if (null != elFormat) {timeFormat = elFormat.getFormat();}SimpleDateFormat format = new SimpleDateFormat(timeFormat);datasourceValue = format.format(propertyValue);}else if (propertyValue instanceof String) {datasourceValue = (String)propertyValue;}} catch (Exception e) {logger.error("No such method.", e);result.setException(new IllegalTemplateConfigException("No such method.", e));return;}if (StringUtils.isNoneEmpty(datasourceValue)) {if (StringUtils.isNoneEmpty(el.getPrefix())) {buffer.append(el.getPrefix());}buffer.append(datasourceValue);if (StringUtils.isNotEmpty(el.getSuffix())) {buffer.append(el.getSuffix());}if (StringUtils.isNoneEmpty(el.getHtmlPrefix())) {htmlBuffer.append(el.getHtmlPrefix());}htmlBuffer.append(datasourceValue);if (StringUtils.isNotEmpty(el.getHtmlSuffix())) {htmlBuffer.append(el.getHtmlSuffix());}}}

这里没有业务逻辑,所以是可以放到jar里面的,各业务系统只要控制如何结构化调用就行了。

Java自定义模板设计相关推荐

  1. java运费模板设计_猿实战17——实现你未必知晓的运费模板

    猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,变身猿人找到工作不是问题.还等什么呢?关注公号,取基 ...

  2. java运费模板设计_电商系统设计之运费模板(上)

    电商大伙每天都在用,类似某猫,某狗等. 电商系统设计看似复杂又很简单,看似简单又很复杂 本章适合初中级工程师细看,大佬请随意 前言 在订单系统中,运费模板是其中一个重要组成部分,看似简单的一个设置,在 ...

  3. java运费模板设计_电商系统设计之运费模板(下)

    电商大伙每天都在用,类似某猫,某狗等. 电商系统设计看似复杂又很简单,看似简单又很复杂 本章适合初中级工程师细看,大佬请随意 前言 在订单系统中,运费模板是其中一个重要组成部分,看似简单的一个设置,在 ...

  4. java运费模板设计,拼多多运费模板怎么设置

    运费模版的设置尤为重要,常常有商家朋友们来咨询运费模板在哪里设置?运费模板怎么设置?运费模板设置好了要如何使用呢?为什么明明设置好了,买家却购买不了?本章节将会统统告诉您哦! 一.什么是运费模版 1. ...

  5. java自定义字段_自定义字段的设计与实现(Java实用版)

    前言 自定义字段又叫做"开放模型",用户可以根据自已的需求,添加需要的字段,实现个性化定制. 使用自定义字段的目的,使用自定义字段解决哪些问题 如现有一套CRM系统,客户模块中客户 ...

  6. Java报表工具技巧--Style Report报表套打模板设计

    在报表软件和报表工具领域,报表套打是最为常见的一个用户需求,例如发票.支票.信封.对账单.保单以及各类证件表格的打印都需要根据既定的表格样式快速批量打印出结果.报表套打功能也是各种报表工具必备的功能之 ...

  7. 可以自定义模板的ide_将IDE检查应用于自定义Java批注

    可以自定义模板的ide J2SE 5中注释的引入改变了我们编写和处理Java的方式. 除了Java SE的预定义注释外 ,框架,IDE和工具包还引入了自己的自定义注释 . Checker框架提供了一些 ...

  8. Python+django网页设计入门(18):自定义模板过滤器

    前导课程: Python+django网页设计入门(17):模板语法及应用 Python+django网页设计入门(16):优化设计复用分页代码 Python+django网页设计入门(15):公用模 ...

  9. java高级课程设计报告书_java高级课程设计报告模板

    java高级课程设计报告模板 Java 高级课程设计报告 课程设计名称:Java高级课程设计 学 期:13-14-1 班 级:计网1231班 姓 名:黄磊 指 导 老 师:刘志生.白党强 一.课程设计 ...

最新文章

  1. 产品经理跪求程序员修改需求
  2. jquery检验身份证规则
  3. Centos新建系统用户详解
  4. Oppoa7手机怎么录视频 oppo手机屏幕录制
  5. SpringToolsSuite (STS)或Eclipse安装gradle
  6. AT3913-XOR Tree【状压dp】
  7. ctfmon是什么启动项_启动项里ctfmon是什么意思,干什么用的??
  8. iOS在app里面跳转到系统的设置界面
  9. linux salt命令 -e,Linux记录-salt命令
  10. RADIUS实验(802.1x)
  11. docker阿里云镜像加速器
  12. Python Pytest自动化测试 获取测试用例执行结果
  13. 有关Intel主板驱动静默安装的一个坑
  14. embed实现PDF文件预览
  15. java中put是什么意思_关于java:请求参数和PUT方法
  16. [折腾日记]win10 ,ubuntu双系统安装避坑指南
  17. 文治者必有武备不然长大了挨欺负_有文事者必有武备,有武备者必有文事。
  18. 华为MatePad 2和MatePad Pro 2的区别
  19. 《数据库原理》实验报告DB3——数据完整性与安全性控制
  20. 小王梦游记四----------隐形天使

热门文章

  1. C++ 封装 信息隐藏
  2. 因为取了个快递我搞懂了五种网络IO模型
  3. 数字报刊平台php,现代快报多媒体数字报刊平台
  4. 采用Java编写一个软件,100以内的口算题,加减运算,运算结果位于[0,100]区间内,要求自动生成题库,实现自动判分,自动生成成绩,并且有图形化CUI界面
  5. STM32F429 13. SPI 通讯(code)
  6. 2.SQL的CRUD操作
  7. 什么是GPU云服务器,有哪些优势,适用于什么场景?
  8. Fzu 2206 函数求解【规律】
  9. java h5在线音频_H5 录音音频可视化
  10. 教你十分钟在Linux系统上快速装机并安装Ansible