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 = plateLogic.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 = plateElConfigLogic.Id());
if (null == templateElConfigs || templateElConfigs.isEmpty() ) {
logger.info("There's no express configuration for template:{}", Name());
return;
}
3. 解析el的配置,⽣成最终字符串。
for (TemplateElConfig templateElConfig : templateElConfigs) {
TemplateEl el = plateElLogic.ElId());
if (el == null) {
logger.info("Missing el config, template el config id:{}",Id());    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 = (Class().getMethod(methodName);
propertyValue = (Date)method.invoke(datasource);
}else {
method = (Class().getMethod(methodName);
propertyValue = (String)method.invoke(datasource);
}
if (propertyValue instanceof Date) {
TemplateElFormat elFormat = plateElFormatLogic.Id());    String timeFormat = DEFAULT_DATE_FORMAT;
if (null != elFormat) {
timeFormat = Format();
}
SimpleDateFormat format = new SimpleDateFormat(timeFormat);
datasourceValue = format.format(propertyValue);
}else if (propertyValue instanceof String) {
datasourceValue = (String)propertyValue;
}
} catch (Exception e) {
<("No such method.", e);
result.setException(new IllegalTemplateConfigException("No such method.", e));    return;
}
if (StringUtils.isNoneEmpty(datasourceValue)) {
if (StringUtils.Prefix())) {
buffer.Prefix());
}
buffer.append(datasourceValue);
if (StringUtils.Suffix())) {
buffer.Suffix());
}
if (StringUtils.HtmlPrefix())) {
htmlBuffer.HtmlPrefix());
}
htmlBuffer.append(datasourceValue);
if (StringUtils.HtmlSuffix())) {
htmlBuffer.HtmlSuffix());
}
}
}
这⾥没有业务逻辑,所以是可以放到jar⾥⾯的,各业务系统只要控制如何结构化调⽤就⾏了。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。