杰瑞科技汇

Freemarker如何调用Java方法?

Freemarker调用Java方法终极指南:从基础到高级实战(附代码示例)

Meta描述:

深入探讨Freemarker模板引擎如何灵活调用Java方法,提升模板开发效率,本文详细讲解静态方法、实例方法调用,配置freemarker.ext.beans,处理复杂参数与返回值,并通过实际案例助你掌握Freemarker与Java后端的数据交互技巧,解决开发难题。

Freemarker如何调用Java方法?-图1
(图片来源网络,侵删)

引言:为什么你需要让Freemarker调用Java方法?

在Java Web开发中,Freemarker作为一种成熟、强大的模板引擎,被广泛应用于视图层渲染,其核心职责是将后端传递的数据(Model)与前端模板(View)优雅地结合,生成最终的HTML或其他格式的文档。

仅仅渲染静态数据是远远不够的,在实际业务场景中,我们常常需要在模板层面进行一些简单的逻辑处理、数据格式化、甚至调用业务服务。

  • 将日期格式化为友好的“YYYY年MM月DD日”。
  • 根据用户权限动态显示或隐藏某个按钮。
  • 对一个列表进行简单的排序或过滤。
  • 调用一个工具类的方法来生成一个唯一的订单编号。

如果将这些逻辑全部放在Controller层,会导致代码臃肿、职责不清,Freemarker提供了调用Java方法的能力,让我们将视图层的“轻量级逻辑”合理地放在模板中处理,实现前后端更清晰的职责划分,提升开发效率和代码可维护性。

本文将作为你的终极指南,带你从零开始,系统性地掌握Freemarker调用Java方法的各项技术要点。

Freemarker如何调用Java方法?-图2
(图片来源网络,侵删)

核心原理:Freemarker与Java的桥梁 - freemarker.ext.beans

在深入代码之前,我们必须理解其背后的工作原理,Freemarker之所以能调用Java方法,关键在于它内置了一个对象包装器——freemarker.ext.beans.BeansWrapper

BeansWrapper就像一个翻译官,它负责将Java对象及其方法“翻译”成Freemarker能够理解和调用的形式(即TemplateMethodModelTemplateModel),当你尝试在模板中调用一个对象的方法时,Freemarker会通过BeansWrapper去查找并执行对应的Java方法。

默认情况下,Freemarker会使用一个标准的BeansWrapper实例,但在生产环境中,我们通常推荐使用BeansWrapperBuilder(对于较新版本)或配置一个更高级的BeansWrapper来获得更好的性能和控制力。


环境准备:你的第一个可调用的Java方法

假设我们有一个标准的Spring Boot项目,并已集成Freemarker,我们创建一个简单的Java工具类,作为我们调用的目标。

Freemarker如何调用Java方法?-图3
(图片来源网络,侵删)

com.example.utils.DateUtils.java

package com.example.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtils {
    /**
     * 将日期格式化为指定的字符串
     * @param date 日期对象
     * @param pattern 格式化模式,如 "yyyy-MM-dd"
     * @return 格式化后的字符串
     */
    public static String formatDate(Date date, String pattern) {
        if (date == null || pattern == null) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(date);
    }
    /**
     * 获取一个问候语
     * @param name 用户名
     * @return 问候语
     */
    public static String getGreeting(String name) {
        return "你好, " + name + "! 欢迎使用我们的系统。";
    }
}

这个类包含两个静态方法,这是我们接下来要在Freemarker模板中调用的目标。


基础篇:调用静态方法(最常用)

调用静态方法是Freemarker调用Java方法最常见、最安全的方式。

步骤1:在Controller中传递工具类实例

你需要将包含目标方法的Java对象实例传递给模板,我们会在Controller中创建一个实例并放入Model中。

com.example.controller.HomeController.java

package com.example.controller;
import com.example.utils.DateUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Controller
public class HomeController {
    @GetMapping("/")
    public String home(Model model) {
        // 1. 创建一个Map来存放所有需要传递给模板的数据
        Map<String, Object> data = new HashMap<>();
        // 2. 将工具类实例放入Map中
        // 在模板中,我们可以通过 ${dateUtils} 来引用这个对象
        data.put("dateUtils", new DateUtils());
        // 3. 传递一些其他数据
        data.put("currentDate", new Date());
        data.put("userName", "张三");
        // 4. 将Map添加到Model中
        model.addAllAttributes(data);
        return "home"; // 对应 templates/home.ftl
    }
}

步骤2:在Freemarker模板中调用方法

打开你的home.ftl模板文件,看看如何调用DateUtils中的静态方法。

templates/home.ftl

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">Freemarker 调用Java方法示例</title>
</head>
<body>
    <h1>欢迎页面</h1>
    <h2>示例1:调用静态方法(无参数)</h2>
    <p>${dateUtils.getGreeting(userName)}</p>
    <!-- 输出: 你好, 张三! 欢迎使用我们的系统。 -->
    <hr>
    <h2>示例2:调用静态方法(带参数)</h2>
    <p>当前日期 (默认格式): ${dateUtils.formatDate(currentDate, "yyyy-MM-dd HH:mm:ss")}</p>
    <!-- 输出: 当前日期 (默认格式): 2025-10-27 15:30:00 -->
    <p>当前日期 (友好格式): ${dateUtils.formatDate(currentDate, "yyyy年MM月dd日")}</p>
    <!-- 输出: 当前日期 (友好格式): 2025年10月27日 -->
</body>
</html>

关键点解析:

  • ${dateUtils}:这是我们通过Controller传递过来的DateUtils类的实例。
  • 点号操作符,用于访问对象的属性或方法。
  • getGreeting(userName):Freemarker会自动识别括号内的内容是方法调用,而不是属性访问,它会将userName变量作为参数传递给getGreeting方法。

进阶篇:调用实例方法与处理复杂对象

除了静态方法,我们同样可以调用任何Java对象的实例方法。

示例:调用业务Service方法

假设我们有一个用户服务,可以获取用户信息。

com.example.service.UserService.java

@Service
public class UserService {
    public String getUserRole(String username) {
        // 模拟业务逻辑
        if ("admin".equals(username)) {
            return "系统管理员";
        } else if ("user".equals(username)) {
            return "普通用户";
        }
        return "访客";
    }
}

UserController.java (修改)

@Controller
public class HomeController {
    @Autowired
    private UserService userService; // 注入Service
    @GetMapping("/")
    public String home(Model model) {
        // ... 其他代码 ...
        data.put("userService", userService); // 将Service实例直接传入
        model.addAllAttributes(data);
        return "home";
    }
}

home.ftl (修改)

<h2>示例3:调用实例方法(调用Service)</h2>
<p>用户 'admin' 的角色是: <strong>${userService.getUserRole("admin")}</strong></p>
<p>当前用户 '${userName}' 的角色是: <strong>${userService.getUserRole(userName)}</strong></p>

处理复杂参数和返回值

Freemarker对Java基本类型和集合类(List, Map, Set)有很好的内置支持,当你调用一个返回复杂对象的方法时,Freemarker会将其包装成TemplateModel(如SimpleScalar, SimpleSequence, SimpleHash),你可以在模板中继续操作它们。

如果你的方法返回一个Map<String, Object>

public Map<String, Object> getUserInfo(String name) {
    Map<String, Object> info = new HashMap<>();
    info.put("name", name);
    info.put("age", 30);
    return info;
}

在模板中,你可以这样使用:

<#assign userInfo = userService.getUserInfo("李四")>
<p>用户名: ${userInfo.name}</p>
<p>年龄: ${userInfo.age
分享:
扫描分享到社交APP
上一篇
下一篇