Java自定义模板设计

还是首先讲一下需求。一个普通的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里面的,各业务系统只要控制如何结构化调用就行了。

时间: 2024-10-08 21:55:17

Java自定义模板设计的相关文章

WPF Step By Step 自定义模板

WPF Step By Step 自定义模板 回顾 上一篇,我们简单介绍了几个基本的控件,本节我们将讲解每个控件的样式的自定义和数据模板的自定义,我们会结合项目中的具体的要求和场景来分析,给出我们实现的方案和最终的运行效果. 本文大纲 1.控件模板及数据模板 2.ListBox深度定制模板. 3.TreeView高级模板使用实例. 控件模板及数据模板 控件模板 什么是控件模板,指定可以在控件的多个实例之间共享 Control 的可视结构和性能方面的方面.控件模板其实就是我们在可视方面的自定义模板

前端学PHP之自定义模板引擎

什么是网站模板?准确地说,是指网站页面模板,即每个页面仅是一个板式,包括结构.样式和页面布局,是创建网页内容的样板,也可以理解为已有的网页框架.可以将模板中原有的内容替换成从服务器端数据库中动态内容,目的是可以保持页面风格一致 PHP是一种HTML内嵌式的在服务器端执行的脚本语言,所以大部分PHP开发出来的Web应用,初始的开发模板就是混合层的数据编程.虽然通过MVC设计模式可以把程序应用逻辑与网页呈现逻辑强制性分离,但也只是将应用程序的输入.处理和输出分开,网页呈现逻辑(视图)还会有HTML代

django 第五课自定义模板过滤器与标签

代码布局:(自定义的代码放在哪里) 某个app特有的 app目录下,templatetags文件夹需要放 __init__.py 在到templetags文件夹下创建python模块(py文件) 定义复用 创建要给新的app,将他们定义在新的app中,在INSTALL_APPS 注册,然后可以应用 自定义模板过滤器 模板过滤器是什么? 函数,一个或两个参数 第一个参数是传递进来的模板变量 第二个参数,普通的参数,也可以是默认也可以不要其实就是个函数,没有什么不同在app目录teacher下创建t

PHP的自定义模板引擎

前面的话 在大多数的项目组中,开发一个Web程序都会出现这样的流程:计划文档提交之后,前端工程师制作了网站的外观模型,然后把它交给后端工程师,它们使用后端代码实现程序逻辑,同时使用外观模型做成基本架构,然后工程被返回到前端工程师继续完善.就这样工程可能在后端工程师和前端工程师之间来来回回好几次.由于后端工程师不干预任何相关HTML标签,同时也不需要前端代码和后端代码混合在一起.前端工程师只需要配置文件,动态区块和其他的界面部分,不必要去接触那些错综复杂的后端代码.因此,这时候有一个很好的模板支持

Springboot 结合百度IORC实现自定义模板图片识别

前言: 首先呢,最近再公司的项目当中遇到这样的一个问题,就是需要识别图片,提取图片当中的关键语句,而且识别的语句当然是人家手写体识别,翻来覆去一想,最终还是决定使用百度的OCR帮助我解决这一项需求 话不多说,我们直接开始 先去官网一探究竟 https://cloud.baidu.com/product/ocr 这里我们看到有很多相关的产品,大致都是图片文字识别,大致都相同 我们在这里选择自定义模板识别,这样跟符合我们逻辑业务的需求,让用户去手填一个单子,肯定会有一定的模板信息,这样识别的精度和准

WPF 自定义模板

回顾 上一篇,我们简单介绍了几个基本的控件,本节我们将讲解每个控件的样式的自定义和数据模板的自定义,我们会结合项目中的具体的要求和场景来分析,给出我们实现的方案和最终的运行效果. 本文大纲 1.控件模板及数据模板 2.ListBox深度定制模板. 3.TreeView高级模板使用实例. 控件模板及数据模板 控件模板 什么是控件模板,指定可以在控件的多个实例之间共享 Control 的可视结构和性能方面的方面.控件模板其实就是我们在可视方面的自定义模板,ControlTemplate 允许您指定控

2016年netty/mina/java nio视频教程java游戏服务器设计教程

2016年netty/mina/Javanio视频教程Java游戏服务器设计教程 需要的加qq:1225462853,备注:程序员学习视频 其他视频都可以索要(Netty   NET    C++ 等等) 互联网架构师教程:http://blog.csdn.net/pplcheer/article/details/71887910 netty录制时间为2015.11-2016.2月份  netty教程为加密视频!      netty12个课程已全部录制完成,相信通过这12节课的分析能让大家对n

从零开始自学Java泛型的设计难不难?

引言 泛型是Java中一个非常重要的知识点,在Java集合类框架中泛型被广泛应用.本文我们将从零开始来看一下Java泛型的设计,将会涉及到通配符处理,以及让人苦恼的类型擦除. 泛型基础 泛型类 我们首先定义一个简单的Box类: public class Box { private String object; public void set(String object) { this.object = object; } public String get() { return object;

RazorEngine在非MVC下的使用,以及使用自定义模板

---恢复内容开始--- RazorEngine模板引擎大大的帮助了我们简化字符串的拼接与方法的调用,开源之后,现在在简单的web程序,winform程序,甚至控制台程序都可以利用它来完成. 但如何在使用中调用方法和使用自定义模板呢?来看这样一个例子 1 string str="hello @Model.Name"; 2 string parse=Razor.Prase(str,new {Name="Tom"}); 3 Console.WriteLine(parse