Velocity模板生成文件

概述

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

当Velocity应用于web开发时,界面设计人员可以和java程序开发人员同步开发一个遵循MVC架构的web站点,也就是说,页面设计人员可以只 关注页面的显示效果,而由java程序开发人员关注业务逻辑编码。Velocity将java代码从web页面中分离出来,这样为web站点的长期维护提 供了便利,同时也为我们在JSP和PHP之外又提供了一种可选的方案。

Velocity的能力远不止web站点开发这个领域,例如,它可以从模板(template)产生SQL和PostScript、XML,它也可以被当 作一个独立工具来产生源代码和报告,或者作为其他系统的集成组件使用。

本文将介绍他作为模板生成文件的具体实现。

实现

依赖

        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>1.7</version>
        </dependency>

模板

package ${packagePath};

import java.lang.String;

## 类名处理
public class $!{targetFileName} {

## 方法处理
#if( $!testProductArr )
    #foreach( $product in $productArr )
    <li>value=$product</li>
    #end
#end

#if( $!testMap )
    #foreach( $key in $kvMap.keySet() )
    <li>Key: $key ->Value: $kvMap.get($key)</li>
    #end
#end


}

代码

目标文件的相关配置

package com.example.demo.test.velocity;

import lombok.Getter;
import org.springframework.util.StringUtils;

/**
 * TargetFileConfig
 *
 * @author yuntian
 * @since 2020/10/30
 */
@Getter
public class TargetFileConfig {
    private static final String JAVA_FILE_PATH = "src/main/java/";
    private static final String PACKAGE_DOT = ".";
    private static final String PATH_SLASH = "/";
    private static final String JAVA_FILE_SUFFIX = ".java";
    private static final String CUR_FILE_NAME_PATTERN = "%sServiceImpl";

    /**
     * com.example.demo
     */
    private String basePackagePath = "com.example.demo";

    /**
     * service.impl
     */
    private String subPackagePath = "service.impl";

    private String domainName;

    /**
     * DomainNameService
     */
    private String fileName;

    /**
     * DomainNameService.java
     */
    private String fileNameWithSuffix;


    private String packagePath;

    /**
     * /Users/yuntian/try/demo/src/main/java/com/example/demo/service/impl/DomainNameService.java
     */
    private String filePathWithFileName;


    public TargetFileConfig(String basePackagePath, String subPackagePath, String domainName, String userDir) {
        this.basePackagePath = basePackagePath;
        this.subPackagePath = subPackagePath;
        this.domainName = domainName;

        this.fileName = String.format(CUR_FILE_NAME_PATTERN,domainName);
        this.fileNameWithSuffix =fileName+JAVA_FILE_SUFFIX;

        // concat package + path

        this.packagePath = concatPackage(basePackagePath, subPackagePath);

        String subPath = packagePath.replaceAll("\\.", PATH_SLASH);
        this.filePathWithFileName = concatPath(userDir, JAVA_FILE_PATH, subPath)+fileNameWithSuffix;
    }

    /**
     * concatPath
     *
     * @param basePath
     * @param subPath
     * @return
     */
    private String concatPath(String basePath, String... subPath) {
        StringBuilder stringBuilder = new StringBuilder(formatPath(basePath));

        for (String s : subPath) {
            String formatPath = formatPath(s);
            if (StringUtils.isEmpty(formatPath)) {
                continue;
            }

            stringBuilder.append(formatPath);
        }

        // 结尾加/
        stringBuilder.append(PATH_SLASH);

        return stringBuilder.toString();
    }

    /**
     * concatPackage
     *
     * @param basePackage
     * @param subPackage
     * @return
     */
    private String concatPackage(String basePackage, String... subPackage) {
        StringBuilder stringBuilder = new StringBuilder(formatPackage(basePackage));

        for (String s : subPackage) {
            String formatPackage = formatPackage(s);
            if (StringUtils.isEmpty(formatPackage)) {
                continue;
            }

            stringBuilder.append(PACKAGE_DOT).append(formatPackage);
        }
        return stringBuilder.toString();
    }

    /**
     * /Users/yuntian/try    前有 后无/
     *
     * @param curPath
     * @return
     */
    private String formatPath(String curPath) {
        if (!curPath.startsWith(PATH_SLASH)) {
            curPath = PATH_SLASH + curPath;
        }

        while (curPath.endsWith(PATH_SLASH)) {
            curPath = curPath.substring(0, curPath.length() - 1);
        }

        return curPath;
    }

    /**
     * 前后无.
     *
     * @param curPackage
     * @return
     */
    private String formatPackage(String curPackage) {
        while (curPackage.startsWith(PACKAGE_DOT)) {
            curPackage = curPackage.substring(1);
        }
        while (curPackage.endsWith(PACKAGE_DOT)) {
            curPackage = curPackage.substring(0, curPackage.length() - 1);
        }

        return curPackage;
    }
}

生成文件的主流程

package com.example.demo.test.velocity;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * VelocityDemo
 *
 * @author YunTian
 * @since 2020/10/29 
 */
public class VelocityDemo {
    //类名
    static String domainName = "YunTian";
    //类包
    static String basePackageName = "com.example.demo";

    //  /Users/yuntian/try/demo;
    static String userDir = System.getProperty("user.dir");

    static String templateDir = "/src/main/resources/templates/";
    static String templateFileName = "Service.java.vm";


    public static void main(String[] args) throws Exception {

        TargetFileConfig fileConfig = new TargetFileConfig(basePackageName,"service.impl",domainName,userDir);
        Map<String, TargetFileConfig> map = new HashMap<>();
        map.put(templateFileName, fileConfig);

        for (Map.Entry<String, TargetFileConfig> entry : map.entrySet()) {
            String templateFileName=entry.getKey();
            TargetFileConfig targetFileConfig = entry.getValue();

            // 模板变量
            VelocityContext context = buildVelocityContext(targetFileConfig);

            // 获取模板
            Template template = genTemplate(templateFileName);

            // 生成文件
            generatorTargetFile(context,template);
        }
    }

    // 生成文件
    private static void generatorTargetFile(VelocityContext context, Template template) throws Exception {

        // 目的路径
        String filePathWithFileName = (String) context.get("fileFullPath");
        File file = new File(filePathWithFileName);

        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }

        if (!file.exists()) {
            file.createNewFile();
        }

        FileOutputStream outStream = new FileOutputStream(file);
        OutputStreamWriter writer = new OutputStreamWriter(outStream,
                StandardCharsets.UTF_8);
        BufferedWriter sw = new BufferedWriter(writer);

        template.merge(context, sw);
        sw.flush();
        sw.close();
        outStream.close();

        System.out.println("成功生成文件:" + filePathWithFileName);
    }

    /**
     * 获取模板
     * @param templateFileName 模板文件名
     * @return
     */
    private static Template genTemplate(String templateFileName){
        VelocityEngine ve = buildVelocityEngine(userDir + templateDir);

        return ve.getTemplate(templateFileName, StandardCharsets.UTF_8.name());
    }

    /**
     * buildVelocityEngine
     * @param absoluteTemplateDir 模板的绝对路径
     * @return
     */
    private static VelocityEngine buildVelocityEngine(String absoluteTemplateDir){

        Properties pro = new Properties();
        pro.setProperty(Velocity.OUTPUT_ENCODING, StandardCharsets.UTF_8.name());
        pro.setProperty(Velocity.INPUT_ENCODING, StandardCharsets.UTF_8.name());
        pro.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, absoluteTemplateDir);
        return new VelocityEngine(pro);
    }

    /**
     * 构造模板变量
     * @return
     */
    private static VelocityContext buildVelocityContext(TargetFileConfig fileConfig){
        VelocityContext context = new VelocityContext();

        context.put("packagePath", fileConfig.getPackagePath());
        context.put("targetFileName", fileConfig.getFileName());
        context.put("fileFullPath", fileConfig.getFilePathWithFileName());


        String[] list= new String[]{"1","3"};
        context.put("productArr", list);

        // 执行add
        context.put("testProductArr", "1");
        context.put("testMap", "1");


        Map<String, String> kvMap = new HashMap<>();
        kvMap.put("k1","v1");
        kvMap.put("k2","v2");

        context.put("kvMap", kvMap);

        return context;
    }
}

结果

package com.example.demo.service.impl;

import java.lang.String;

public class YunTianServiceImpl {

        <li>value=1</li>
        <li>value=3</li>
    
        <li>Key: k1 ->Value: v1</li>
        <li>Key: k2 ->Value: v2</li>
    

}

推而广之,可以利用velocity生成任意模板化的项目文件。

Reference

  • https://www.cnblogs.com/codingsilence/archive/2011/03/29/2146580.html
  • https://www.cnblogs.com/niehaikuo/p/8873279.html
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Velocity进行代码生成的过程通常涉及以下几个步骤: 1. 准备模板文件:首先,你需要创建Velocity模板文件,它是用来描述生成代码的结构和内容的。模板文件通常使用`.vm`作为扩展名。 2. 配置Velocity引擎:接下来,你需要配置Velocity引擎,以便正确加载和解析模板文件。这涉及设置Velocity的属性,如模板路径、编码等。 3. 创建数据模型:在生成代码之前,你需要准备好所需的数据。可以创建一个Java对象作为数据模型,将需要的数据存储在该对象中。 4. 合并模板和数据:通过将数据模型与模板进行合并,可以生成最终的代码。这可以通过调用Velocity引擎的`mergeTemplate`方法来实现。你需要提供模板文件的路径和数据模型作为参数。 5. 输出生成的代码:最后,将生成的代码输出到所需的位置,如文件、控制台等。你可以使用Java的IO操作来实现。 以下是一个简单的示例代码,演示了使用Velocity生成Java类的过程: ```java import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; public class CodeGenerator { public static void main(String[] args) { // 配置Velocity引擎 Properties properties = new Properties(); properties.setProperty("resource.loader", "file"); properties.setProperty("file.resource.loader.path", "path/to/templates"); VelocityEngine velocityEngine = new VelocityEngine(); velocityEngine.init(properties); // 创建数据模型 VelocityContext context = new VelocityContext(); context.put("className", "MyClass"); context.put("packageName", "com.example"); // 合并模板和数据 Template template = velocityEngine.getTemplate("classTemplate.vm"); StringWriter writer = new StringWriter(); template.merge(context, writer); // 输出生成的代码到文件 try { File outputFile = new File("path/to/output/MyClass.java"); FileWriter fileWriter = new FileWriter(outputFile); fileWriter.write(writer.toString()); fileWriter.close(); System.out.println("代码生成完成!"); } catch (IOException e) { e.printStackTrace(); } } } ``` 在上述示例中,你需要将模板文件放置在指定的路径(`path/to/templates`),并创建一个名为`classTemplate.vm`的模板文件模板文件中可以使用Velocity的语法来定义代码结构和使用数据模型中的值。 当运行代码时,Velocity引擎将加载模板文件,合并数据模型,并将生成的代码输出到指定的位置(`path/to/output/MyClass.java`)。 这只是一个简单的示例,你可以根据需要进行更复杂的代码生成Velocity提供了丰富的语法和功能,可以根据你的需求来定制生成过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值