velocity模板引擎
文章目录
- 学习链接
- 一. velocity简介
- 1. velocity简介
- 2. 应用场景
- 3. velocity 组成结构
- 二. 快速入门
- 1. 需求分析
- 2. 步骤分析
- 3. 代码实现
- 3.1 创建工程
- 3.2 引入坐标
- 3.3 编写模板
- 3.4 输出结果
- 示例1
- 编写模板
- 测试
- 示例2
- 4. 运行原理
- 三. 基础语法
- 3.1 VTL介绍
- 3.2 VTL注释
- 3.2.1 语法
- 3.2.1 示例
- 3.3 非解析内容
- 3.3.1 语法
- 3.3.2 示例
- 3.4 引用
- **3.4.1 变量引用**
- 语法
- 示例
- 3.4.2 属性引用
- 语法
- 示例
- 3.4.3 方法引用
- 语法
- 示例
- 3.5 指令
- 3.5.1 流程控制
- #set
- #if/#elseif/#else
- #foreach
- 3.5.2 引入资源
- #include
- #parse
- #define
- #evaluate
- 3.5.3 宏指令
- 四. 综合案例
- 4.1 需求分析
- 4.2 步骤分析
- 4.3 代码实现
- 4.3.1 创建项目
- 4.3.2 导入依赖
- 4.3.3 编写模板
- Controller.java.vm
- Service.java.vm
- ServiceImpl.java.vm
- Dao.java.vm
- 4.3.4 生成代码
- 4.3.5 运行测试
学习链接
velocity模板引擎
freemarker模板引擎
thymleaf模板引擎
Apache Velocity Project 官网
Velocity Engine基础
Velocity 模板引擎使用介绍
黑马程序员Java进阶VelocityTools全套教程
一. 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渲染提供了一个单例模式,拿到了这个实例就可以完成渲染过程了。
二. 快速入门
1. 需求分析
使用velocity定义html模板 , 将动态数据填充到模板中 , 形成一个完整的html页面
2. 步骤分析
- 创建项目(maven)
- 引入依赖
- 定义模板
- 输出html
3. 代码实现
3.1 创建工程

3.2 引入坐标
<dependencies><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>
</dependencies>
3.3 编写模板
在项目resources目录下创建模板文件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>hello , ${name} !</body>
</html>
3.4 输出结果
@Test
public void test1() throws IOException {//设置velocity资源加载器Properties prop = new Properties();prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");Velocity.init(prop);//创建Velocity容器VelocityContext context = new VelocityContext();context.put("name", "zhangsan");//加载模板Template tpl = Velocity.getTemplate("vms/demo1.vm", "UTF-8");FileWriter fw = new FileWriter("D:\\work\\workspace\\velocity\\velocity_01\\src\\main\\resources\\html\\demo1.html");//合并数据到模板tpl.merge(context, fw);//释放资源fw.close();
}
示例1
编写模板
模板文件:resources/vms/template.vm
## 用户信息模板
#set($title = "用户详情")<!DOCTYPE html>
<html>
<head><title>$title</title>
</head>
<body>
<h1>$!{user.name} 的信息</h1>## 条件判断:是否显示年龄#if($user.age && $user.age > 0)<p>年龄:$user.age 岁</p>#else<p>年龄:未公开</p>#end## 循环输出朋友列表
<h2>好友列表(共 ${friends.size()} 人)</h2>
<ul>#foreach($friend in $friends)<li>${foreach.count}. $friend.name#if($friend.role == "admin")(管理员)#end</li>#end
</ul>## 使用宏简化代码#macro(showRole $role)#if($role == "admin")<span style="color: red;">管理员</span>#else<span style="color: blue;">普通用户</span>#end#end<p>角色:#showRole($user.role)</p>
</body>
</html>
测试
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import java.io.StringWriter;
import java.util.List;
import java.util.Properties;public class VelocityDemo {public static void main(String[] args) {// 1. 初始化引擎VelocityEngine velocityEngine = new VelocityEngine();Properties props = new Properties();props.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");velocityEngine.init(props);// 2. 创建上下文并填充数据VelocityContext context = new VelocityContext();context.put("user", new User("张三", 25, "admin"));context.put("friends", List.of(new User("ls", 25, "user"), new User("ww", 27, "user")));// 3. 加载模板(假设模板在 classpath 的 templates 目录)Template template = velocityEngine.getTemplate("vms/template.vm");// 4. 渲染结果StringWriter writer = new StringWriter();template.merge(context, writer);System.out.println(writer.toString());}
}
示例2
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;import java.io.StringWriter;
import java.util.List;public class InlineVelocityDemo {public static void main(String[] args) {// 1. 初始化 Velocity 引擎(无需配置文件)VelocityEngine velocityEngine = new VelocityEngine();velocityEngine.init(); // 使用默认配置// 2. 定义模板字符串(直接写在代码中)String templateString = """## 用户信息模板<h1>$!{user.name} 的信息 - $user.name - $!user.name</h1>#if($user.age > 0)<p>年龄:${user.age} 岁</p>#else<p>年龄:未公开</p>#end## 循环输出订单<h2>近期订单:</h2><ul>#foreach($order in $orders)<li>$foreach.count. $order.id $order.amount</li>#end</ul>""";// 3. 准备模板变量(模拟数据)VelocityContext context = new VelocityContext();context.put("user", new User("李雷", 30)); // 自定义对象context.put("orders", List.of(new Order("O2023001", 199.99),new Order("O2023002", 599.50)));// 4. 渲染模板try (StringWriter writer = new StringWriter()) {// 关键方法:直接解析字符串模板velocityEngine.evaluate(context, writer, "inline", templateString);// 5. 输出结果System.out.println(writer.toString());} catch (Exception e) {e.printStackTrace();}}}
4. 运行原理
Velocity解决了如何在后台程序和网页之间传递数据的问题,后台代码和视图之间相互独立,一方的修改不影响另一方 .
他们之间是通过环境变量(Context)来实现的,网页制作一方和后台程序一方相互约定好对所传递变量的命名约定,比如上个程序例子中的site, name变量,它们在网页上就是 n a m e , name , name,site 。
只要双方约定好了变量名字,那么双方就可以独立工作了。无论页面如何变化,只要变量名不变,那么后台程序就无需改动,前台网页也可以任意由网页制作人员修改。这就是Velocity的工作原理。

三. 基础语法
3.1 VTL介绍
Velocity Template Language (VTL) , 是Velocity 中提供的一种模版语言 , 旨在提供最简单和最干净的方法来将动态内容合并到网页中。简单来说VTL可以将程序中的动态数展示到网页中
VTL的语句分为4大类:注释 , 非解析内容 ** , 引用和指令**。
3.2 VTL注释
3.2.1 语法
1. 行注释
## 行注释内容
2. 块注释
#*
块注释内容1
块注释内容2
*#
3. 文档注释
#**
文档注释内容1
文档注释内容2
*#
3.2.1 示例
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
## 我是行注释#*
* 我是块注释
* 呵呵呵
* *##**
* 我是文档注释
*
* *#
hello , ${name} !</body>
</html>
3.3 非解析内容
所谓非解析内容也就是不会被引擎解析的内容。
3.3.1 语法
#[[
非解析内容1
非解析内容2
]]#
3.3.2 示例
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>hello , ${name} !<h1>非解析内容</h1>
#[[
直接输出的内容1
直接输出的内容2
${name}
]]#
</body>
</html>
3.4 引用
3.4.1 变量引用
引用语句就是对引擎上下文对象中的属性进行操作。语法方面分为常规语法($属性)和正规语法(${属性})。
语法
$变量名, 若上下文中没有对应的变量,则输出字符串"$变量名"
${变量名},若上下文中没有对应的变量,则输出字符串"${变量名}"
$!变量名, 若上下文中没有对应的变量,则输出空字符串""
$!{变量名}, 若上下文中没有对应的变量,则输出空字符串""
示例
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>引用变量</h1>
常规语法 : $name
正规语法 : ${name}## 如果获取的变量不存在, 表达式会原样展示 , 如果不想展示 , 可以使用 $!变量名
## 以下写法的含义代表么如果有变量, 那么获取变量值展示, 没有变量展示""
常规语法 : $!name
正规语法 : $!{name}</body>
</html>
3.4.2 属性引用
语法
$变量名.属性, 若上下文中没有对应的变量,则输出字符串"$变量名.属性"
${变量名.属性} 若上下文中没有对应的变量,则输出字符串"${变量名.属性}"
$!变量名.属性 若上下文中没有对应的变量,则输出字符串""
$!{变量名.属性} 若上下文中没有对应的变量,则输出字符串""
示例
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>引用属性</h1>
常规语法 : $user.username --- $user.password
正规语法 : ${user.username} --- ${user.password}正规语法 : ${user.email} --- ${user.email}
正规语法 : $!{user.email} --- $!{user.email}</body>
</html>
3.4.3 方法引用
方法引用实际就是指方法调用操作,关注点返回值和参数 , 方法的返回值将输出到最终结果中
语法
$变量名.方法([入参1[, 入参2]*]?), 常规写法
${变量名.方法([入参1[, 入参2]*]?)}, 正规写法$!变量名.方法([入参1[, 入参2]*]?), 常规写法
$!{变量名.方法([入参1[, 入参2]*]?)}, 正规写法
示例
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>引用属性</h1>
$str.split(" ")
${str.split(" ")}
$time.getTime()
${time.getTime()}</body>
</html>
3.5 指令
指令主要用于定义重用模块、引入外部资源、流程控制。指令以 # 作为起始字符。
3.5.1 流程控制
#set
作用 : 在页面中声明定义变量
语法: #set($变量 = 值)
示例 :
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>set指令</h1>
#set($str = "hello world")
#set($int = 1)
#set($arr = [1,2])
#set($boolean = true)
#set($map = {"key1":"value1", "key2":"value2"})## 在字符串中也可以引用之前定义过的变量
#set($str2 = "$str , how are you !")
#set($str3 = '$str , how are you !')<h1>获取set指令定义的变量</h1>
${str}
${int}
${arr}
${boolean}
${map.key1}--${map.key2}
${str2}
${str3}</body>
</html>
#if/#elseif/#else
作用 : 进行逻辑判断
语法 :
#if(判断条件).........
#elseif(判断条件).........
#else.........
#end
示例 :
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>if/elseif/else指令</h1>
#set($language="PHP")#if($language.equals("JAVA"))java开发工程师
#elseif($language.equals("PHP"))php开发工程师
#else开发工程师
#end</body>
</html>
#foreach
作用 : 遍历循环数组或者集合
格式:
#foreach($item in $items)..........[#break]
#end
- $items : 需要遍历的对象或者集合
- 如果items的类型为map集合, 那么遍历的是map的value
- $item : 变量名称, 代表遍历的每一项
- break : 退出循环
- 内置属性 :
- $foreach.index : 获取遍历的索引 , 从0开始
- $foreach.count : 获取遍历的次数 , 从1开始
示例 :
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>遍历数组</h1>
#foreach($hobby in $hobbies)$foreach.index -- $foreach.count -- $hobby <br>${foreach.index} -- ${foreach.count} -- ${hobby} <br>
#end<h1>变量对象集合</h1>
<table border="1px" align="center"><tr><td>编号</td><td>用户名</td><td>密码</td><td>邮箱</td><td>年龄</td><td>操作</td></tr>#foreach($user in $users)<tr><td>${foreach.index}</td><td>${user.username}</td><td>${user.password}</td><td>$user.email</td><td>$user.age</td><td><a href="">编辑</a><a href="">删除</a></td></tr>#end
</table><h1>遍历map集合</h1>
<h2>遍历值</h2>#foreach($value in $map)$value#end<h2>遍历键值对</h2>
#foreach($entry in $map.entrySet())$entry.key -- $entry.value
#end</body>
</html>
3.5.2 引入资源
#include
作用 : 引入外部资源 , 引入的资源不会被引擎所解析
语法 : #include(resource)
- resource可以为单引号或双引号的字符串,也可以为**$变量**,内容为外部资源路径。
- 注意 : 路径如果为相对路径,则以
引擎配置的文件加载器加载路径作为参考
示例 :
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><!-- 1、将hello.vm的内容全部引入, 2、如果引入的内容中有模板表达式的话,不会对内部的内容进行模板解析 -->
#include("vms/hello.vm")</body>
</html>
#parse
作用 : 引入外部资源 , 引入的资源将被引擎所解析
语法 : #parse(resource)
- resource可以为单引号或双引号的字符串,也可以为**$变量**,内容为外部资源路径。
- 注意 : 路径如果为相对路径,则以引擎配置的文件加载器加载路径作为参考系
示例 :
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><!-- 1、将hello.vm的内容全部引入, 2、如果引入的内容中有模板表达式的话,会对内部的内容进行模板解析 -->
#include("vms/hello.vm")</body>
</html>
#define
作用 : 定义重用模块(不带参数)
语法 :
#define($模块名称)模块内容
#end
示例 :
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>定义模块</h1><!-- define定义的内容中,可以使用模板表达式 -->#define($table)<table border="1px" align="center"><tr><td>编号</td><td>用户名</td><td>密码</td><td>邮箱</td><td>年龄</td><td>操作</td></tr>#foreach($user in $users)<tr><td>${foreach.index}</td><td>${user.username}</td><td>${user.password}</td><td>$user.email</td><td>$user.age</td><td><a href="">编辑</a><a href="">删除</a></td></tr>#end</table>#end<h1>使用模块</h1>$table$table$table</body>
</html>
#evaluate
作用 : 动态计算 , 动态计算可以让我们在字符串中使用变量
语法 : #evalute("计算语句")
示例 :
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>动态计算</h1>#set($name = "over")#if($name=='over')over#elsenot over#end## 直接使用#evaluate("#if($name=='over') over #else not over #end")## code是context中设置的变量, 它是字符串类型, 内容是: #if($name=='over') over #else not over #end## 这里也可以解析出来#evaluate($code)</body>
</html>
3.5.3 宏指令
作用 : 定义重用模块(可带参数)
语法 :
定义语法
#macro(宏名 [$arg]?).....
#end
调用语法
#宏名([$arg]?)
**示例 : **
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><h1>定义宏</h1>#macro(table $list)<table border="1px"><tr><td>编号</td><td>用户名</td><td>密码</td><td>邮箱</td><td>年龄</td><td>操作</td></tr>#foreach($item in $list)<tr><td>${foreach.count}</td><td>${item.username}</td><td>${item.password}</td><td>${item.email}</td><td>${item.age}</td><td><a href="">编辑</a><a href="">删除</a></td></tr>#end</table>#end<h1>调用宏</h1>#table($users)</body>
</html>
四. 综合案例
4.1 需求分析
在实际项目开发过程中, 编写基础的CRUD操作代码, 往往会花费我们大量的时间 , 而且这些CRUD代码的基础结构基本上是固定的 , 如果能有一个代码生成器 , 能够帮助我们把这些代码生成出来 , 我们就可以节省出大量的时间关注核心业务代码的开发, 大大提高了我们的开发效率 !
需求 : 使用velocity实现一个简单的代码生成器 , 生成项目开发过程中的基础CRUD代码
4.2 步骤分析
- 创建项目
- 导入依赖
- 编写模板
- 生成代码
4.3 代码实现
4.3.1 创建项目

4.3.2 导入依赖
<dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.2</version>
</dependency>
4.3.3 编写模板
一般我们的项目开发将项目分为三层 , 我们的代码生成器就基于传统的三层架构生成代码 , 所以我们需要为每一层的每一个类创建模板 , 所以需要有如下模板 :
- Controller.java.vm : 控制层模板
- Service.java.vm : 业务层接口模板
- ServiceImpl.java.vm : 业务层实现模板
- Dao.java.vm : 数据服务层模板(数据访问层基于通用Mpper实现)
Controller.java.vm
package ${package}.controller;import ${package}.pojo.${className};
import ${package}.service.${className}Service;
import ${package}.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;
import java.util.Map;@RestController
@RequestMapping("/${classname}")
public class ${className}Controller {@Autowiredprivate ${className}Service ${classname}Service ;/*** 查询列表* @return*/@RequestMapping("/list")public Result list(){List<${className}> ${classname}s = null;try {${classname}s = ${classname}Service.list();return Result.ok(${classname}s);} catch (Exception e) {e.printStackTrace();return Result.error("查询数据异常");}}/*** 保存* @param ${classname}* @return*/@RequestMapping("/save")public Result save(@RequestBody ${className} ${classname}){try {${classname}Service.save(${classname});return Result.ok("新增数据成功");} catch (Exception e) {e.printStackTrace();return Result.error("新增数据异常");}}/*** 更新* @param ${classname}* @return*/@RequestMapping("/update")public Result update(@RequestBody ${className} ${classname}){try {${classname}Service.update(${classname});return Result.ok("修改数据成功");} catch (Exception e) {e.printStackTrace();return Result.error("修改数据异常");}}/*** 删除* @param ids* @return*/@RequestMapping("/delete")public Result delete(@RequestBody Integer[] ids){try {${classname}Service.delete(ids);return Result.ok("删除数据成功");} catch (Exception e) {e.printStackTrace();return Result.error("删除数据异常");}}
}
Service.java.vm
package ${package}.service;import com.itheima.pojo.${className};import java.util.List;
import java.util.Map;public interface ${className}Service {/*** 查询数据列表* @return*/List<${className}> list();/*** 保存数据* @param ${classname}*/void save(${className} ${classname});/*** 更新数据* @param ${classname}*/void update(${className} ${classname});/*** 删除数据* @param ids*/void delete(Integer[] ids);
}
ServiceImpl.java.vm
package ${package}.service.impl;import ${package}.dao.${className}Dao;
import ${package}.pojo.${className};
import ${package}.service.${className}Service;
import org.springframework.beans.factory.annotation.Autowired;import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;public class ${className}ServiceImpl implements ${className}Service {@Autowiredprivate ${className}Dao ${classname}Dao ;public List<${className}> list() {return ${classname}Dao.selectAll();}public void save(${className} ${classname}) {${classname}Dao.insert(${classname});}public void update(${className} ${classname}) {${classname}Dao.updateByPrimaryKey(${classname});}public void delete(Integer[] ids) {Stream.of(ids).forEach(${classname}Dao::deleteByPrimaryKey);}
}
Dao.java.vm
package ${package}.dao;import com.itheima.pojo.${className};
import tk.mybatis.mapper.common.Mapper;public interface ${className}Dao extends Mapper<${className}> {
}
4.3.4 生成代码
我们可以封装一个生成代码的工具类 , 后期生成代码运行工具类即可
package com.itheima.utils;import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;/*** 代码生成器 工具类*/
public class GenUtils {private static String currentTableName;public static List<String> getTemplates() {List<String> templates = new ArrayList<String>();templates.add("vms/Controller.java.vm");templates.add("vms/Service.java.vm");templates.add("vms/ServiceImpl.java.vm");templates.add("vms/Dao.java.vm");return templates;}/*** 生成代码*/public static void generatorCode(Map<String, Object> data, List<String> templates, ZipOutputStream zip) {//设置velocity资源加载器Properties prop = new Properties();prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");Velocity.init(prop);//封装模板数据VelocityContext context = new VelocityContext(data);//获取模板列表for (String template : templates) {//渲染模板StringWriter sw = new StringWriter();Template tpl = Velocity.getTemplate(template, "UTF-8");tpl.merge(context, sw);try {//添加到zipzip.putNextEntry(new ZipEntry(getFileName(template, data.get("className").toString(),data.get("package").toString())));IOUtils.write(sw.toString(), zip, "UTF-8");IOUtils.closeQuietly(sw);} catch (IOException e) {e.printStackTrace();}}}/*** 获取文件名 , 每个文件所在包都不一样, 在磁盘上的文件名几路径也各不相同*/public static String getFileName(String template, String className,String packageName) {String packagePath = "main" + File.separator + "java" + File.separator;if (StringUtils.isNotBlank(packageName)) {packagePath += packageName.replace(".", File.separator) + File.separator;}if (template.contains("Dao.java.vm")) {return packagePath + "dao" + File.separator + className + "Dao.java";}if (template.contains("Service.java.vm")) {return packagePath + "service" + File.separator + className + "Service.java";}if (template.contains("ServiceImpl.java.vm")) {return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";}if (template.contains("Controller.java.vm")) {return packagePath + "controller" + File.separator + className + "Controller.java";}return null;}
}
4.3.5 运行测试
public class GeneratorCodeTest {public static void main(String[] args) throws IOException {Map<String,Object> data = new HashMap<String,Object>();data.put("className","Product");data.put("classname","product");data.put("package","com.itheima");File file = new File("D:\\Users\\Desktop\\code.zip");FileOutputStream outputStream = new FileOutputStream(file);ZipOutputStream zip = new ZipOutputStream(outputStream);GenUtils.generatorCode(data, GenUtils.getTemplates(), zip);zip.close();}
}
运行完毕之后, 可以看到输出路径下回自动生成一个压缩文件 , 解压之后将里面的代码copy到我们的项目之中即可 !
相关文章:
velocity模板引擎
文章目录 学习链接一. velocity简介1. velocity简介2. 应用场景3. velocity 组成结构 二. 快速入门1. 需求分析2. 步骤分析3. 代码实现3.1 创建工程3.2 引入坐标3.3 编写模板3.4 输出结果示例1编写模板测试 示例2 4. 运行原理 三. 基础语法3.1 VTL介绍3.2 VTL注释3.2.1 语法3.2…...
word选中所有的表格——宏
Sub 选中所有表格()Dim aTable As TableApplication.ScreenUpdating FalseActiveDocument.DeleteAllEditableRanges wdEditorEveryoneFor Each aTable In ActiveDocument.TablesaTable.Range.Editors.Add wdEditorEveryoneNextActiveDocument.SelectAllEditableRanges wdEdito…...
13.第二阶段x64游戏实战-分析人物等级和升级经验
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 上一个内容:12.第二阶段x64游戏实战-远程调试 效果图: 如下图红框,…...
容器化-Docker-基础
一、Docker 核心概念 1、容器化技术的本质 Docker 是基于 Linux 内核的轻量级容器化技术,通过 Namespace 和 Cgroups 实现资源隔离与限制,将应用及其依赖封装成可移植的容器。与传统虚拟机(需模拟完整硬件层)不同,Docker 容器共享宿主机内核,启动时间以秒级计算,资源占…...
六边形棋盘格(Hexagonal Grids)的坐标
1. 二位坐标转六边形棋盘的方式 1-1这是“波动式”的 这种就是把【方格子坐标】“左右各错开半个格子”做到的 具体来说有如下几种情况 具体到庙算平台上,是很巧妙的用一个4位整数,前两位为x、后两位为y来进行表示 附上计算距离的代码 def get_hex_di…...
SICAR 标准 安全门锁操作箱 按钮和指示灯说明
1、安全门锁操作箱 2、按钮和指示灯说明 一、指示灯说明 红灯: 常亮:表示安全门已解锁;闪烁:表示安全门未复位;熄灭:表示安全门已复位。 黄灯: 常亮:表示处于维修模式。 绿灯&…...
Day10【基于encoder- decoder架构实现新闻文本摘要的提取】
实现新闻文本摘要的提取 1. 概述与背景2.参数配置3.数据准备4.数据加载5.主程序6.预测评估7.生成效果8.总结 1. 概述与背景 新闻摘要生成是自然语言处理(NLP)中的一个重要任务,其目标是自动从长篇的新闻文章中提取出简洁、准确的摘要。近年来…...
【blender小技巧】使用blender的Cats Blender Plugin插件将3D人物模型快速绑定或者修复为标准的人形骨骼
文章目录 前言绑定或者修复人形骨骼1、下载模型2、导入模型到blender中3、删除无用的相机和灯光3、导出模型并在unity中使用 专栏推荐完结 前言 有时候我们下载的3D人物模型,可能不带骨骼信息,或者带一些错乱的骨骼信息。这时候我们就可以使用blender将…...
Linux——firewalld防火墙(笔记)
目录 一:Firewalld防火墙的概述 (1)firewalld简介 (2)firewalld&iptables的关系 (3)firewalld与iptables service的区别 1. 规则管理方式 2. 默认策略与设计逻辑 3. 配置文…...
《分布式软总线赋能老旧设备高效通信》
在数字化转型的浪潮中,分布式软总线技术成为实现设备互联互通的关键力量。然而,当面对大量老旧设备时,其性能受限的现状对分布式软总线提出了严峻挑战。如何在这些性能瓶颈下,让老旧设备实现高效连接与通信,是亟待解决…...
YOLO拓展-锚框(anchor box)详解
一.锚框(anchor box)概述 1.1什么是锚框 锚框就是一种进行预测的像素框,通过遍历输入图像上所有可能的像素框,然后选出正确的目标框,并对位置和大小进行调整就可以完成目标检测任务。 对于yolo锚框的建设须基于实际…...
GPU渲染阶段介绍+Shader基础结构实现
GPU是什么 (CPU)Center Processing Unit:逻辑编程 (GPU)Graphics Processing Unit:图形处理(矩阵运算,数据公式运算,光栅化) 渲染管线 渲染管线也称为渲染流水线&#x…...
第32讲:卫星遥感与深度学习融合 —— 让地球“读懂”算法的语言
目录 🔍 一、讲讲“遥感+深度学习”到底是干啥的? ✅ 能解决什么问题? 🧠 二、基础原理串讲:深度学习如何“看懂”遥感图? 🛰 遥感图像数据类型: 🧠 CNN的基本思路: 🧪 三、实战案例:用CNN对遥感图像做地类分类 📦 所需R包: 🗂️ 步骤一:构建训…...
kubernetes》》k8s》》Service
Kubernetes 中的 Service 是用于暴露应用服务的核心抽象,为 Pod 提供稳定的访问入口、负载均衡和服务发现机制。Service在Kubernetes中代表了一组Pod的逻辑集合,通过创建一个Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址…...
多道程序和多任务操作系统区别
多道程序 vs. 多道任务:对比分析 ✅ 共同点 方面共同特征核心机制都依赖于进程/任务切换执行需求实现多个程序或任务"并发"执行系统支持都需要操作系统的支持(如调度算法、内存管理)本质目标提高资源利用率(CPU不空转…...
CMFA在自动驾驶中的应用案例
CMFA在自动驾驶中的典型应用案例 CMFA(Cross-Modal Feature Alignment)方法在自动驾驶领域有多个成功的应用场景,以下是几个典型案例: 1. 多模态3D目标检测 应用场景:车辆、行人、骑行者等交通参与者的精确检测 …...
已注册商标如何防止被不使用撤销!
近年来已注册商标被撤销越来越多,不乏著名企业或机构,普推知产商标老杨看到前一阵看到央视和百度等申请的商标也被申请撤销,连续三年不使用撤销也是正常的商标流程。 已注册商标被撤销普推老杨看到案例主要是集中在一些早期申请注册的好记的商…...
android 打包内容 安卓打包工具有哪些
Android ROM打包工具与技巧分享 eMMC存储与Android文件系统 eMMC作为手机和平板电脑的内嵌式存储器,因其集成了控制器并提供标准接口等优势,受到Android厂商青睐。采用eMMC存储的Android手机,其文件系统(system、data分区)通常采用ext4格式…...
管理与维护samba服务器
允许 Linux、Unix 系统与 Windows 系统之间进行文件和打印机共享,使得不同操作系统的用户能够方便地访问和共享资源,就像在同一局域网中的 Windows 计算机之间共享资源一样。 server01安装Samba服务器 [rootserver ~]# rpm -qa | grep samba [rootserver…...
EAGLE代码研读+模型复现
要对代码下手了,加油(ง •_•)ง 作者在他们自己的设备上展现了推理的评估结果,受第三方评估认证,EAGLE为目前最快的投机方法(虽然加速度是评估投机解码方法的主要指标,但其他点也值得关注。比如PLD和Lookahead无需额…...
2024期刊综述论文 Knowledge Graphs and Semantic Web Tools in Cyber Threat Intelligence
发表在期刊Journal of Cybersecurity and Privacy上,专门讲知识图谱技术和语义Web工具在网络威胁情报领域的作用,还把本体和知识图谱放在相同的地位上讨论。 此处可以明确一点:本体和知识图谱都可以用于网络威胁情报的应用,当然也…...
vue3+vite 多个环境配置
同一套代码 再也不用在不同的环境里来回切换请求地址了 然后踩了一个坑 就是env的文件路径是在当前项目下 不是在views内 因为公司项目需求只有dev和pro两个环境 虽然我新增了3个 但是只在这两个里面配置了 .env是可以配置一些公共配置的 目前需求来说不需要 所以我也懒得配了。…...
秒杀系统解决两个核心问题的思路方法总结:1.库存超卖问题;2.用户重复抢购问题。
秒杀系统解决两个核心问题 秒杀系统解决两个核心问题:一、解决库存超卖的核心逻辑:解释:原子性保证: 二、如何避免重复抢购:使用 Redis 做唯一标识判断优点: 三、流程完整梳理:四、通过数据库建…...
linux socket编程之udp(实现客户端和服务端消息的发送和接收)
目录 一.创建socket套接字(服务器端) 二.bind将prot与端口号进行绑定(服务器端) 2.1填充sockaddr_in结构 2.2bind绑定端口 三.直接通信(服务器端) 3.1接收客户端发送的消息 3.2给客户端发送消息 四.客户端通信 4.1创建socket套接字 4.2客户端bind问题 4.3直接通信即可…...
SAP HANA使用命令行快速导出导入
楔子 今天折腾了接近一下午,就为了使用SAP HANA自带的命令行工具来导出数据备份。 SAP HANA(后续简称Hana)是内存数据库,性能这一方面上还真没怕过谁。 由于SAP HANA提供了Hana Studio这个桌面工具来方便运维和DBA使用…...
goland做验证码识别时报“undefined: gosseract.NewClient”
gosseract 应该有 和 c 相关的配置库因此需要安装 cgo 并且启用 CGO_ENABLED 在cmd下面输入这个 go env -w CGO_ENABLED1 接着输入 go env 验证是否设置成功 解决了这个问题后 “undefined: gosseract.NewClient” 又出现了 # runtime/cgo …...
计算机网络 实验四 静态路由的配置与应用
一、实验目的 掌握路由器基础工作原理及静态路由协议机制熟练使用华为ENSP网络模拟器进行拓扑设计与设备配置建立系统化的网络故障排除思维通过实践验证静态路由在中小型网络中的部署优势 二、实验环境 硬件配置:标准PC终端软件工具:华为企业网络模拟…...
Vue自定义指令-防抖节流
Vue2版本 // 防抖 // <el-button v-debounce"[reset,click,300]" ></el-button> // <el-button v-debounce"[reset]" ></el-button> Vue.directive(debounce, { inserted: function (el, binding) { let [fn, event "cl…...
[每周一更]-(第140期):sync.Pool 使用详解:性能优化的利器
文章目录 一、什么是 sync.Pool?二、sync.Pool 的基本作用三、sync.Pool 的主要方法四、sync.Pool 的内部工作原理五、sync.Pool 适用场景六、使用示例示例 1:基本使用输出示例:示例 2:并发使用 七、一个基于 sync.Pool 的 **Benc…...
3.QT-信号和槽|自定义槽函数|自定义信号}自定义的语法}带参数的信号和槽(C++)
信号和槽 Linux信号 Signal 系统内部的通知机制. 进程间通信的方式. 信号源:谁发的信号.信号的类型:哪种类别的信号信号的处理方式:注册信号处理函数,在信号被触发的时候自动调用执行. Qt中的信号和Linux中的信号,虽…...
