杰瑞科技汇

JSP中JS如何直接调用Java方法?

JavaScript(运行在客户端浏览器)不能直接调用 Java 代码(运行在服务器端 JVM 中)。 它们之间需要一个“桥梁”。

JSP中JS如何直接调用Java方法?-图1
(图片来源网络,侵删)

主要有以下三种方式,我会按照从最推荐不推荐的顺序进行讲解:

  1. AJAX (推荐):现代、标准、灵活的方式。
  2. JSP 内联表达式/脚本 (不推荐):老旧、耦合度高、维护困难的方式。
  3. 后端框架 (如 Spring MVC, Struts2) (最佳实践):在大型项目中,这是最规范、最强大的方式。

使用 AJAX (Asynchronous JavaScript and XML)

这是目前最主流、最推荐的方式,工作流程如下:

  1. 客户端 (JSP/JS)
    • 用户在页面上进行某个操作(如点击按钮)。
    • JavaScript 监听这个事件,然后通过 XMLHttpRequestfetch API 向服务器发送一个 HTTP 请求(通常是 GET 或 POST)。
    • 这个请求会指向一个特定的 URL(/your-app/data)。
  2. 服务器端 (Java Servlet)
    • 一个 Java ServletController 接收到这个 HTTP 请求。
    • Servlet 调用你想要执行的 Java 方法(从数据库查询数据、进行计算等)。
    • 将 Java 方法执行的结果(数据)转换成一种通用的格式,最常用的是 JSON
  3. 响应返回客户端

    服务器将 JSON 数据作为 HTTP 响应体返回给客户端的浏览器。

  4. 客户端 (JS)
    • JavaScript 的回调函数接收到这个 HTTP 响应。
    • 解析 JSON 数据。
    • 使用 JavaScript 动态更新页面的内容,而无需刷新整个页面。

示例:AJAX 调用 Java 方法

目标:在 JSP 页面上点击一个按钮,调用服务器端的 Java 方法,获取一个 "Hello from Java!" 的字符串,并显示在页面上。

JSP中JS如何直接调用Java方法?-图2
(图片来源网络,侵删)

创建 Java 后端代码

我们需要一个 Servlet 来处理请求。

HelloServlet.java

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson; // 使用 Gson 库将对象转为 JSON
@WebServlet("/hello") // 定义这个 Servlet 的访问 URL
public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    // 你想要被调用的 Java 方法
    public String getGreetingMessage() {
        return "Hello from Java! The current time is: " + new java.util.Date();
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 调用 Java 方法
        String message = getGreetingMessage();
        // 2. 创建 Gson 实例
        Gson gson = new Gson();
        // 3. 将 Java 对象/字符串转换为 JSON 格式
        String jsonResponse = gson.toJson(message);
        // 4. 设置响应内容类型为 JSON
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        // 5. 将 JSON 数据写回响应中
        response.getWriter().write(jsonResponse);
    }
}

注意:你需要添加 gson.jar 库到你的项目中,如果你使用 Maven,可以在 pom.xml 中添加:

JSP中JS如何直接调用Java方法?-图3
(图片来源网络,侵删)
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>

创建 JSP 前端页面

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">AJAX 调用 Java 方法示例</title>
<style>
    #result {
        margin-top: 20px;
        padding: 10px;
        border: 1px solid #ccc;
        background-color: #f9f9f9;
    }
</style>
</head>
<body>
    <h1>前端与后端交互测试</h1>
    <button id="myButton">点击调用后端 Java 方法</button>
    <div id="result">等待调用...</div>
    <script>
        document.getElementById('myButton').addEventListener('click', function() {
            // 1. 获取要显示结果的 div 元素
            const resultDiv = document.getElementById('result');
            // 2. 使用 fetch API 发送 AJAX 请求
            // 注意:这里的 '/your-app-context/hello' 必须与 @WebServlet("/hello") 的路径匹配
            // 'your-app-context' 是你的 Web 应用的上下文路径
            fetch('/your-app-context/hello') 
                .then(response => {
                    // 检查响应是否成功
                    if (!response.ok) {
                        throw new Error('Network response was not ok');
                    }
                    // 将响应体解析为 JSON
                    return response.json(); 
                })
                .then(data => {
                    // 3. 获取到数据后,更新页面内容
                    // data 就是后端返回的 JSON 字符串,这里它已经被解析成了 JavaScript 字符串
                    resultDiv.textContent = data;
                })
                .catch(error => {
                    // 4. 处理请求中发生的错误
                    console.error('There was a problem with the fetch operation:', error);
                    resultDiv.textContent = '调用失败: ' + error.message;
                });
        });
    </script>
</body>
</html>

如何找到 your-app-context

  • pom.xml (Maven) 中查看 <finalName>
  • web.xml 中查看 <context-param>
  • 部署后,查看 Tomcat (或其他服务器) 的 webapps 目录下的文件夹名。
  • 如果是根应用,路径可能是 /hello

JSP 内联表达式和脚本 (不推荐)

这种方式非常古老,直接在 JSP 页面中嵌入 Java 代码。强烈不推荐 在新项目中使用,因为它会导致严重的代码混乱、维护困难和安全隐患。

示例:JSP 调用 Java 方法

创建一个普通的 Java Bean (POJO)

这个类必须有 public 的无参构造函数和 public 的 getter/setter 方法。

MessageGenerator.java

package com.example;
public class MessageGenerator {
    public String getWelcomeMessage() {
        return "This message is from a Java Bean, generated at: " + new java.util.Date();
    }
}

在 JSP 中调用

old_way.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="com.example.MessageGenerator" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">JSP 内联 Java 代码 (不推荐)</title>
</head>
<body>
    <h1>旧式 JSP 调用</h1>
    <%-- 
        这是 JSP 脚本片段,用于编写 Java 代码。
        1. 创建 Java 对象的实例。
    --%>
    <%
        MessageGenerator generator = new MessageGenerator();
    %>
    <%--
        2. 调用 Java 方法并使用内联表达式 <%= ... %> 将结果输出到 HTML 中。
    --%>
    <p>
        消息: <%= generator.getWelcomeMessage() %>
    </p>
    <%--
        警告:下面的方式更糟糕,直接在 HTML 中写逻辑!
    --%>
    <%
        String currentTime = new java.util.Date().toString();
    %>
    <p>当前时间 (通过脚本片段): <%= currentTime %></p>
</body>
</html>

为什么这种方式不推荐?

  • 代码混乱:HTML、JavaScript 和 Java 代码混在一起,难以阅读和维护。
  • 高耦合:视图(JSP)和业务逻辑(Java)紧密绑定,修改业务逻辑可能需要修改 JSP 页面。
  • 可测试性差:无法对 JSP 页面中的 Java 逻辑进行单元测试。
  • 安全隐患:容易受到跨站脚本攻击。

使用后端框架 (如 Spring MVC) (最佳实践)

在现代 Java Web 开发中,我们通常使用框架如 Spring MVC,它本质上是对 方式一(AJAX) 的封装和规范化,使得开发更加高效和结构化。

工作流程与 AJAX 类似,但代码组织更清晰:

  1. 前端 (JSP/JS):与 AJAX 方式完全相同,使用 fetch 发送请求到某个 URL(如 /api/hello)。
  2. 后端 (Spring Controller)
    • 使用 @RestController@Controller + @ResponseBody 来创建一个控制器。
    • @RequestMapping@GetMapping 来映射 URL 到 Java 方法。
    • Java 方法可以直接返回一个 Java 对象,框架(如 Jackson)会自动将其序列化为 JSON 并返回。
    • 依赖注入:可以直接在 Controller 中注入 Service 层,Service 层再注入 Repository(DAO)层,实现完美的分层解耦。

示例:Spring MVC 调用 Java 方法

Spring Controller

HelloController.java

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController // @RestController = @Controller + @ResponseBody,表示所有方法都返回 JSON/XML
@RequestMapping("/api") // 为所有这个类下的方法添加前缀 /api
public class HelloController {
    // @GetMapping 映射 GET 请求
    // 这个方法会自动处理请求并返回 JSON
    @GetMapping("/hello")
    public String getGreeting() {
        return "Hello from Spring! The time is: " + new java.util.Date();
    }
    // 也可以返回复杂对象
    @GetMapping("/user")
    public User getUser() {
        User user = new User();
        user.setName("John Doe");
        user.setEmail("john.doe@example.com");
        return user;
    }
}
// 一个简单的 POJO
class User {
    private String name;
    private String email;
    // Getters and Setters...
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

注意:你需要 Spring MVC 和 Jackson (用于 JSON 序列化) 的依赖。

JSP 前端

前端代码与 AJAX 方式中的 index.jsp 几乎完全一样,只需要修改 fetch 的 URL 即可。

// 将 fetch 的 URL 改为 /your-app-context/api/hello
fetch('/your-app-context/api/hello') 
    .then(response => response.json()) // Spring MVC 返回的 Content-Type 通常是 application/json
    .then(data => {
        document.getElementById('result').textContent = data;
    });

总结与对比

特性 AJAX (Servlet) JSP 内联脚本 Spring MVC (框架)
推荐度 ⭐⭐⭐⭐ (纯 Servlet 项目) ⭐ (不推荐) ⭐⭐⭐⭐⭐ (现代项目首选)
核心思想 JS 发送 HTTP 请求,Servlet 返回 JSON 在 JSP 中直接嵌入 Java 代码 Controller 处理请求,返回 JSON/XML
前后端分离
代码耦合度 极高
可维护性 极低 非常高
学习曲线 中等 简单 (但坏习惯) 中等 (但值得)
适用场景 简单项目、学习 Servlet 原理 维护老旧项目 所有现代 Java Web 应用
  • 如果你在学习 Servlet 原理或做一个简单的、不涉及框架的项目,请使用 AJAX 方式
  • 如果你在维护一个老旧的 JSP 项目,你可能会遇到 JSP 内联脚本 的代码,但新功能请尽量用 AJAX 重构。
  • 如果你在开发任何新的、现代的 Java Web 应用,请直接使用 Spring MVC 或类似的框架,这是最佳实践。
分享:
扫描分享到社交APP
上一篇
下一篇