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

主要有以下三种方式,我会按照从最推荐到不推荐的顺序进行讲解:
- AJAX (推荐):现代、标准、灵活的方式。
- JSP 内联表达式/脚本 (不推荐):老旧、耦合度高、维护困难的方式。
- 后端框架 (如 Spring MVC, Struts2) (最佳实践):在大型项目中,这是最规范、最强大的方式。
使用 AJAX (Asynchronous JavaScript and XML)
这是目前最主流、最推荐的方式,工作流程如下:
- 客户端 (JSP/JS):
- 用户在页面上进行某个操作(如点击按钮)。
- JavaScript 监听这个事件,然后通过
XMLHttpRequest或fetchAPI 向服务器发送一个 HTTP 请求(通常是 GET 或 POST)。 - 这个请求会指向一个特定的 URL(
/your-app/data)。
- 服务器端 (Java Servlet):
- 一个 Java Servlet 或 Controller 接收到这个 HTTP 请求。
- Servlet 调用你想要执行的 Java 方法(从数据库查询数据、进行计算等)。
- 将 Java 方法执行的结果(数据)转换成一种通用的格式,最常用的是 JSON。
- 响应返回客户端:
服务器将 JSON 数据作为 HTTP 响应体返回给客户端的浏览器。
- 客户端 (JS):
- JavaScript 的回调函数接收到这个 HTTP 响应。
- 解析 JSON 数据。
- 使用 JavaScript 动态更新页面的内容,而无需刷新整个页面。
示例:AJAX 调用 Java 方法
目标:在 JSP 页面上点击一个按钮,调用服务器端的 Java 方法,获取一个 "Hello from Java!" 的字符串,并显示在页面上。

创建 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 中添加:

<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 类似,但代码组织更清晰:
- 前端 (JSP/JS):与 AJAX 方式完全相同,使用
fetch发送请求到某个 URL(如/api/hello)。 - 后端 (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 或类似的框架,这是最佳实践。
