本文目录导读:

我来为您提供一个完整的Java模板引擎实现案例,包含核心功能和示例:
简单的模板引擎实现
import java.util.*;
import java.util.regex.*;
/**
* 简单的模板引擎实现
*/
public class SimpleTemplateEngine {
// 变量替换模式:${variableName}
private static final Pattern VARIABLE_PATTERN =
Pattern.compile("\\$\\{([^}]+)\\}");
// 条件判断模式:{#if condition}...{/if}
private static final Pattern IF_PATTERN =
Pattern.compile("\\{#if\\s+([^}]+)\\}(.*?)\\{/if\\}", Pattern.DOTALL);
// 循环模式:{#foreach item in list}...{/foreach}
private static final Pattern FOREACH_PATTERN =
Pattern.compile("\\{#foreach\\s+(\\w+)\\s+in\\s+(\\w+)\\}(.*?)\\{/foreach\\}", Pattern.DOTALL);
private Map<String, Object> context = new HashMap<>();
/**
* 设置模板变量
*/
public void setVariable(String name, Object value) {
context.put(name, value);
}
/**
* 批量设置模板变量
*/
public void setVariables(Map<String, Object> variables) {
context.putAll(variables);
}
/**
* 渲染模板
*/
public String render(String template) {
if (template == null) {
return "";
}
String result = template;
// 处理条件判断
result = processIfBlocks(result);
// 处理循环
result = processForeachBlocks(result);
// 处理变量替换
result = processVariables(result);
return result;
}
/**
* 处理条件判断
*/
private String processIfBlocks(String template) {
Matcher matcher = IF_PATTERN.matcher(template);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String condition = matcher.group(1).trim();
String content = matcher.group(2);
String replacement = evaluateCondition(condition) ? content : "";
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 评估条件表达式
*/
private boolean evaluateCondition(String condition) {
// 简化版条件评估
if (condition.contains("==")) {
String[] parts = condition.split("==");
return getVariableValue(parts[0].trim())
.equals(getVariableValue(parts[1].trim()));
} else if (condition.contains("!=")) {
String[] parts = condition.split("!=");
return !getVariableValue(parts[0].trim())
.equals(getVariableValue(parts[1].trim()));
} else if (condition.contains(">")) {
String[] parts = condition.split(">");
try {
double left = Double.parseDouble(getVariableValue(parts[0].trim()));
double right = Double.parseDouble(getVariableValue(parts[1].trim()));
return left > right;
} catch (NumberFormatException e) {
return false;
}
} else if (condition.contains("<")) {
String[] parts = condition.split("<");
try {
double left = Double.parseDouble(getVariableValue(parts[0].trim()));
double right = Double.parseDouble(getVariableValue(parts[1].trim()));
return left < right;
} catch (NumberFormatException e) {
return false;
}
}
// 直接变量判断
return Boolean.parseBoolean(getVariableValue(condition));
}
/**
* 处理循环
*/
private String processForeachBlocks(String template) {
Matcher matcher = FOREACH_PATTERN.matcher(template);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String itemName = matcher.group(1).trim();
String listName = matcher.group(2).trim();
String content = matcher.group(3);
StringBuilder replacement = new StringBuilder();
Object listObj = context.get(listName);
if (listObj instanceof Collection) {
Collection<?> list = (Collection<?>) listObj;
for (Object item : list) {
Map<String, Object> oldContext = new HashMap<>(context);
context.put(itemName, item);
replacement.append(processVariables(content));
context.clear();
context.putAll(oldContext);
}
} else if (listObj != null && listObj.getClass().isArray()) {
Object[] array = (Object[]) listObj;
for (Object item : array) {
Map<String, Object> oldContext = new HashMap<>(context);
context.put(itemName, item);
replacement.append(processVariables(content));
context.clear();
context.putAll(oldContext);
}
}
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement.toString()));
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 处理变量替换
*/
private String processVariables(String template) {
Matcher matcher = VARIABLE_PATTERN.matcher(template);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String variablePath = matcher.group(1).trim();
String value = getVariableValue(variablePath);
matcher.appendReplacement(sb, Matcher.quoteReplacement(value));
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 获取变量值
*/
private String getVariableValue(String path) {
// 支持点号访问对象属性
String[] parts = path.split("\\.");
Object value = context.get(parts[0]);
if (value == null) {
return "null";
}
// 对象属性访问
if (parts.length > 1) {
for (int i = 1; i < parts.length; i++) {
if (value instanceof Map) {
value = ((Map<?, ?>) value).get(parts[i]);
} else {
// 使用反射访问属性
try {
String getter = "get" + parts[i].substring(0, 1).toUpperCase()
+ parts[i].substring(1);
value = value.getClass().getMethod(getter).invoke(value);
} catch (Exception e) {
return "null";
}
}
}
}
return value != null ? value.toString() : "null";
}
}
/**
* 用户类(用于测试)
*/
class User {
private String name;
private int age;
private String email;
public User(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
public String getName() { return name; }
public int getAge() { return age; }
public String getEmail() { return email; }
@Override
public String toString() {
return name;
}
}
更完整的模板引擎(支持更多功能)
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.regex.*;
/**
* 高级模板引擎
*/
public class AdvancedTemplateEngine {
private static final Map<String, Pattern> PATTERNS = new HashMap<>();
private static final String CACHE_DIR = "template_cache";
static {
// 变量: {{ varName }}
PATTERNS.put("variable", Pattern.compile("\\{\\{\\s*([^}]+?)\\s*\\}\\}"));
// 循环: {% for item in items %}
PATTERNS.put("for", Pattern.compile("\\{%\\s*for\\s+(\\w+)\\s+in\\s+(\\w+)\\s*%\\}(.*?)\\{%\\s*endfor\\s*%\\}", Pattern.DOTALL));
// 条件: {% if condition %}
PATTERNS.put("if", Pattern.compile("\\{%\\s*if\\s+(.+?)\\s*%\\}(.*?)(\\{%\\s*else\\s*%\\}(.*?))?\\{%\\s*endif\\s*%\\}", Pattern.DOTALL));
// 注释: {# comment #}
PATTERNS.put("comment", Pattern.compile("\\{#.*?#\\}", Pattern.DOTALL));
// 包含: {% include "filename" %}
PATTERNS.put("include", Pattern.compile("\\{%\\s*include\\s+[\"'](.+?)[\"']\\s*%\\}"));
}
private Map<String, Object> globalContext = new HashMap<>();
private Map<String, String> templateCache = new HashMap<>();
/**
* 设置全局变量
*/
public void setGlobalVariable(String name, Object value) {
globalContext.put(name, value);
}
/**
* 渲染字符串模板
*/
public String render(String template, Map<String, Object> context) {
Map<String, Object> mergedContext = new HashMap<>(globalContext);
mergedContext.putAll(context);
String result = template;
// 1. 移除注释
result = PATTERNS.get("comment").matcher(result).replaceAll("");
// 2. 处理包含指令
result = processIncludes(result, mergedContext);
// 3. 处理循环
result = processLoops(result, mergedContext);
// 4. 处理条件
result = processConditionals(result, mergedContext);
// 5. 处理变量
result = processVariables(result, mergedContext);
return result;
}
/**
* 从文件渲染模板
*/
public String renderFile(String templatePath, Map<String, Object> context) throws IOException {
String template = loadTemplate(templatePath);
return render(template, context);
}
/**
* 加载模板文件(带缓存)
*/
private String loadTemplate(String path) throws IOException {
if (templateCache.containsKey(path)) {
return templateCache.get(path);
}
String content = new String(Files.readAllBytes(Paths.get(path)));
templateCache.put(path, content);
return content;
}
/**
* 处理包含指令
*/
private String processIncludes(String template, Map<String, Object> context) {
Matcher matcher = PATTERNS.get("include").matcher(template);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String file = matcher.group(1);
try {
String includedContent = loadTemplate(file);
String rendered = render(includedContent, context);
matcher.appendReplacement(sb, Matcher.quoteReplacement(rendered));
} catch (IOException e) {
matcher.appendReplacement(sb, "<!-- Error including: " + file + " -->");
}
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 处理循环
*/
private String processLoops(String template, Map<String, Object> context) {
Matcher matcher = PATTERNS.get("for").matcher(template);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String itemVar = matcher.group(1);
String listVar = matcher.group(2);
String content = matcher.group(3);
Object listObj = context.get(listVar);
StringBuilder result = new StringBuilder();
if (listObj instanceof Collection) {
for (Object item : (Collection<?>) listObj) {
Map<String, Object> newContext = new HashMap<>(context);
newContext.put(itemVar, item);
newContext.put("loop.index", ((Collection<?>) listObj).size());
result.append(processVariables(content, newContext));
}
} else if (listObj instanceof Map) {
Map<?, ?> map = (Map<?, ?>) listObj;
for (Map.Entry<?, ?> entry : map.entrySet()) {
Map<String, Object> newContext = new HashMap<>(context);
newContext.put(itemVar, entry.getValue());
newContext.put("loop.key", entry.getKey());
result.append(processVariables(content, newContext));
}
}
matcher.appendReplacement(sb, Matcher.quoteReplacement(result.toString()));
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 处理条件语句
*/
private String processConditionals(String template, Map<String, Object> context) {
Matcher matcher = PATTERNS.get("if").matcher(template);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String condition = matcher.group(1).trim();
String thenContent = matcher.group(2);
String elseContent = matcher.group(4) != null ? matcher.group(4) : "";
boolean result = evaluateCondition(condition, context);
String replacement = result ? thenContent : elseContent;
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 评估条件
*/
private boolean evaluateCondition(String condition, Map<String, Object> context) {
condition = condition.trim();
// 处理 NOT 操作
if (condition.startsWith("not ")) {
return !evaluateCondition(condition.substring(4), context);
}
// 处理 AND
if (condition.contains(" and ")) {
String[] parts = condition.split("\\s+and\\s+");
for (String part : parts) {
if (!evaluateCondition(part, context)) {
return false;
}
}
return true;
}
// 处理 OR
if (condition.contains(" or ")) {
String[] parts = condition.split("\\s+or\\s+");
for (String part : parts) {
if (evaluateCondition(part, context)) {
return true;
}
}
return false;
}
// 处理比较操作
if (condition.matches(".*\\s*(==|!=|>=|<=|>|<)\\s*.*")) {
String[] parts = condition.split("\\s*(==|!=|>=|<=|>|<)\\s*");
if (parts.length == 2) {
Object left = getValue(parts[0].trim(), context);
Object right = getValue(parts[1].trim(), context);
if (left instanceof Number && right instanceof Number) {
double l = ((Number) left).doubleValue();
double r = ((Number) right).doubleValue();
if (condition.contains(">")) return l > r;
if (condition.contains("<")) return l < r;
if (condition.contains(">=")) return l >= r;
if (condition.contains("<=")) return l <= r;
}
return left != null && left.equals(right);
}
}
// 检查变量是否存在且为true
Object value = getValue(condition, context);
if (value instanceof Boolean) {
return (Boolean) value;
}
return value != null && !value.toString().isEmpty();
}
/**
* 获取值
*/
private Object getValue(String path, Map<String, Object> context) {
if (path.startsWith("'") && path.endsWith("'")) {
return path.substring(1, path.length() - 1);
}
String[] parts = path.split("\\.");
Object value = context.get(parts[0]);
for (int i = 1; i < parts.length && value != null; i++) {
if (value instanceof Map) {
value = ((Map<?, ?>) value).get(parts[i]);
} else {
try {
String getter = "get" + Character.toUpperCase(parts[i].charAt(0)) + parts[i].substring(1);
value = value.getClass().getMethod(getter).invoke(value);
} catch (Exception e) {
return null;
}
}
}
return value;
}
/**
* 处理变量
*/
private String processVariables(String template, Map<String, Object> context) {
Matcher matcher = PATTERNS.get("variable").matcher(template);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String expression = matcher.group(1).trim();
Object value = getValue(expression, context);
String replacement = value != null ? value.toString() : "";
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(sb);
return sb.toString();
}
}
测试类
import java.util.*;
public class TemplateEngineTest {
public static void main(String[] args) {
testSimpleTemplate();
testAdvancedTemplate();
}
private static void testSimpleTemplate() {
System.out.println("=== 简单模板引擎测试 ===");
// 创建模板引擎
SimpleTemplateEngine engine = new SimpleTemplateEngine();
// 准备数据
Map<String, Object> context = new HashMap<>();
context.put("name", "张三");
context.put("age", 25);
List<User> users = Arrays.asList(
new User("李四", 28, "lisi@example.com"),
new User("王五", 32, "wangwu@example.com"),
new User("赵六", 22, "zhaoliu@example.com")
);
context.put("users", users);
engine.setVariables(context);
// 模板字符串
String template = """
欢迎,${name}!
你的年龄是${age}岁。
{#if age >= 18}
<h2>你已是成年人</h2>
{/if}
<h3>用户列表:</h3>
{#foreach user in users}
<p>用户名:${user.name},年龄:${user.age},邮箱:${user.email}</p>
{/foreach}
""";
// 渲染
String result = engine.render(template);
System.out.println(result);
}
private static void testAdvancedTemplate() {
System.out.println("\n=== 高级模板引擎测试 ===");
AdvancedTemplateEngine engine = new AdvancedTemplateEngine();
// 设置全局变量
engine.setGlobalVariable("siteName", "MyWebsite");
engine.setGlobalVariable("version", "1.0.0");
// 准备数据
Map<String, Object> context = new HashMap<>();
context.put("pageTitle", "用户管理");
context.put("isLoggedIn", true);
context.put("username", "admin");
Map<String, Object> settings = new HashMap<>();
settings.put("itemsPerPage", 10);
settings.put("showEmail", false);
context.put("settings", settings);
List<User> allUsers = Arrays.asList(
new User("张三", 25, "zhangsan@example.com"),
new User("李四", 28, "lisi@example.com"),
new User("王五", 32, "wangwu@example.com")
);
context.put("allUsers", allUsers);
String template = """
<!-- 页面模板 -->
<!DOCTYPE html>
<html>
<head>
<title>{{ pageTitle }} - {{ siteName }}</title>
</head>
<body>
{# if isLoggedIn #}
<h1>欢迎回来,{{ username }}!</h1>
{# else #}
<h1>请登录</h1>
{# endif #}
{% if settings.showEmail %}
<p>显示邮箱:是</p>
{% else %}
<p>显示邮箱:否</p>
{% endif %}
<h2>用户列表(每页显示{{ settings.itemsPerPage }}条):</h2>
{% for user in allUsers %}
<div class="user-item">
<span>用户名:{{ user.name }}</span>
<span>年龄:{{ user.age }}</span>
{% if settings.showEmail %}
<span>邮箱:{{ user.email }}</span>
{% endif %}
</div>
{% endfor %}
<footer>
<p>© 2023 {{ siteName }} v{{ version }}</p>
</footer>
</body>
</html>
""";
String result = engine.render(template, context);
System.out.println(result);
}
}
说明
功能特性
- 变量替换:支持
${variable}和{{ variable }}两种语法 - 条件判断:支持
{#if condition}...{/if}和{% if condition %}语法 - 循环遍历:支持
{#foreach item in list}...{/foreach}和{% for item in list %}语法 - 对象属性访问:支持点号语法
user.name - 条件表达式:支持比较运算符(
>,<,>=,<=, , )和逻辑运算符(and,or,not) - 模板包含:支持包含其他模板文件
- 注释支持:支持
{# comments #}注释 - 模板缓存:对模板文件进行缓存以提高性能
使用示例
// 创建引擎
AdvancedTemplateEngine engine = new AdvancedTemplateEngine();
// 设置数据
Map<String, Object> data = new HashMap<>();
data.put("name", "张三");
data.put("users", userList);
// 渲染模板
String html = engine.render(template, data);
这是一个功能完整的模板引擎实现,您可以在此基础上进行扩展以满足特定需求。