前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Apache Velocity-----基于Java的模板引擎

Apache Velocity-----基于Java的模板引擎

作者头像
wuweixiang
发布2018-08-14 10:44:57
8.1K0
发布2018-08-14 10:44:57
举报
文章被收录于专栏:吴伟祥吴伟祥

Velocity简介

Apache Velocity是一个基于Java模板引擎,它提供了一个模板语言去引用由Java代码定义的对象。Velocity是Apache基金会旗下的一个开源软件项目,旨在确保Web应用程序在表示层和业务逻辑层之间的隔离(即MVC设计模式)。

用途

下面是一些利用Velocity的常见应用类型:

  • Web应用程序网页设计者创建HTML页面,并为动态信息预留占位符。页面再由VelocityViewServlet或任何支持Velocity的框架处理。
  • 源代码生成:Velocity可基于模板生成Java、SQLPostScript源代码。大量的开源和商业软件包的开发就是这样利用Velocity。[1]
  • 电子邮件自动生成:许多应用程序为了账户注册、密码提醒或自动寄送报表之需自动生成电子邮件。利用Velocity,电子邮件模板可以存储在一个文本文件,而不是直接嵌入到电子邮件生成器的Java代码中。
  • XML转化:Velocity提供一个Ant任务——Anakia。Anakia读取XML文件,利用Velocity模板转换成所需的文档格式。常见的应用是将某种格式的文档转换成的一个带样式的HTML文档。

代码示例

如下的Web模板:

代码语言:javascript
复制
## Velocity Hello World
<html>
    <body>
       #set( $foo = "Velocity" )
       ## followed by
       Hello $foo World!
    </body>
</html>

经过Velocity处理后会生成如下的HTML代码:

代码语言:javascript
复制
<html>
    <body>
     Hello Velocity World!
    </body>
</html>

 Velocty的基本用法

在这里我们以一个HelloVelocity作为Velocity的入门实例.首先在官网下载velocity的最新发布包,新建普通java项目,引入其中的velocity-1.7.jar和lib文件夹下的所有jar包即可.

Maven 用户

在你的POM文件中引用下面依赖:

代码语言:javascript
复制
<dependency>
  <groupId>org.apache.velocity</groupId>
  <artifactId>velocity-engine-core</artifactId>
  <version>x.x.x</version>
</dependency>

如果你想在Velocity中引入Logging, SLF4J, Log4j或者服务器logger日志, 在POM文件中添加一下依赖:

代码语言:javascript
复制
<dependency>
  <groupId>org.apache.velocity</groupId>
  <artifactId>velocity-engine-commons-logging</artifactId>
  <version>x.x.x</version>
</dependency>

<dependency>
  <groupId>org.apache.velocity</groupId>
  <artifactId>velocity-engine-slf4j</artifactId>
  <version>x.x.x</version>
</dependency>

<dependency>
  <groupId>org.apache.velocity</groupId>
  <artifactId>velocity-engine-log4j</artifactId>
  <version>x.x.x</version>
</dependency>

<dependency>
  <groupId>org.apache.velocity</groupId>
  <artifactId>velocity-engine-servlet</artifactId>
  <version>x.x.x</version>
</dependency>

然后分为如下两步:

2.1 初始化Velocity引擎

编写HelloVelocity.java文件如下:

代码语言:javascript
复制
public static void main(String[] args) {
    // 初始化模板引擎
    VelocityEngine ve = new VelocityEngine();
    ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
    ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
    ve.init();
    // 获取模板文件
    Template t = ve.getTemplate("hellovelocity.vm");
    // 设置变量
    VelocityContext ctx = new VelocityContext();
    ctx.put("name", "Velocity");
    List list = new ArrayList();
    list.add("1");
    list.add("2");
    ctx.put("list", list);
    // 输出
    StringWriter sw = new StringWriter();
    t.merge(ctx,sw);
    System.out.println(sw.toString());
}

首先,我们在代码中初始化了VelocityEngine这个模板引擎,对其设置参数进行初始化,指定使用ClasspathResourceLoader来加载vm文件。然后我们就可以往VelocityContext这个Velocity容器中存放对象了,在vm文件中我们可以取出这些变量,从而进行模板输出.

2.2 编写hellovelocity.vm文件

其中,vm文件放在classpath目录下即可,类加载器会进行加载 hellovelocity.vm文件如下:

代码语言:javascript
复制
#set($greet = 'hello')
$greet $name 
#foreach($i in $list)
$i
#end

控制台输出如下:

代码语言:javascript
复制
hello Velocity
1
2

2.3 Velocity的基本语法

本文中只简单的介绍几个Velocity的基本语法,具体可以参考这篇文章

3.1 变量

在Velocity中也有变量的概念,使用$符声明变量,可以声明变量也可以对变量进行赋值(变量是弱类型的)。另外还可以使用$取出在VelocityContext容器中存放的值

代码语言:javascript
复制
#set(${!name} = "velocity")
#set(${!foo} = $bar)
#set($foo =“hello”)
#set($foo.name = $bar.name)
#set($foo.name = $bar.getName($arg))
#set($foo = 123)
#set($foo = [“foo”,$bar])

需要注意,上面代码中 $!{}的写法,使用$vari获取变量时,如果变量不存在,Velocity引擎会将其原样输出,通过使用$!{}的形式可以将不存在的变量变成空白输出.

3.2 循环

在Velocity中可以使用循环语法遍历集合,语法结构如下:

代码语言:javascript
复制
#foreach($item in $list)
 $item
 $velocityCount 
#end

其中,$item代表遍历的每一项,velocityCount是Velocity提供的用来记录当前循环次数的计数器,默认从1开始计数,可以在velocity.properties文件中修改其初始值

3.3 条件控制语法

在Velocity中可以使用条件语法对流程进行控制

代码语言:javascript
复制
#if(condition)
...dosonmething...
#elseif(condition)
...dosomething...
#else
...dosomething...
#end

3.4 宏

在Velocity中也有宏的概念,可以将其作为函数来理解,使用#macro声明宏

代码语言:javascript
复制
## 声明宏
#macro(sayHello $name)
   hello $name
#end
## 使用宏
#sayHello("NICK")

3.5 parse和include指令

在Velocity中可以通过parse或者include指令引入外部vm文件,但是二者存在区别:include指令会将外部文件原样输出,而parse指令会先对其进行解析再输出(即对外部文件中的vm语法解析)

代码语言:javascript
复制
#parse("header.vm")
#include("footer.vm")

4. 在web项目中使用Velocity

velocity只是一个模板引擎,在web项目中使用Velocity还得添加一个HTTP框架来处理请求和转发,apache提供了velocity-tools,其提供了VelocityViewServlet,也可继承VelocityViewServlet,从而实现自己的HTTP框架 一般都是继承VelocityViewServlet,重写handleRequest方法,在其中存入公共的参数.

通过继承或直接使用VelocityViewServlet,可以在管理的vm文件中获得request、session与application对象,也可以直接获取在这几个域对象中保存的值,获取的顺序与EL表达式获取的顺序类似: ${request} --> ${session} --> ${application} 比如${testArr}获取testArr属性,velocity会在velocity的context中寻找。没找到在request域中找,没找到在session中找.

下面将通过实例的方式讲解如何在web项目中使用Velocity 首先引入velocity-tools及其依赖的相关jar包,然后分为如下4步:

4.1 继承VelocityViewServlet

通过继承VelocityViewServlet重写handleRequest方法,可以自定义转发规则

代码语言:javascript
复制
public class MyVelocityViewServlet extends VelocityViewServlet {
    @Override
    protected Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx) {
        // 往Context容器存放变量
        ctx.put("fullName","lixiaolin");
        // 也可以往request域中存值
        request.setAttribute("anotherName","xlli");
        // forward到指定模板
        return getTemplate("test.vm");
    }
}

4.2 配置web.xml

对自定义的VelocityViewServlet配置就像配置普通的Servlet一样,如下:

代码语言:javascript
复制
<servlet>
    <servlet-name>MyVelocityServlet</servlet-name>
    <servlet-class>com.lxl.velocity.MyVelocityViewServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>MyVelocityServlet</servlet-name>
    <url-pattern>/servlet/myVelocityServlet</url-pattern>
</servlet-mapping>

4.3 编写vm文件

vm文件是作为jsp的替代来展示给用户,在vm文件中可以获得在Context域或request等域中存放的值。默认情况下,会在资源根路径下搜索vm文件,所以直接将vm放在根路径下即可(也可以通过配置velocity.properties指定加载路径) 如下:

代码语言:javascript
复制
#set($greet = "hello")
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
 <p>$!{greet} $!{fullName}</p>
 <p>my another name is $!{anotherName}</p>
</body>
</html>

4.4 配置velocity.properties

通过配置velocity.properties文件,可以自定义vm文件加载方式,指定编码等。当然,也可以不配置velocity.properties,使用缺省的值即可.

代码语言:javascript
复制
## 设置模板文件加载器,webapp从应用根目录加载
resource.loader = webapp
webapp.resource.loader.class = org.apache.velocity.tools.view.WebappResourceLoader
## 模板路径,根目录下的vm文件夹
webapp.resource.loader.path = /vm
## 设置编码
input.encoding = UTF-8
output.encoding = UTF-8

最后,在浏览器中访问http://localhost:8080/VelocityApp/servlet/myVelocityServlet即可

5. 使用VelocityLayoutServlet

在web站点开发的过程中,经常会碰到几个页面的布局大致相同,比如引用相同的头部和尾部、左侧边栏相同等,在使用jsp开发时我们可以将头部等公共文件抽离出来,然后在实际页面中引入。Velocity也提供了类似的功能,并且该功能更加强大.

apache提供了VelocityLayoutServlet来实现页面布局,它是VelocityViewServlet的子类,通过使用VelocityLayoutServlet可以简化velocity下页面布局开发,可以使当forward到一个vm页面时,把该页面作为一个已有页面布局的一部分整体显示出来,比如访问资料页面,能够自动把头、尾部显示出来

velocity-tools包中已经包含了这个类,其使用分为如下几步:

5.1 配置velocity.properties

在/WEB-INF/路径下配置velocity.properties文件,指定模板布局文件的位置

代码语言:javascript
复制
input.encoding=UTF-8
output.encoding=UTF-8
## 定义加载器
resource.loader=webapp
webapp.resource.loader.cache=false
## 布局文件夹位置
tools.view.servlet.layout.directory = /templates/layout
## 定义默认布局文件
tools.view.servlet.layout.default.template = layout.vm
## 错误模板文件
tools.view.servlet.error.template = err.vm

5.2 布局母版vm文件

布局layout.vm文件是所有要展示的vm文件的母版,如下所示:

代码语言:javascript
复制
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>${page_title}</title>
#if($!{CSS})
 #foreach($_css in ${CSS})
   <link type="text/css" rel="stylesheet" href="${ContextPath}/$_css">
 #end
#end
</head>
<body>
  <div class="header">
      #parse("/templates/layout/header.vm")
  </div>
  <div class="container">
      <div class="sub">
          #parse($sub)
      </div>
      <div class="main">
          $screen_content
      </div>
  </div>
#if($!JS)
 #foreach($_js in $JS)
   <script type="text/javascript" src="${CntextPath}/${_js}">
 #end
#end
</body>
</html>

其中,有个特殊的变量 screen_content,这是Velocity内置的变量,代表将要转发的页面

5.3 编写转发的vm文件

代码语言:javascript
复制
#set($layout = "/templates/layout/layout.vm")
#set($CSS = ["scripts/css/index.css"])
#set($JS = ["scripts/js/jquery-1.11.3.js"])
#set($page_title = "主页")
#set($sub = "/templates/sub.vm")

<div id="main-show">
    this is main-show
</div>

5.4 继承VelocityLayoutServlet

代码语言:javascript
复制
public class MyLayoutServlet extends VelocityLayoutServlet {
    @Override
    protected void doRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 设置通用的变量
        request.setAttribute("Request", request);
        request.setAttribute("ContextPath", request.getContextPath());
        request.setAttribute("BasePath", request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath());

        long runtime = System.currentTimeMillis();
        super.doRequest(request, response);

        if (request.getAttribute("close_comment") == null) {
            Date cur_time = Calendar.getInstance(request.getLocale()).getTime();
            PrintWriter pw = response.getWriter();
            pw.print("\r\n<!-- Generated by VelocityApp Server(");
            pw.print(cur_time);
            pw.print(") Cost ");
            pw.print(cur_time.getTime() - runtime);
            pw.print(" ms -->");
            pw.flush();
            pw.close();
        }
    }
}

本文转载自:https://www.jianshu.com/p/5913903324ff

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Velocity简介
  • 用途
  • 代码示例
  •  Velocty的基本用法
    • Maven 用户
      • 2.1 初始化Velocity引擎
        • 2.2 编写hellovelocity.vm文件
          • 2.3 Velocity的基本语法
            • 3.1 变量
            • 3.2 循环
            • 3.3 条件控制语法
            • 3.4 宏
            • 3.5 parse和include指令
          • 4. 在web项目中使用Velocity
            • 4.1 继承VelocityViewServlet
            • 4.2 配置web.xml
            • 4.3 编写vm文件
            • 4.4 配置velocity.properties
          • 5. 使用VelocityLayoutServlet
            • 5.1 配置velocity.properties
            • 5.2 布局母版vm文件
            • 5.3 编写转发的vm文件
            • 5.4 继承VelocityLayoutServlet
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档