通过在 IntelliJ IDEA 中的 “Includes” 部分添加多个文件头模板,并在 “Files” 模板中利用这些包含来实现不同类型文件的注释。以下是为 Controller、Service、Mapper 文件设置不同文件头的完整示例:
File > Settings (在 macOS 上是 Preferences)> Editor > File and Code Templates > includes
在 “Includes” 选项卡中,创建以下三个文件头模板:
ControllerHeader
/**
* 控制层:
* Controller Class: ${NAME}
* @Author: ${USER}
* @Date: ${DATE} ${TIME}
* @Version: ${VERSION}
* @Description: ${DESCRIPTION}
*/
ServiceHeader
/**
* 服务层:
* Service Class: ${NAME}
* @Author: ${USER}
* @Date: ${DATE} ${TIME}
* @Version: ${VERSION}
* @Description: ${DESCRIPTION}
*/
MapperHeader
/**
* 数据层:
* Mapper Class: ${NAME}
* @Author: ${USER}
* @Date: ${DATE} ${TIME}
* @Version: ${VERSION}
* @Description: ${DESCRIPTION}
*/
File > Settings (在 macOS 上是 Preferences)> Editor > File and Code Templates > includes
${NAME.endsWith("Controller")}
这种写法专业名词叫Velocity 模板引擎
,关于该引擎在后续有详细介绍
#if (${NAME.endsWith("Controller")})
#parse("ControllerHeader.java")
#elseif (${NAME.endsWith("Service")})
#parse("ServiceHeader.java")
#elseif (${NAME.endsWith("Mapper")})
#parse("MapperHeader.java")
#else
/**
* Class: ${NAME}
* Author: ${USER}
* Date: ${DATE}
* Description: ${DESCRIPTION}
*/
#end
#if (${NAME.matches(".*Controller$")})
#parse("ControllerHeader.java")
#elseif ($NAME.matches(".*Service$") || $NAME.matches(".*ServiceImpl$"))
#parse("ServiceHeader.java")
#elseif (${NAME.matches(".*(Mapper|Dao|Repo)$")})
#parse("DataLayerHeader.java")
#else
/**
* Class: ${NAME}
* Author: ${USER}
* Date: ${DATE}
* Description: ${DESCRIPTION}
*/
#end
#if (${PACKAGE_NAME}.contains("controller"))
/**
* Controller层 - ${NAME}
* 包路径:${PACKAGE_NAME}
*/
#elseif (${PACKAGE_NAME}.contains("service"))
/**
* Service层 - ${NAME}
*/
#elseif (${PACKAGE_NAME}.contains("mapper"))
/**
* Mapper接口 - ${NAME}
*/
#end
#set($isMapperPackage = ${PACKAGE_NAME.contains(".mapper")} || ${PACKAGE_NAME.contains(".dao")})
#set($isServiceImplPackage = ${PACKAGE_NAME.contains(".service.impl")})
#if ($isMapperPackage && ($isMapper || ${NAME.endsWith("Repository")}))
#parse("mapperHeader.java")
#elseif ($isServiceImplPackage)
#parse("serviceImplHeader.java")
#end
UserController.java
、UserService.java
或 UserMapper.java
,IDEA 将根据文件名后缀自动应用相应的文件头注释。*Controller
、*Service
、*Mapper
的模式,以便条件判断能够正确匹配。在 IntelliJ IDEA 中创建需要的文件模板,比如 Controller、Service、Mapper,可以通过以下步骤来实现:
打开文件模板设置:
File
-> Settings
(在 macOS 上是 IntelliJ IDEA
-> Preferences
)。Editor
-> File and Code Templates
。创建新的文件模板:
Files
标签页中,点击右上角的 +
按钮,创建一个新的文件模板(如Controller)。Controller
、Service
、Mapper
,Controller
等,扩展名:java
。定义文件模板内容:
在模板的编辑器中输入你希望的文件内容。你可以使用变量来动态生成代码,如 ${NAME}
、${PACKAGE_NAME}
等。
例如,对于一个 Controller
模板,你可以这样定义:
package ${PACKAGE_NAME};
import org.springframework.web.bind.annotation.*;
#parse("ControllerHeader.java")
@RestController
@RequestMapping("/${NAME}")
public class ${NAME}Controller {
// Add your endpoints here
}
对于 Service
模板,可以这样定义:
package ${PACKAGE_NAME};
import org.springframework.stereotype.Service;
#parse("ServiceHeader.java")
@Service
public class ${NAME}Service {
// Add your service methods here
}
对于 Mapper
模板,可以这样定义:
package ${PACKAGE_NAME};
import org.apache.ibatis.annotations.Mapper;
#parse("MapperHeader.java")
@Mapper
public interface ${NAME}Mapper {
// Add your mapper methods here
}
使用模板:
New
-> Java Class
。Controller
、Service
、Mapper
)。通过这些步骤,你可以为常用的文件类型创建模板,提升开发效率和代码的一致性。
如**#set
** 是 Velocity 模板引擎的核心指令之一。以下为您完整解析 Velocity 的语法体系和学习路径:
以下是 Velocity 模板引擎核心指令的详细解析:
#set
- 变量赋值#set($var = "value") ## 字符串
#set($num = 10 + 5) ## 数值计算
#set($list = [1, 2, 3]) ## 列表
#set($map = {"key":"value"}) ## 键值对
特性:
特殊场景:
## 多变量赋值
#set($a = $b = 10)
## 空值处理
#set($result = $optionalValue ?: "default")
#if / #elseif / #else
- 条件分支#if($user.role == "admin")
ADMIN MODE
#elseif($user.age >= 18)
ADULT USER
#else
GUEST MODE
#end
判断规则:
条件表达式 | 判定为 false 的情况 |
---|---|
$var |
null、空字符串、空集合、false |
$var == 5 |
值不相等或类型不同 |
$list && $list.size() > 0 |
组合逻辑判断 |
#foreach
- 循环迭代#foreach($item in $items)
Item $foreach.index: $item.name
#if($foreach.count == 5)
#break ## 退出循环
#end
#end
循环变量:
属性 | 说明 |
---|---|
$foreach.index |
当前索引(从 0 开始) |
$foreach.count |
当前计数(从 1 开始) |
$foreach.first |
是否是第一次迭代(布尔值) |
$foreach.last |
是否是最后一次迭代(布尔值) |
#include
- 静态引入#include("header.html")
特点:
#include("head.html", "footer.html")
#parse
- 动态解析#parse("user_card.vm")
与 #include 对比:
特性 | #parse |
#include |
---|---|---|
语法解析 | ✅ 会解析 VTL 指令 | ❌ 原样输出 |
变量共享 | ✅ 共享当前上下文变量 | ❌ 无变量传递 |
性能 | 较低(需解析) | 较高(直接读取) |
#stop
- 引擎停止#if($error)
#stop ## 立即终止模板渲染
#end
使用场景:
#break
- 退出当前指令#foreach($item in $list)
#if($item == "stop")
#break ## 退出当前 #foreach 循环
#end
#end
作用范围:
#foreach
、#macro
)#evaluate
- 动态执行#set($template = "Hello $name")
#evaluate($template) ## 输出:Hello John
危险操作:
## 可能引发代码注入(慎用!)
#evaluate($userInput)
#define
- 定义代码块#define($block)
This is a reusable block
#end
## 调用
$block
特点:
#macro
- 定义可传参宏#macro(renderUser $user $isAdmin)
$user.name
#end
## 调用
#renderUser($currentUser true)
高级特性:
功能 | 示例 |
---|---|
默认参数 | #macro(show $msg="Hello") |
可变参数 | #macro(sum $nums...) |
嵌套调用 | 宏内可调用其他宏 |
指令 | 是否解析内容 | 是否共享变量 | 典型应用场景 |
---|---|---|---|
#include |
❌ | ❌ | 引入静态资源文件 |
#parse |
✅ | ✅ | 模块化动态模板 |
#define |
✅ | ✅ | 定义重复使用的静态内容块 |
#macro |
✅ | ✅ | 创建带参数的复用组件 |
避免 #evaluate
用户输入
## 危险!
#evaluate($request.getParameter("tpl"))
防御性模板设计
## 安全变量引用
$!{userInput} ## 自动处理 null
## 集合判空
#if($!{list} && $list.size() > 0)
性能优化
## 复杂计算预编译
#set($regex = "^\\d{4}-\\d{2}-\\d{2}$")
#if($dateStr.matches($regex))
## 用户列表模板 (user_list.vm)
#define($header)
User List
#include("styles.css")
#end
#macro(userCard $user)
#parse("user_avatar.vm")
$!{user.name}
#if($user.isAdmin)
ADMIN
#end
#end
$header
#foreach($user in $users)
#if($user.name == "root")
#stop ## 禁止显示 root 用户
#end
#userCard($user)
#if($foreach.count >= 100)
#break ## 最多显示 100 条
#end
#end
#parse("footer.vm")
以上内容可作为 Velocity 开发的权威参考,建议结合官方文档实践验证。每个指令的详细行为可能因 Velocity 版本略有差异(本文基于 2.x 版本)。
#set
指令详解#set($variable = "value")
## 字符串赋值
#set($className = "UserController")
## 数值计算
#set($total = 10 + 5 * 3) ## $total = 25
## 布尔逻辑
#set($isValid = $name && $name.length() > 5)
## 对象方法调用
#set($firstChar = $className.substring(0,1))
Velocity 的语法规则来源于以下渠道:
5.2.1. 官方文档
Apache Velocity 官网 (velocity.apache.org) 提供完整的 VTL (Velocity Template Language) 规范。
5.2.2. IDE 集成
#
时会自动弹出指令列表(如 #if
, #foreach
, #macro
)5.2.3. 开源项目实践
指令/语法 | 用途 | 示例 |
---|---|---|
变量引用 | 输出变量值 | $variable 或 ${variable} |
注释 | 添加模板注释 | ## 单行注释 或 #* 多行注释 *# |
#set | 变量赋值 | #set($price = 99.9) |
#if/#else/#elseif | 条件分支 | 见下方示例 |
#foreach | 循环遍历集合 | 见下方示例 |
条件判断示例:
#if($user.role == "admin")
管理员权限
#elseif($user.age > 18)
成年用户
#else
未成年用户
#end
循环示例:
#foreach($item in $items)
- ${foreach.index} - ${item.name}
#end
功能 | 说明 | 示例 |
---|---|---|
宏 (Macro) | 定义可复用的代码片段 | #macro(showError $msg) |
引入其他模板 | 模块化模板设计 | #parse("header.vm") |
内置工具对象 | 提供字符串/数学等工具方法 | $math.add(1,2) 或 $date.format('yyyy-MM-dd') |
转义输出 | 防止 XSS 攻击 | $!{userInput} 或 #escape($htmlContent) |
宏定义与调用:
## 定义宏
#macro(renderButton $text $color)
#end
## 调用宏
#renderButton("提交", "blue")
#[[ 不解析的内容 ]]#
#[[
这里的 $variable 不会被解析 → 直接输出 $variable
]]#
$variable.class.name ## 输出变量类型(如 java.lang.String)
在模板开发中常用以下语法:
需求场景 | 对应语法 |
---|---|
避免变量为 null 时报错 | $!{variable} |
字符串拼接 | #set($fullName = "$firstName $lastName") |
集合是否为空判断 | #if($list.isEmpty()) 或 `#if(!$list |
数值格式化 | $number.format("#,###", $price) |
日期格式化 | $date.format('yyyy-MM-dd', $today) |
5.5.1. 官方文档(必读)
5.5.2. 实战教程
5.5.3. IDE 辅助
.vm
文件,IDE 会提供:
#
触发)## 模板:user_profile.vm
#set($user = $data.getUser())
#set($birthday = $date.format('yyyy-MM-dd', $user.birthDate))
$!{user.name} 的资料
#if($user.isAdmin())
#end
用户信息
- 姓名:$!{user.name}
- 年龄:$math.sub($date.getYear(), $user.birthYear)
- 生日:$birthday
#macro(renderSection $title $content)
$title
$content
#end
#renderSection("联系方式", $user.contactInfo)
通过系统学习上述内容,您将能:
建议边学边实践,在 IntelliJ 中创建 .vm
文件体验实时语法反馈。
Velocity 确实不如 Freemarker、Thymeleaf 这类模板引擎知名度高,但它是一个历史悠久且特定场景下非常高效的模板引擎。以下是它的核心应用场景和特点解析,帮助您理解为什么某些场景(比如 IDEA 的注释模板)会选择它:
优势:
✅ 语法简单,适合非前端开发者使用
✅ 无复杂依赖,可嵌入任何 Java 环境
✅ 生成纯文本(代码/配置文件)时性能极高
现状:
⚠️ 新项目更推荐 Thymeleaf/FreeMarker(对现代前端更友好)
⚠️ 不支持响应式设计等现代特性
#set($dbHost = "192.168.1.100")
jdbc.url=jdbc:mysql://${dbHost}:3306/db
轻量级
无需引入额外依赖,IDEA 内置的模板引擎需要极低的开销。
逻辑简单
注释模板通常只需要变量替换和简单条件判断,例如:
/**
* @author ${USER}
* @date ${DATE}
#if(${DESCRIPTION})
* @description ${DESCRIPTION}
#end
*/
无副作用
不会像 FreeMarker 那样产生意外换行或空格(对代码格式敏感)。
特性 | Velocity | FreeMarker | Thymeleaf |
---|---|---|---|
学习曲线 | ⭐(最简单) | ⭐⭐ | ⭐⭐⭐(需懂 HTML) |
性能 | ⭐⭐⭐(最快) | ⭐⭐ | ⭐ |
前端友好度 | ❌(纯后端) | ✅ | ✅⭐⭐⭐(原生 HTML) |
动态代码生成 | ✅⭐⭐⭐ | ✅⭐ | ❌ |
社区活跃度 | ⭐(维护模式) | ⭐⭐⭐ | ⭐⭐⭐⭐ |
mapper.xml.vm
)
#foreach($field in ${table.fields})
#if(${field.keyFlag})
#else
#end
#end
Controller.java.vm
)#set($entity = ${table.entityName.toLowerCase()})
@RestController
@RequestMapping("/api/${entity}")
public class ${table.controllerName} {
@Autowired
private ${table.serviceName} ${entity}Service;
@GetMapping("/{id}")
public Result<${table.entityName}> getById(@PathVariable ${table.primaryKeyType} id) {
return Result.success(${entity}Service.getById(id));
}
}
需要生成代码/配置文件
(如自动生成 CRUD 代码、批量创建相似文件)
嵌入式模板需求
(如插件系统需要允许用户自定义模板)
历史项目维护
(老系统升级时保留原有模板)
功能局限
缺少模板继承、片段复用等现代特性,复杂页面难以维护。
前后端协作困难
设计师无法直接修改 HTML(模板语法混合在标签中)。
安全风险
默认不开启 HTML 转义,容易导致 XSS 攻击(需手动处理)。
.vm
<h1>$titleh1>
#foreach($item in $list)
<li>$itemli>
#end
如果您只需要一个轻量级文本生成工具(如代码注释、配置文件生成),Velocity 仍然是优秀选择。但对于 Web 页面开发,建议转向 FreeMarker/Thymeleaf 等现代引擎。