本文最后更新于 2024-04-01,欢迎来到我的Blog! https://www.zpeng.site/

RuoYi学习-代码生成(generate)

1.代码生成使用

1、登录系统(系统工具 -> 代码生成 -> 导入对应表)

2、代码生成列表中找到需要表(可预览、编辑、同步、删除生成配置)

3、点击生成代码会得到一个ruoyi.zip执行sql文件,按照包内目录结构复制到自己的项目中即可

代码生成支持编辑、预览、同步

预览:对生成的代码提前预览,防止出现一些不符合预期的情况。

同步:对原表的字段进行同步,包括新增、删除、修改的字段处理。

修改:对生成的代码基本信息、字段信息、生成信息做一系列的调整。

另外多模块所有代码生成的相关业务逻辑代码在ruoyi-generator模块,不需要可以自行删除模块。

2.导入

src/main/java/com/ruoyi/generator/controller/GenController.java

/**
 * 导入表结构(保存)
 */
@PreAuthorize("@ss.hasPermi('tool:gen:import')")
@Log(title = "代码生成", businessType = BusinessType.IMPORT)
@PostMapping("/importTable")
public AjaxResult importTableSave(String tables)
{
    String[] tableNames = Convert.toStrArray(tables);
    // 查询表信息
    List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
    genTableService.importGenTable(tableList, SecurityUtils.getUsername());
    return success();
}

insert into gen_table_column保存列信息

src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java

3.预览

    /**
     * 预览代码
     */
    @PreAuthorize("@ss.hasPermi('tool:gen:preview')")
    @GetMapping("/preview/{tableId}")
    public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException
    {
        Map<String, String> dataMap = genTableService.previewCode(tableId);
        return success(dataMap);
    }
 @Override
    public Map<String, String> previewCode(Long tableId)
    {
        Map<String, String> dataMap = new LinkedHashMap<>();
        // 查询表信息
        GenTable table = genTableMapper.selectGenTableById(tableId);
        // 设置主子表信息
        setSubTable(table);
        // 设置主键列信息
        setPkColumn(table);
        VelocityInitializer.initVelocity();

        VelocityContext context = VelocityUtils.prepareContext(table);

        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
        for (String template : templates)
        {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(context, sw);
            dataMap.put(template, sw.toString());
        }
        return dataMap;
    }

4.生成

    /**
     * 生成代码(下载方式)
     */
    @PreAuthorize("@ss.hasPermi('tool:gen:code')")
    @Log(title = "代码生成", businessType = BusinessType.GENCODE)
    @GetMapping("/download/{tableName}")
    public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
    {
        byte[] data = genTableService.downloadCode(tableName);
        genCode(response, data);
    }

5.velocity模板引擎

1.velocity简介

Velocity是一个基于Java的模板引擎,可以通过特定的语法获取在java对象的数据 , 填充到模板中,从而实现界面和java代码的分离 !

2. 应用场景

  • Web应用程序 : 作为为应用程序的视图, 展示数据。

  • 源代码生成 : Velocity可用于基于模板生成Java源代码

  • 自动电子邮件 : 网站注册 , 认证等的电子邮件模板

  • 网页静态化 : 基于velocity模板 , 生成静态网页

3. velocity 组成结构

Velocity主要分为app、context、runtime和一些辅助util几个部分。

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

  • Context模块 : 主要封装了模板渲染需要的变量

  • Runtime模块 : 整个Velocity的核心模块,Runtime模块会将加载的模板解析成语法树,Velocity调用mergeTemplate方法时会渲染整棵树,并输出最终的渲染结果。

  • RuntimeInstance类为整个Velocity渲染提供了一个单例模式,拿到了这个实例就可以完成渲染过程了。

4.使用

添加依赖

        <!-- velocity代码生成使用模板 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
        </dependency>

新建vm文件

hello 
#foreach($name in $names)
$name
#end
 
#foreach($name in $citys)
$name
#end

新建java文件

public class Context {
	public static void main(String[] args) throws Exception {
		Velocity.init();
		
		VelocityContext ctx = new VelocityContext();
		Vector v = new Vector();
		v.addElement("Shanghai");
		v.addElement("Beijing");
		
		Object[] objs = {"word","世界"};
		
		ctx.put("names", objs);
		ctx.put("citys", v);
		
		Template tem = null;
		tem = Velocity.getTemplate("myTemplate.vm");
		StringWriter writer = new StringWriter();
		tem.merge(ctx, writer);
		
		
		System.out.println(writer.toString());
		        /* 输出流输出到文件*/
		PrintWriter filewriter = new PrintWriter(new FileOutputStream("E:/i.html"), true); 
		        filewriter.print(writer.toString());
		        filewriter.close();
	}
}


设置velocity的资源加载器;
初始化velocity引擎;
创建velocity容器;
加载velocity模板文件;
合并数据到模板文件;
输出合并后的结构流或者文件;
释放资源。
登录后复制 
//实例化资源加载器
Properties p = new Properties();

 // 加载classpath目录下的vm文件
p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");

// 定义字符集
p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8);

// 初始化Velocity引擎,指定配置Properties
Velocity.init(p);

//创建容器,加入渲染模板需要的变量
VelocityContext velocityContext = new VelocityContext();
velocityContext .put("varName","varValue");

//根据模板名称装载模板对象
Template tpl = Velocity.getTemplate("templateName", Constants.UTF8);

// 渲染模板:输出为字符串时使用
StringWriter sw = new StringWriter();

// 渲染模板:输出到指定文件时使用
FileWriter  fw= new FileWriter("fileName");


//执行数据+模板合并,输出最终结果
  tpl.merge(velocityContext , sw);
  tpl.merge(velocityContext , fw);

//释放资源
sw.close();
fw.close();

测试运行

hello word 世界 Shanghai Beijing

5.语法

1、注释:注释包括行注释、块注释、文档注释。这些注释只用于开发者阅读,不会被生成到输出文件/流中。

## 这是一个单行注释

#*
*
*  这是多行注释
*
* *#

#**
*
*  这是文档注释
*
* *#1.2.3.4.5.6.7.8.9.10.11.12.13.

 2、非解析内容:这部分内容将会被原样显示,即使包含变量占位符也不会被替换。

#[[
.....

这里面的内容将被原样输出,即使存在变量占位符${xxx}也不会被替换。
......

]]#1.2.3.4.5.6.7.

3、变量引用、属性引用、方法引用:引用是对引擎上下文对象中的属性进行调用,分为常规语法($xxx)和正规语法(${xxx})。

$变量名:若上下文中没有对应的变量,则输出字符串"$变量名"
${变量名}:若上下文中没有对应的变量,则输出字符串"${变量名}"
$!变量名:若上下文中没有对应的变量,则输出空字符串""
$!{变量名}:若上下文中没有对应的变量,则输出空字符串""

$变量名.属性:若上下文中没有对应的变量,则输出字符串"$变量名.属性"
${变量名.属性}:若上下文中没有对应的变量,则输出字符串"${变量名.属性}"
$!变量名.属性:若上下文中没有对应的变量,则输出空字符串""
$!{变量名.属性}:若上下文中没有对应的变量,则输出空字符串""

$变量名.方法([入参1[,入参2]*]?)
${变量名.方法([入参1[,入参2]*]?)}
$!变量名.方法([入参1[,入参2]*]?)
$!{变量名.方法([入参1[,入参2]*]?)}1.2.3.4.5.6.7.8.9.10.11.12.13.14.

4、指令:主要用于定义重用模块、引入外部资源、流程控制。指令以#作为起始字符。

/**
*#set指令用于定义一个变量
**/
#set($变量=值) 

/**
*#if #else 用于条件判断,#end表示结束
**/
#if(判断条件)
..............
#elseif(判断条件)
..............
#else
..............
#end

/**
*#foreach 用于循环变量一个集合; #break用于结束循环,可选;在循环体内可以使用$foreach.index/$foreach.count获取遍历的索引和次数
**/
#foreach($item in $items)
     .............
     [#break]
     .............
#end1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.

5、引用:用于引入资源。

/**
* #include用于引入一个外部资源,参数resourcePath指定资源的路径,该资源不会被解析器解析
*/
#include(resourcePath)

/**
* #parse用于引入一个外部资源,参数resourcePath指定资源的路径,该资源会被解析器解析
*/
#parse(resourcePath)

/**
* #define用于定义重用模块,不可携带参数。定义后可使用 $模块名称 来引用
*/
#define($模块名称)
.....模块内容.....
#end

/**
* #macro用于定义重用模块,可以携带参数。定义后可以使用 #宏名称(实数) 指令进行调用
*/
#macro(宏名称 [可选参数])
.....模块内容.....
#end

/**
* #evaluate用于动态计算,参数express为计算表达式字符串。evaluate方法可以把字符串当作代码进行运行并得出结果
*/
#evaluate(express)