首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

设计 REST 风格的 MVC 框架-3 集成模板引擎

设计 REST 风格的 MVC 框架-3 集成模板引擎

集成模板引擎作为示例,返回一个“<h1>Hello, world!</h1>”作为 HTML 页面非常容易。然而,实际应用的页面通常是极其复杂的,需要一个模板引擎来渲染出 HTML。可以把 JSP 看作是一种模板,只要不在 JSP 页面中编写复杂的 Java 代码。我们的设计目标是实现对 JSP 和 Velocity 这两种模板的支持。
和集成 IoC 框架类似,我们需要解耦 MVC 与模板系统,因此,TemplateFactory 用于初始化模板引擎,并返回 Template 模板对象。TemplateFactory 定义见清单 11。
清单 11. 定义 TemplateFactory
1
2
3
4
5
6
7
8
public abstract class TemplateFactory {
    private static TemplateFactory instance;
    public static TemplateFactory getTemplateFactory() {
        return instance;
    }

    public abstract Template loadTemplate(String path) throws Exception;
}




Template 接口则实现真正的渲染任务。定义见清单 12。
清单 12. 定义 Template
1
2
3
4
public interface Template {
    void render(HttpServletRequest request, HttpServletResponse response,
        Map<String, Object> model) throws Exception;
}




以 JSP 为例,实现 JspTemplateFactory 非常容易。代码见清单 13。
清单 13. 定义 JspTemplateFactory
1
2
3
4
5
6
7
8
9
10
11
12
13
public class JspTemplateFactory extends TemplateFactory {
    private Log log = LogFactory.getLog(getClass());

    public Template loadTemplate(String path) throws Exception {
        if (log.isDebugEnabled())
            log.debug("Load JSP template '" + path + "'.");
        return new JspTemplate(path);
    }

    public void init(Config config) {
        log.info("JspTemplateFactory init ok.");
    }
}




JspTemplate 用于渲染页面,只需要传入 JSP 的路径,将 Model 绑定到 HttpServletRequest,就可以调用 Servlet 规范的 forward 方法将请求转发给指定的 JSP 页面并渲染。代码见清单 14。
清单 14. 定义 JspTemplate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class JspTemplate implements Template {
    private String path;

    public JspTemplate(String path) {
        this.path = path;
    }

    public void render(HttpServletRequest request, HttpServletResponse response,
            Map<String, Object> model) throws Exception {
        Set<String> keys = model.keySet();
        for (String key : keys) {
            request.setAttribute(key, model.get(key));
        }
        request.getRequestDispatcher(path).forward(request, response);
    }
}




另一种比 JSP 更加简单且灵活的模板引擎是 Velocity,它使用更简洁的语法来渲染页面,对页面设计人员更加友好,并且完全阻止了开发人员试图在页面中编写 Java 代码的可能性。使用 Velocity 编写的页面示例如清单 15 所示。
清单 15. Velocity 模板页面
1
2
3
4
<html>
    <head><title>${title}</title></head>
    <body><h1>Hello, ${name}!</body>
</html>




通过 VelocityTemplateFactory 和 VelocityTemplate 就可以实现对 Velocity 的集成。不过,从 Web 开发人员看来,并不需要知道具体使用的模板,客户端仅需要提供模板路径和一个由 Map<String, Object> 组成的 Model,然后返回一个 TemplateRenderer 对象。代码如清单 16 所示。
清单 16. 定义 TemplateRenderer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class TemplateRenderer extends Renderer {
    private String path;
    private Map<String, Object> model;

    public TemplateRenderer(String path, Map<String, Object> model) {
        this.path = path;
        this.model = model;
    }

    @Override
    public void render(ServletContext context, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        TemplateFactory.getTemplateFactory()
                .loadTemplate(path)
                .render(request, response, model);
    }
}




TemplateRenderer 通过简单地调用 render 方法就实现了页面渲染。为了指定 Jsp 或 Velocity,需要在 web.xml 中配置 DispatcherServlet 的初始参数。配置示例请参考清单 17。
清单 17. 配置 Velocity 作为模板引擎
1
2
3
4
5
6
7
8
<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.expressme.webwind.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>template</param-name>
        <param-value>Velocity</param-value>
    </init-param>
</servlet>




如果没有该缺省参数,那就使用默认的 Jsp。
类似的,通过扩展 TemplateFactory 和 Template,就可以添加更多的模板支持,例如 FreeMarker。
返回列表