JEE6 CDI 扩展实现 MVC (四) 实现多模板引擎支持,并提供扩展接口
为什么80%的码农都做不了架构师?>>>
在上一篇中,我们添加了对 Freemarker的支持,这里我们再添加多 Velocity 的支持,同时留出扩展接口。方便用户自己添加模板引擎。我们这里全试用注解,无需配置文件。这个功能也正好可以很好的体现出CDI 强大的扩展性。
1. 定义模板处理的接口
我们定义一个接口来表示模板引擎的功能。
public interface ResponeseTemplateHandler {void init(String path) throws IOException;void process(RequestContext context) throws IOException;
}
2. 定义注解和枚举
对于@ResponseTemplate注解,我们在使用在 Controller 的方法上面的时候通过其type的值来确定调用使用的引擎模板,value的值表示模板所在的路径。
@Qualifier
@Target({ElementType.METHOD,ElementType.TYPE,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ResponseTemplate {String value() default "";TemplateType type();String customname() default "";
}
public enum TemplateType {FREEMARKER,VELOCITY,CUSTOM
}
3.实现接口并通过限定词区分
我们这里提供了 Freemarker 和 Velocity 的实现,分别使用@ResponseTemplate(type = TemplateType.FREEMARKER) 和 @ResponseTemplate(type = TemplateType.VELOCITY) 作为限定词。
@ResponseTemplate(type = TemplateType.FREEMARKER)
public class FreeMarkerTemplate implements ResponeseTemplateHandler{private Configuration cfg;public void init(String path) throws IOException {cfg = new Configuration();cfg.setDirectoryForTemplateLoading(new File(path));}public void process(RequestContext context) throws IOException {init(context.getRequest().getSession().getServletContext().getRealPath("/"));String templatePath = context.getMethod().getResponseTemplate().value();Template t = cfg.getTemplate(templatePath);try {HttpServletResponse response = context.getResponse();response.setContentType("text/html");t.process(context.getOutcome(), context.getResponse().getWriter());} catch (TemplateException e) {e.printStackTrace();}}}
@ResponseTemplate(type = TemplateType.VELOCITY)
public class VelocityTemplate implements ResponeseTemplateHandler{private VelocityEngine engine;public void init(String path) throws IOException {engine = new VelocityEngine();engine.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, path);}public void process(RequestContext context) throws IOException {init(context.getRequest().getSession().getServletContext().getRealPath("/"));String templatePath = context.getMethod().getResponseTemplate().value();Template t = engine.getTemplate(templatePath);try {HttpServletResponse response = context.getResponse();response.setContentType("text/html");if(!(context.getOutcome() instanceof Map)){throw new Exception("The return value of template method must be a map");}VelocityContext velocityContext = new VelocityContext((Map)context.getOutcome());t.merge(velocityContext, context.getResponse().getWriter());} catch (TemplateException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}}
4. 动态注入接口的实现类
在Controller 方法执行完以后,我们根据它的 @ResponseTemplate 注解来注入对应的模板引擎。在CDI中,我们可以使用 BeanManager 实现 Bean的注入。利用它的 getBeans 和 getReference 方法。这里我们需要先定义出 @ResponseTemplate 注解的实现类。其实注解也是一个接口,注解这方面没有太深入的研究过,用起来的感觉是很爽的。
@ResponseTemplate的实现类 ResponseTemplateLiteral
public class ResponseTemplateLiteral extends AnnotationLiteral<ResponseTemplate> implements ResponseTemplate{private static final long serialVersionUID = -3438074414725731211L;private TemplateType type;private String customname = "";public ResponseTemplateLiteral(TemplateType type){this.type = type;}public ResponseTemplateLiteral(TemplateType type,String customname){this.type = type;this.customname = customname;}public String value() {return "";}public TemplateType type() {return type;}public String customname() {return customname;}}
我们写一个模板的默认处理类,Controller 方法的值返回后,我们就交给这个类处理。然后在这个类里面动态注入对应的模板引擎。
public class DefaultTemplateHandler {@Injectprivate BeanManager beanManager;public void handle(RequestContext context) {try {ResponseTemplate template = context.getMethod().getResponseTemplate();ResponseTemplateLiteral templateLiteral ;TemplateType type = template.type();if (type.equals(TemplateType.CUSTOM)&& (template.customname().equals(""))) {throw new MvcdiTemplateException("Custom template name Can not be empty with TemplateType.CUSTOM");}if(type.equals(TemplateType.CUSTOM)){templateLiteral = new ResponseTemplateLiteral(type, template.customname());}else{templateLiteral = new ResponseTemplateLiteral(type);}Bean<?> bean = beanManager.getBeans(ResponeseTemplateHandler.class,templateLiteral).iterator().next();ResponeseTemplateHandler templateHandler = (ResponeseTemplateHandler) beanManager.getReference(bean, ResponeseTemplateHandler.class,beanManager.createCreationalContext(bean));templateHandler.process(context);} catch (IOException e) {e.printStackTrace();} catch (MvcdiTemplateException e) {e.printStackTrace();}}
}
在上面代码中 ,我们通过 new 出不同的 ResponseTemplate 的实现类,然后通过 BeanManager 注入ResponeseTemplateHandler 接口不同的实现类。
自定义模板引擎扩展
假如,我们需要使用 Smarty4j 模板引擎。那么我们只需要实现ResponeseTemplateHandler接口,然后给实现类添加注解 @ResponseTemplate(type= TemplateType.CUSTOM, customname ="Smarty4j"), 然后在使用的Controller 的方法上面也加上这个注解就可以了。
转载于:https://my.oschina.net/FengJ/blog/74555
JEE6 CDI 扩展实现 MVC (四) 实现多模板引擎支持,并提供扩展接口相关推荐
- MVC 4.0 Razor模板引擎 @Html.RenderPartial 与 @Html.RenderAction 区别
近来在学习MVC 4.0,设置布局全局网页的页脚,使用了Razor语法 @{Html.RenderPartial("Footer", Model.FooterData);} 但是并 ...
- html 模板引擎 热部署,springboot系列四、配置模板引擎、配置热部署
一.配置模板引擎 在之前所见到的信息显示发现都是以 Rest 风格进行显示,但是很明显在实际的开发之中,所有数据的显示最终都应该交由页面完成,但是这个页面并不是*.jsp 页面,而是普通的*.html ...
- springboot系列四、配置模板引擎、配置热部署
一.配置模板引擎 在之前所见到的信息显示发现都是以 Rest 风格进行显示,但是很明显在实际的开发之中,所有数据的显示最终都应该交由页面完成,但是这个页面并不是*.jsp 页面,而是普通的*.html ...
- 初学者idea web项目搭建之路(四) thymeleaf模板引擎
前言 自己摸索了一阵后,在网络上找了一个入门的spring boot视频看了一下,有如醍醐灌顶一般,瞬间就筑基成功突破了,毕竟学习知识还是成体系的好. 模板引擎依赖引入 首先吧抛出两个官网spring ...
- PHP MVC及模板引擎
连接到此文 模板引擎,这四个字听起来很高深的样子,一般用到"引擎"两字都会感觉比较高级,类似游戏3D引擎.Zend引擎等,其实都是唬人的,骗外行人的.所以在我初学PHP的那会,也因 ...
- Smarty模板引擎和MVC设计模式
Smarty模板引擎 一.什么是smarty? smarty是一个使用php写出来的模板php模板引擎,它提供了逻辑与外在内容的分离 目的:使用户界面和业务数据的代码分离 smarty 第三方的类库 ...
- 基于Mozilla Thunderbird的扩展开发(四)---修改Thunderbird源代码实现自动保存附件...
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace ...
- 实现WebMvcConfigurer接口扩展Spring MVC的功能
前言: 先查看WebMvcConfigurer接口中都定义了哪些内容 public interface WebMvcConfigurer {default void configurePathMatc ...
- 第四篇 快速、轻量、可扩展、易于使用的EmEditor
第四篇 快速.轻量.可扩展.易于使用的EmEditor 最近一直在尝试各种文本编辑器.说实话,以前对文本编辑器没啥要求,普通的也就用Windows自带的记事本了.想要高亮或格式好点的,这时候就会使用E ...
最新文章
- ACM 中常用的算法有哪些?
- 用Everything搜索指定的路径
- 【js】小数点后保留两位小数
- Java构造和解析Json数据的两种方法详解一
- iOS 正则表达式使用的三种方式语法
- 原生JS数组去重的几种方法
- qt中设置控件不能使用
- 拿到一台新的Windows电脑,我会做什么?
- centos 图形模式与命令行模式设置
- Spring Framework,ioc容器(转)
- 【2017级面向对象程序设计】作业二
- Atitit. 构造ast 语法树的总结attilax oao
- Activiti学习记录 Activiti初始化数据库、Activiti6增加表注释字段注释
- WebSocket + 微信小程序 一对一聊天
- 计算机专业应届毕业生如何找工作(偏软件方向)
- 联想g510升级换什么cpu好_老775平台还有升级CPU的必要吗?实测来告诉你
- 质心定位算法C语言实现,TOA定位算法.pdf
- cup过高是什么意思_CPU占用过高怎么办? 每日一答
- PingCAP CTO 黄东旭 :基础软件“好用”指南——必须跨越这两道鸿沟!
- Vue全局共享数据之globalData,vuex,本地存储使用方法
热门文章
- python3.8新特性 逻辑表达式_Python3.8新特性
- codeforces392B
- 使用 JProbe 调试 Linux 内核(转)
- 判断input框是否为空
- 屏蔽firefox浏览器连接失败页面的广告
- CentOS+Nginx+PHP+Mysql(3)(转)
- kafka重新启动时出现:found a corrupted index file due to requirement failed问题解决方法
- IIS6.0发布后对路径“D:\xxx\xxxx\web.config”的访问被拒绝问题的解决方法
- Chrome浏览器打开异常慢的解决办法
- vue 打包后访问接口报错404 解决方案 (前提是在vue里使用了代理)