杰瑞科技汇

Java action 方法如何定义与调用?

在标准的 Java 语言规范(如 Java SE)中,并没有一个叫做 action 的关键字或内置方法。

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

action 这个术语通常出现在特定的框架或上下文中,它代表一个“动作”“行为”,通常指一段需要被执行的代码逻辑,在不同的框架里,它的实现和含义略有不同。

下面我将从几个最常见的场景来解释 action 方法:

  1. Java Web 开发中的 Action (最经典)
  2. Java Swing 中的 Action
  3. 现代框架中的替代概念 (如 Functional Interface)
  4. 自定义的 Action 模式

Java Web 开发中的 Action (最经典)

在经典的 Java Web 开发中,尤其是在 Struts 1 框架中,Action 是一个核心概念,后来,在 Struts 2 中,虽然底层实现不同,但“Action”的理念依然保留,很多开发者使用 Spring MVCController 承担了类似 Action 的角色。

Struts 1 中的 Action

在 Struts 1 中,开发者需要创建一个类,继承自 org.apache.struts.action.Action,这个类中的核心方法就是 execute()

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

Action 的生命周期:

  1. 接收来自客户端的 HTTP 请求。
  2. Struts 框架根据 struts-config.xml 中的配置,将请求映射到对应的 Action 类。
  3. 框架创建该 Action 类的一个实例(或复用现有实例)。
  4. 调用该实例的 execute() 方法,并将 ActionForm(用于封装表单数据)和 ActionMapping(用于获取配置信息)等对象作为参数传入。
  5. execute() 方法内部处理业务逻辑,然后返回一个 ActionForward 对象,告诉框架下一步应该跳转到哪个 JSP 页面。

示例代码 (Struts 1):

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// 1. 定义一个 Action 类
public class LoginAction extends Action {
    // 2. 这是核心的 "action" 方法
    @Override
    public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        // 3. 从 ActionForm 中获取表单数据
        LoginForm loginForm = (LoginForm) form;
        String username = loginForm.getUsername();
        String password = loginForm.getPassword();
        // 4. 执行业务逻辑 (验证用户)
        if ("admin".equals(username) && "password".equals(password)) {
            // 登录成功,将用户信息存入 session
            request.getSession().setAttribute("user", username);
            // 返回一个成功跳转的标识
            return mapping.findForward("success");
        } else {
            // 登录失败,返回一个失败跳转的标识
            return mapping.findForward("failure");
        }
    }
}

在这个例子中,LoginAction 类的 execute() 方法就是一个典型的 Action 方法,它封装了处理“用户登录”这个动作的所有逻辑。


Spring MVC 中的 Controller (Action 的现代替代品)

在现代的 Spring MVC 框架中,Controller 承担了 Struts 1 中 Action 的职责,它不再需要继承任何基类,而是通过注解来定义。

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

@Controller 的生命周期:

  1. 接收 HTTP 请求。
  2. Spring MVC 通过 @RequestMapping@GetMapping/@PostMapping 等注解将请求映射到 Controller 中的具体方法。
  3. 该方法直接处理请求、执行业务逻辑,并返回一个逻辑视图名(或直接返回数据,如 JSON)。

示例代码 (Spring MVC):

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
// 1. 使用 @Controller 注解标记这是一个控制器
@Controller
public class LoginController {
    // 2. 这是一个处理 POST 请求的 "action" 方法
    @PostMapping("/login")
    public ModelAndView handleLogin(
            @RequestParam("username") String username,
            @RequestParam("password") String password) {
        // 3. 执行业务逻辑
        if ("admin".equals(username) && "password".equals(password)) {
            // 登录成功,添加数据到 Model 并返回视图名
            ModelAndView mav = new ModelAndView("welcome"); // 跳转到 welcome.jsp
            mav.addObject("user", username);
            return mav;
        } else {
            // 登录失败,返回错误页面
            ModelAndView mav = new ModelAndView("error"); // 跳转到 error.jsp
            mav.addObject("errorMsg", "用户名或密码错误");
            return mav;
        }
    }
    // 也可以是一个处理 GET 请求的 "action" 方法
    @GetMapping("/home")
    public String showHomePage() {
        return "home"; // 返回逻辑视图名 "home"
    }
}

在 Spring MVC 中,LoginController 里的 handleLogin 方法就是一个 Action 方法,它更简洁,与 Web 容器的耦合度更低。


Java Swing 中的 Action

在 Java Swing 图形界面编程中,javax.swing.Action 接口提供了一种将组件(如按钮、菜单项)与动作行为解耦的机制,一个 Action 对象可以同时被多个 UI 组件共享。

Action 的核心思想:

  • 封装行为:将一个操作(如“保存文件”、“打开文件”)的代码封装在一个 Action 对象中。
  • 管理状态Action 可以管理自己的状态(如是否可用 setEnabled()、文本 putValue(Action.NAME, "Save")、图标等)。
  • 统一管理:一个 Action 可以同时附加到一个菜单项、一个工具栏按钮和一个键盘快捷键上,它们的界面状态会自动同步。

示例代码 (Swing):

import javax.swing.*;
import java.awt.event.ActionEvent;
// 1. 创建一个类实现 Action 接口
public class SaveAction extends AbstractAction { // 通常继承 AbstractAction 更方便
    public SaveAction() {
        // 2. 设置 Action 的属性,这些属性会被所有使用它的组件共享
        putValue(Action.NAME, "保存");
        putValue(Action.SHORT_DESCRIPTION, "保存当前文件 (Ctrl+S)");
        putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control S"));
    }
    // 3. 这是核心的 "action" 方法,当组件被点击时,此方法被调用
    @Override
    public void actionPerformed(ActionEvent e) {
        // 这里是“保存文件”的具体逻辑
        System.out.println("执行保存文件操作...");
        // JOptionPane.showMessageDialog(null, "文件已保存!");
    }
    public static void main(String[] args) {
        JFrame frame = new JFrame("Action 示例");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 200);
        // 4. 创建 Action 实例
        SaveAction saveAction = new SaveAction();
        // 5. 将 Action 应用到不同的组件上
        JButton saveButton = new JButton(saveAction);
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("文件");
        JMenuItem saveMenuItem = new JMenuItem(saveAction);
        fileMenu.add(saveMenuItem);
        menuBar.add(fileMenu);
        frame.setJMenuBar(menuBar);
        frame.getContentPane().add(saveButton);
        frame.setVisible(true);
    }
}

在这个例子中,SaveAction 类的 actionPerformed() 方法就是 Swing 中的 Action 方法,它定义了点击“保存”按钮或菜单项时应该发生的动作。


现代框架中的替代概念 (Functional Interface)

随着 Java 8 引入 Lambda 表达式和函数式接口,很多框架开始使用更轻量级的方式来定义“动作”。

RunnableConsumer 是最典型的例子。

Runnable (无参数,无返回值) 常用于多线程,定义一个可以被独立执行的任务。

// 使用匿名内部类
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("一个简单的动作正在执行...");
    }
}).start();
// 使用 Lambda 表达式 (更简洁)
new Thread(() -> System.out.println("一个简单的动作正在执行...")).start();

这里的 run() 方法就是一个 action 方法。

Consumer<T> (接受一个参数,无返回值) 常用于流式处理,对集合中的每个元素执行一个操作。

import java.util.List;
import java.util.function.Consumer;
List<String> names = List.of("Alice", "Bob", "Charlie");
// 定义一个动作:打印每个名字
Consumer<String> printName = name -> System.out.println("你好, " + name);
// 对列表中的每个元素执行这个动作
names.forEach(printName);

这里的 accept(T t) 方法(forEach 内部调用)Consumeraction 方法。


自定义的 Action 模式

你也可以在自己的代码中设计一个“Action”模式,这通常涉及到定义一个接口,该接口中有一个执行核心逻辑的方法。

示例代码 (自定义 Action):

// 1. 定义一个 Action 接口
public interface Action {
    void execute(); // 核心的动作方法
    String getName(); // 获取动作名称
}
// 2. 实现具体的动作
public class SendEmailAction implements Action {
    @Override
    public void execute() {
        System.out.println("正在发送邮件...");
        // 邮件发送逻辑...
    }
    @Override
    public String getName() {
        return "Send Email";
    }
}
// 3. 使用 Action
public class ActionProcessor {
    public void processAction(Action action) {
        System.out.println("准备执行动作: " + action.getName());
        action.execute(); // 调用 action 方法
        System.out.println("动作执行完毕。");
    }
}
// 主程序
public class Main {
    public static void main(String[] args) {
        ActionProcessor processor = new ActionProcessor();
        Action sendEmail = new SendEmailAction();
        processor.processAction(sendEmail); // 这里调用了 SendEmailAction 的 execute() 方法
    }
}

这种模式将“做什么”(Action接口)和“谁来做”(具体的实现类)分离开,非常灵活。

场景 关键词/框架 Action 方法 作用
经典 Web 开发 Struts 1 execute() 处理 HTTP 请求,执行业务逻辑,决定视图跳转。
现代 Web 开发 Spring MVC @RequestMapping / @PostMapping 等注解的方法 处理特定 HTTP 请求,是 Web 应用的入口。
桌面应用 Java Swing actionPerformed() 响应用户界面组件(如按钮)的交互事件。
函数式编程 Java 8+ run(), accept(), apply() 定义可执行的代码块,用于线程、流处理等。
自定义设计 设计模式 自定义的 execute() 或类似方法 封装独立的、可复用的业务逻辑单元。

action 方法不是一个 Java 语言内置的东西,而是一个在特定上下文中(尤其是框架中)用于封装“行为”或“操作”的核心方法,理解它在不同框架中的具体实现和作用,对于学习和使用这些框架至关重要。

分享:
扫描分享到社交APP
上一篇
下一篇