为什么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 (四) 实现多模板引擎支持,并提供扩展接口相关推荐

  1. MVC 4.0 Razor模板引擎 @Html.RenderPartial 与 @Html.RenderAction 区别

    近来在学习MVC 4.0,设置布局全局网页的页脚,使用了Razor语法 @{Html.RenderPartial("Footer", Model.FooterData);} 但是并 ...

  2. html 模板引擎 热部署,springboot系列四、配置模板引擎、配置热部署

    一.配置模板引擎 在之前所见到的信息显示发现都是以 Rest 风格进行显示,但是很明显在实际的开发之中,所有数据的显示最终都应该交由页面完成,但是这个页面并不是*.jsp 页面,而是普通的*.html ...

  3. springboot系列四、配置模板引擎、配置热部署

    一.配置模板引擎 在之前所见到的信息显示发现都是以 Rest 风格进行显示,但是很明显在实际的开发之中,所有数据的显示最终都应该交由页面完成,但是这个页面并不是*.jsp 页面,而是普通的*.html ...

  4. 初学者idea web项目搭建之路(四) thymeleaf模板引擎

    前言 自己摸索了一阵后,在网络上找了一个入门的spring boot视频看了一下,有如醍醐灌顶一般,瞬间就筑基成功突破了,毕竟学习知识还是成体系的好. 模板引擎依赖引入 首先吧抛出两个官网spring ...

  5. PHP MVC及模板引擎

    连接到此文 模板引擎,这四个字听起来很高深的样子,一般用到"引擎"两字都会感觉比较高级,类似游戏3D引擎.Zend引擎等,其实都是唬人的,骗外行人的.所以在我初学PHP的那会,也因 ...

  6. Smarty模板引擎和MVC设计模式

    Smarty模板引擎 一.什么是smarty? smarty是一个使用php写出来的模板php模板引擎,它提供了逻辑与外在内容的分离 目的:使用户界面和业务数据的代码分离 smarty 第三方的类库 ...

  7. 基于Mozilla Thunderbird的扩展开发(四)---修改Thunderbird源代码实现自动保存附件...

    <?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace ...

  8. 实现WebMvcConfigurer接口扩展Spring MVC的功能

    前言: 先查看WebMvcConfigurer接口中都定义了哪些内容 public interface WebMvcConfigurer {default void configurePathMatc ...

  9. 第四篇 快速、轻量、可扩展、易于使用的EmEditor

    第四篇 快速.轻量.可扩展.易于使用的EmEditor 最近一直在尝试各种文本编辑器.说实话,以前对文本编辑器没啥要求,普通的也就用Windows自带的记事本了.想要高亮或格式好点的,这时候就会使用E ...

最新文章

  1. ACM 中常用的算法有哪些?
  2. 用Everything搜索指定的路径
  3. 【js】小数点后保留两位小数
  4. Java构造和解析Json数据的两种方法详解一
  5. iOS 正则表达式使用的三种方式语法
  6. 原生JS数组去重的几种方法
  7. qt中设置控件不能使用
  8. 拿到一台新的Windows电脑,我会做什么?
  9. centos 图形模式与命令行模式设置
  10. Spring Framework,ioc容器(转)
  11. 【2017级面向对象程序设计】作业二
  12. Atitit. 构造ast 语法树的总结attilax oao
  13. Activiti学习记录 Activiti初始化数据库、Activiti6增加表注释字段注释
  14. WebSocket + 微信小程序 一对一聊天
  15. 计算机专业应届毕业生如何找工作(偏软件方向)
  16. 联想g510升级换什么cpu好_老775平台还有升级CPU的必要吗?实测来告诉你
  17. 质心定位算法C语言实现,TOA定位算法.pdf
  18. cup过高是什么意思_CPU占用过高怎么办? 每日一答
  19. PingCAP CTO 黄东旭 :基础软件“好用”指南——必须跨越这两道鸿沟!
  20. Vue全局共享数据之globalData,vuex,本地存储使用方法

热门文章

  1. python3.8新特性 逻辑表达式_Python3.8新特性
  2. codeforces392B
  3. 使用 JProbe 调试 Linux 内核(转)
  4. 判断input框是否为空
  5. 屏蔽firefox浏览器连接失败页面的广告
  6. CentOS+Nginx+PHP+Mysql(3)(转)
  7. kafka重新启动时出现:found a corrupted index file due to requirement failed问题解决方法
  8. IIS6.0发布后对路径“D:\xxx\xxxx\web.config”的访问被拒绝问题的解决方法
  9. Chrome浏览器打开异常慢的解决办法
  10. vue 打包后访问接口报错404 解决方案 (前提是在vue里使用了代理)