SpringBoot-Velocity模板引擎

Velocity (简称 VTL)是一个基于 Java 的模版引擎。它允许任何人仅仅使用简单的模板语言来引用由java代码定义的对象。

本案例使用 Velocity 动态生成 XML 文件

Velocity总体架构

APP模块

其中app主要封装了一些接口,暴露给使用者使用。主要有两个类,分别是Velocity(单例)和VelocityEngine

Velocity主要封装了一些静态接口,可以直接调用,帮助你渲染模板,只要传给Velocity一个模板和模板中对应的变量值就可以直接渲染

VelocityEngine类主要是供一些框架开发者调用的,它提供了更加复杂的接口供调用者选择,MVC框架中初始化一个VelocityEngine

Context模块

Context模块主要封装了模板渲染需要的变量,它的主要作用有两点:

  1. 便于与其他框架集成,起到一个适配器的作用,如MVC框架内部保存的变量往往在一个Map中,这样MVC框架就需要将这个Map适配到Velocity的context中
  2. Velocity内部做数据隔离,数据进入Velocity的内部的不同模块需要对数据做不同的处理,封装不同的数据接口有利于模块之间的解耦

Context类是外部框架需要向Velocity传输数据必须实现的接口,具体实现时可以集成抽象类AbstractContext,例如,Spring MVC中直接继承了VelocityContext,调用构造函数创建Velocity需要的数据结构

另外一个接口InternetEventContext主要是为扩展Velocity事件处理准备的数据接口,当你扩展了事件处理、需要操作数据时可以实现这个接口,并且处理你需要的数据

Runtime模块

整个Velocity的核心模块在runtime package下,这里会将加载的模板解析成JavaCC语法树,Velocity调用mergeTemplate方法时会渲染整棵树,并输出最终的渲染结果

RuntimeInstance类

RuntimeInstance类为整个Velocity渲染提供了一个单例模式,它也是Velocity的一个门面,封装了渲染模板需要的所有接口,拿到了这个实例就可以完成渲染过程了。它与VelocityEngine不同,VelocityEngine代表了整个Velocity引擎,它不仅包括模板渲染,还包括参数设置及数据的封装规则,RuntimeInstance仅仅代表一个模板的渲染状态

一、引入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>        

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.18</version>
        </dependency>

        <!-- Apache Velocity -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>

二、模版文件

位置:resources\vm\demo.vm

## 测试
<?xml version="1.0" encoding="utf-8"?>
<TEST>
    <Head>
        <Time>$!{time}</Time>
    </Head>
    <Body>
        <DEMO>
            <ID>$!{id}</ID>
            <STATUS/>
            <LIST>
                #foreach( $list in $listDemo )
                    <VALUE>$!{list.name}</VALUE>
                #end
            </LIST>
        </DEMO>
    </Body>
</TEST>

三、模版工具类

import cn.hutool.core.util.CharsetUtil;
import com.example.demo.velocity.domin.DemoTemplate;
import lombok.experimental.UtilityClass;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * 模板工具类
 */
@UtilityClass
public class VelocityUtils {

    /**
     * 初始化 Velocity 环境
     */
    public void initVelocity() {
        Properties p = new Properties();
        try {
            // 加载classpath目录下的vm文件
            p.setProperty("resource.loader.file.class",
                    "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
            // 定义字符集
            p.setProperty(Velocity.INPUT_ENCODING, CharsetUtil.UTF_8);
            // 初始化Velocity引擎,指定配置Properties
            Velocity.init(p);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 设置批复模板变量信息
     *
     * @return 模板列表
     */
    public VelocityContext prepareApprovalContext(DemoTemplate demoTemplate) {
        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("time", demoTemplate.getTime());
        velocityContext.put("id", demoTemplate.getId());
        velocityContext.put("listDemo", demoTemplate.getListDemo());
        return velocityContext;
    }

    /**
     * 获取模板信息
     *
     * @param tplCategory 模版类型
     * @return 模板列表
     */
    public List<String> getTemplateList(String tplCategory) {
        List<String> templates = new ArrayList<String>();
        if ("demo".equals(tplCategory)) {
            templates.add("vm/demo.vm");
        }
        return templates;
    }

    /**
     * 生成模板信息
     *
     * @param demoTemplate 模版数据
     * @return 模板信息
     */
    public static String getXmlByData(DemoTemplate demoTemplate) {
        // 初始化上下文
        VelocityUtils.initVelocity();
        // 获取模版变量
        VelocityContext context = VelocityUtils.prepareApprovalContext(demoTemplate);
        if (Objects.isNull(context)) {
            return StringUtils.EMPTY;
        }
        // 获取预制模版
        List<String> templates = VelocityUtils.getTemplateList("demo");

        StringWriter sw = new StringWriter();
        for (String template : templates) {
            // 渲染模板
            Template tpl = Velocity.getTemplate(template, CharsetUtil.UTF_8);
            tpl.merge(context, sw);
        }
        return sw.toString();
    }
}

四、创建实体类

import lombok.Data;
import java.io.Serializable;
import java.util.List;

@Data
public class DemoTemplate implements Serializable {
    private String id;
    private String time;
    private List<ListDemo> listDemo;
}
import lombok.Data;
import java.io.Serializable;


@Data
public class ListDemo implements Serializable {
    private String name;
}

五、测试方法

import cn.hutool.core.collection.ListUtil;
import com.example.demo.velocity.VelocityUtils;
import com.example.demo.velocity.domin.DemoTemplate;
import com.example.demo.velocity.domin.ListDemo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class VelocityController {

    @GetMapping("velocityDemo")
    public String velocityDemo(){
        DemoTemplate demoTemplate = new DemoTemplate();
        demoTemplate.setId("1");
        demoTemplate.setTime("2023-08-01");
        ListDemo listDemo = new ListDemo();
        listDemo.setName("demo");
        demoTemplate.setListDemo(ListUtil.of(listDemo));
        return VelocityUtils.getXmlByData(demoTemplate);
    }
}

相关链接:

Velocity 快速入门 | JAVA-TUTORIAL☕ java-tutorial 是一个 Java 教程,汇集一个老司机在 Java 领域的十年积累。icon-default.png?t=N7T8https://dunwu.github.io/java-tutorial/pages/7ecb81/#%E6%B3%A8%E9%87%8A

介紹 | Velocity 中文文档icon-default.png?t=N7T8https://wizardforcel.gitbooks.io/velocity-doc/content/

https://github.com/alibaba/velocity-spring-boot-projecticon-default.png?t=N7T8https://github.com/alibaba/velocity-spring-boot-projecthttps://www.cnblogs.com/wade-luffy/p/5996848.htmlicon-default.png?t=N7T8https://www.cnblogs.com/wade-luffy/p/5996848.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值