通過在 IntelliJ IDEA 中的 “Includes” 部分添加多個文件頭模板,并在 “Files” 模板中利用這些包含來實現不同類型文件的注釋。以下是為 Controller、Service、Mapper 文件設置不同文件頭的完整示例:
1. 設置 Includes 文件頭模板
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}*/
2. 設置 Files 模板
2.1 設置路徑
File > Settings (在 macOS 上是 Preferences)> Editor > File and Code Templates > includes
2.2 在 “Files” 選項卡中,找到或創建 Java 類模板,并使用條件判斷來選擇合適的文件頭:
2.2.1 根據文件名區分
${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
使用更嚴謹的File template
#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
2.2.2根據包名區分
#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
3. 應用模板
- 當你創建一個新文件時,例如
UserController.java
、UserService.java
或UserMapper.java
,IDEA 將根據文件名后綴自動應用相應的文件頭注釋。 - 確保新文件的命名遵循
*Controller
、*Service
、*Mapper
的模式,以便條件判斷能夠正確匹配。
4. 為不同文件類型創建完全獨立模板
4.1 實圖講解
- 新增Controller模板—效果圖:
New
->Java Class
->Controller
就會出現新添加的模板
4.2 自定義Files模板詳細設置
在 IntelliJ IDEA 中創建需要的文件模板,比如 Controller、Service、Mapper,可以通過以下步驟來實現:
-
打開文件模板設置:
- 在 IntelliJ IDEA 的菜單欄中,點擊
File
->Settings
(在 macOS 上是IntelliJ IDEA
->Preferences
)。 - 在左側欄中,選擇
Editor
->File and Code Templates
。
- 在 IntelliJ IDEA 的菜單欄中,點擊
-
創建新的文件模板:
- 在
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
)。 - 輸入文件名,IDEA 會根據模板自動生成文件內容,包括你預定義的文件頭注釋。
- 當你創建新文件時,右鍵點擊項目結構樹中的目標包或目錄,選擇
通過這些步驟,你可以為常用的文件類型創建模板,提升開發效率和代碼的一致性。
5. Velocity 模板引擎
如**#set
** 是 Velocity 模板引擎的核心指令之一。以下為您完整解析 Velocity 的語法體系和學習路徑:
5.0 相關指令
以下是 Velocity 模板引擎核心指令的詳細解析:
一、變量操作指令
1. #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")
二、流程控制指令
2. #if / #elseif / #else
- 條件分支
#if($user.role == "admin")ADMIN MODE
#elseif($user.age >= 18)ADULT USER
#elseGUEST MODE
#end
判斷規則:
條件表達式 | 判定為 false 的情況 |
---|---|
$var | null、空字符串、空集合、false |
$var == 5 | 值不相等或類型不同 |
$list && $list.size() > 0 | 組合邏輯判斷 |
3. #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 | 是否是最后一次迭代(布爾值) |
三、模板組織指令
4. #include
- 靜態引入
#include("header.html")
特點:
- 引入的文件內容不解析 Velocity 語法
- 適合引入靜態 HTML/CSS/JS 片段
- 可一次引入多個文件:
#include("head.html", "footer.html")
5. #parse
- 動態解析
#parse("user_card.vm")
與 #include 對比:
特性 | #parse | #include |
---|---|---|
語法解析 | ? 會解析 VTL 指令 | ? 原樣輸出 |
變量共享 | ? 共享當前上下文變量 | ? 無變量傳遞 |
性能 | 較低(需解析) | 較高(直接讀取) |
6. #stop
- 引擎停止
#if($error)#stop ## 立即終止模板渲染
#end
使用場景:
- 遇到致命錯誤時中斷渲染
- 調試時快速定位問題
四、邏輯控制指令
7. #break
- 退出當前指令
#foreach($item in $list)#if($item == "stop") #break ## 退出當前 #foreach 循環#end
#end
作用范圍:
- 僅對當前所在指令有效(如
#foreach
、#macro
)
8. #evaluate
- 動態執行
#set($template = "Hello $name")
#evaluate($template) ## 輸出:Hello John
危險操作:
## 可能引發代碼注入(慎用!)
#evaluate($userInput)
五、代碼復用指令
9. #define
- 定義代碼塊
#define($block)<div class="alert">This is a reusable block</div>
#end## 調用
$block
特點:
- 類似變量賦值,但可包含復雜 HTML/VTL
- 每次調用輸出相同內容
10. #macro
- 定義可傳參宏
#macro(renderUser $user $isAdmin)<div class="#if($isAdmin)admin#end">$user.name</div>
#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)<!DOCTYPE html><html><head><title>User List</title>#include("styles.css")</head>
#end#macro(userCard $user)<div class="card">#parse("user_avatar.vm")<h3>$!{user.name}</h3>#if($user.isAdmin)<span class="badge">ADMIN</span>#end</div>
#end$header
<body>#foreach($user in $users)#if($user.name == "root")#stop ## 禁止顯示 root 用戶#end#userCard($user)#if($foreach.count >= 100)#break ## 最多顯示 100 條#end#end#parse("footer.vm")
</body>
</html>
以上內容可作為 Velocity 開發的權威參考,建議結合官方文檔實踐驗證。每個指令的詳細行為可能因 Velocity 版本略有差異(本文基于 2.x 版本)。
5.1、#set
指令詳解
5.1.1. 基礎作用
#set($variable = "value")
- 變量定義:創建或修改變量(類似編程中的賦值)
- 動態計算:可賦值為字符串、數字、布爾值,或通過表達式計算的結果
- 作用域:在整個模板中有效(類似全局變量)
5.1.2. 典型用法
## 字符串賦值
#set($className = "UserController")## 數值計算
#set($total = 10 + 5 * 3) ## $total = 25## 布爾邏輯
#set($isValid = $name && $name.length() > 5)## 對象方法調用
#set($firstChar = $className.substring(0,1))
5.2、Velocity 的語法規則
Velocity 的語法規則來源于以下渠道:
5.2.1. 官方文檔
Apache Velocity 官網 (velocity.apache.org) 提供完整的 VTL (Velocity Template Language) 規范。
5.2.2. IDE 集成
- IntelliJ IDEA 等 IDE 的 Velocity 模板編輯界面會提供語法提示
- 輸入
#
時會自動彈出指令列表(如#if
,#foreach
,#macro
)
5.2.3. 開源項目實踐
- 許多 Java 項目(如 Spring Boot 的代碼生成器)使用 Velocity 模板
- 通過閱讀開源代碼學習實際應用技巧
5.3、系統學習 Velocity 語法的路徑
5.3.1. 基礎語法
指令/語法 | 用途 | 示例 |
---|---|---|
變量引用 | 輸出變量值 | $variable 或 ${variable} |
注釋 | 添加模板注釋 | ## 單行注釋 或 #* 多行注釋 *# |
#set | 變量賦值 | #set($price = 99.9) |
#if/#else/#elseif | 條件分支 | 見下方示例 |
#foreach | 循環遍歷集合 | 見下方示例 |
條件判斷示例:
#if($user.role == "admin")<p>管理員權限</p>
#elseif($user.age > 18)<p>成年用戶</p>
#else<p>未成年用戶</p>
#end
循環示例:
<ul>
#foreach($item in $items)<li>${foreach.index} - ${item.name}</li>
#end
</ul>
5.3.2. 高級功能
功能 | 說明 | 示例 |
---|---|---|
宏 (Macro) | 定義可復用的代碼片段 | #macro(showError $msg)<div class="error">$msg</div>#end |
引入其他模板 | 模塊化模板設計 | #parse("header.vm") |
內置工具對象 | 提供字符串/數學等工具方法 | $math.add(1,2) 或 $date.format('yyyy-MM-dd') |
轉義輸出 | 防止 XSS 攻擊 | $!{userInput} 或 #escape($htmlContent) |
宏定義與調用:
## 定義宏
#macro(renderButton $text $color)<button style="color:${color}">$text</button>
#end## 調用宏
#renderButton("提交", "blue")
5.3.3. 調試技巧
- 輸出原始文本:使用
#[[ 不解析的內容 ]]#
#[[這里的 $variable 不會被解析 → 直接輸出 $variable ]]#
- 查看變量類型:
$variable.class.name ## 輸出變量類型(如 java.lang.String)
5.4、快速查詢手冊
在模板開發中常用以下語法:
需求場景 | 對應語法 |
---|---|
避免變量為 null 時報錯 | $!{variable} |
字符串拼接 | #set($fullName = "$firstName $lastName") |
集合是否為空判斷 | #if($list.isEmpty()) 或 `#if(!$list |
數值格式化 | $number.format("#,###", $price) |
日期格式化 | $date.format('yyyy-MM-dd', $today) |
5.5、學習資源推薦
5.5.1. 官方文檔(必讀)
- VTL 語法參考
- 用戶指南
5.5.2. 實戰教程
- Baeldung 的 Velocity 指南
- TutorialsPoint 的 Velocity 教程
5.5.3. IDE 輔助
- 在 IntelliJ IDEA 中創建
.vm
文件,IDE 會提供:- 語法高亮
- 指令自動補全(輸入
#
觸發) - 錯誤檢查
5.6、示例:完整模板文件
## 模板:user_profile.vm
#set($user = $data.getUser())
#set($birthday = $date.format('yyyy-MM-dd', $user.birthDate))<html>
<head><title>$!{user.name} 的資料</title>
</head>
<body>#if($user.isAdmin())<div class="admin-banner">管理員用戶</div>#end<h1>用戶信息</h1><ul><li>姓名:$!{user.name}</li><li>年齡:$math.sub($date.getYear(), $user.birthYear)</li><li>生日:$birthday</li></ul>#macro(renderSection $title $content)<div class="section"><h2>$title</h2><p>$content</p></div>#end#renderSection("聯系方式", $user.contactInfo)
</body>
</html>
通過系統學習上述內容,您將能:
- 熟練使用 Velocity 生成動態內容
- 理解模板引擎的運行機制
- 快速定位和解決模板渲染問題
建議邊學邊實踐,在 IntelliJ 中創建 .vm
文件體驗實時語法反饋。
5.7 Velocity引擎與Freemarker等熱門引擎對比以及應用場景
Velocity 確實不如 Freemarker、Thymeleaf 這類模板引擎知名度高,但它是一個歷史悠久且特定場景下非常高效的模板引擎。以下是它的核心應用場景和特點解析,幫助您理解為什么某些場景(比如 IDEA 的注釋模板)會選擇它:
一、Velocity 的典型應用場景
1. 代碼生成(核心優勢場景)
- Java 注釋模板(如 IDEA 內置)
- MyBatis 逆向工程(生成 DAO/Mapper 文件)
- Spring Boot 項目腳手架(如 JHipster 早期版本)
- API 文檔生成(結合 Swagger 模板)
優勢:
? 語法簡單,適合非前端開發者使用
? 無復雜依賴,可嵌入任何 Java 環境
? 生成純文本(代碼/配置文件)時性能極高
2. 傳統 Web 頁面渲染(逐漸被替代)
- 早期的 Java Web 項目(如 Struts 1.x 時代)
- 企業級 CMS 內容模板(如 Alfresco)
現狀:
?? 新項目更推薦 Thymeleaf/FreeMarker(對現代前端更友好)
?? 不支持響應式設計等現代特性
3. 郵件模板
- 企業級郵件內容動態生成(如訂單通知)
- 相比 HTML 頁面,郵件模板更簡單,Velocity 足夠輕量
4. 配置文件動態化
#set($dbHost = "192.168.1.100")
jdbc.url=jdbc:mysql://${dbHost}:3306/db
二、為什么 IDEA 選擇 Velocity 做注釋模板?
-
輕量級
無需引入額外依賴,IDEA 內置的模板引擎需要極低的開銷。 -
邏輯簡單
注釋模板通常只需要變量替換和簡單條件判斷,例如:/*** @author ${USER}* @date ${DATE}#if(${DESCRIPTION})* @description ${DESCRIPTION}#end*/
-
無副作用
不會像 FreeMarker 那樣產生意外換行或空格(對代碼格式敏感)。
三、與現代模板引擎對比
特性 | Velocity | FreeMarker | Thymeleaf |
---|---|---|---|
學習曲線 | ?(最簡單) | ?? | ???(需懂 HTML) |
性能 | ???(最快) | ?? | ? |
前端友好度 | ?(純后端) | ? | ????(原生 HTML) |
動態代碼生成 | ???? | ?? | ? |
社區活躍度 | ?(維護模式) | ??? | ???? |
四、經典代碼生成示例
MyBatis 生成器模板(mapper.xml.vm
)
<!-- 生成于 ${date} -->
<mapper namespace="${package.Mapper}.${table.mapperName}">#foreach($field in ${table.fields})#if(${field.keyFlag})<id column="${field.name}" property="${field.propertyName}" />#else<result column="${field.name}" property="${field.propertyName}" />#end#end<select id="selectById" resultMap="BaseResultMap">SELECT * FROM ${table.name} WHERE id = #{id}</select>
</mapper>
Spring Controller 模板(Controller.java.vm
)
#set($entity = ${table.entityName.toLowerCase()})
@RestController
@RequestMapping("/api/${entity}")
public class ${table.controllerName} {@Autowiredprivate ${table.serviceName} ${entity}Service;@GetMapping("/{id}")public Result<${table.entityName}> getById(@PathVariable ${table.primaryKeyType} id) {return Result.success(${entity}Service.getById(id));}
}
五、什么時候應該選擇 Velocity?
-
需要生成代碼/配置文件
(如自動生成 CRUD 代碼、批量創建相似文件) -
嵌入式模板需求
(如插件系統需要允許用戶自定義模板) -
歷史項目維護
(老系統升級時保留原有模板)
六、為什么不推薦新項目用 Velocity 做頁面渲染?
-
功能局限
缺少模板繼承、片段復用等現代特性,復雜頁面難以維護。 -
前后端協作困難
設計師無法直接修改 HTML(模板語法混合在標簽中)。 -
安全風險
默認不開啟 HTML 轉義,容易導致 XSS 攻擊(需手動處理)。
七、快速識別 Velocity 模板
- 文件擴展名:
.vm
- 語法特征:
<!-- 變量使用 $ 前綴 --> <h1>$title</h1><!-- 指令以 # 開頭 --> #foreach($item in $list)<li>$item</li> #end
如果您只需要一個輕量級文本生成工具(如代碼注釋、配置文件生成),Velocity 仍然是優秀選擇。但對于 Web 頁面開發,建議轉向 FreeMarker/Thymeleaf 等現代引擎。