Spring Boot (Java/Kotlin) 作为主应用程序,负责业务流程的控制和 HTTP 接口的暴露;Python 作为计算引擎,负责执行复杂的计算任务,两者之间通过进程间通信进行数据交换。

下面我将详细介绍几种主流的实现方式,并给出各自的优缺点和代码示例。
通过 Process (命令行调用)
这是最直接、最简单的方式,Spring Boot 使用 Java 的 ProcessBuilder 或 Runtime 类来启动一个新的 Python 进程,就像在终端里运行 python script.py 一样。
工作原理
- Spring Boot 构造一个执行命令(
python /path/to/script.py arg1 arg2)。 - 通过
ProcessBuilder启动这个命令,创建一个子进程。 - 通过标准输入、标准输出、标准错误流与子进程进行通信。
- 等待 Python 进程执行完毕,获取其返回结果。
优点
- 实现简单:不需要任何额外的框架或中间件,是 Java 语言内置的能力。
- 解耦性好:Python 脚本可以独立于 Java 项目开发和部署,版本管理灵活。
- 通用性强:任何可以命令行执行的 Python 脚本都可以被调用。
缺点
- 性能开销:每次调用都需要创建一个新的 Python 进程,启动和销毁进程有性能成本,不适合高频、低延迟的调用。
- 通信复杂:数据需要通过字符串(JSON, CSV等)在流中传递,需要手动进行序列化和反序列化。
- 资源管理:需要手动管理子进程的生命周期,Python 脚本崩溃,Java 端需要妥善处理,避免资源泄漏。
- 调试困难:两个进程间的错误排查相对麻烦。
代码示例
Python 脚本 (src/main/resources/scripts/process_example.py)
这个脚本接受一个名字作为命令行参数,并返回一个 JSON 格式的问候语。

import sys
import json
import datetime
def main():
# 从命令行参数获取输入
if len(sys.argv) > 1:
name = sys.argv[1]
else:
name = "Stranger"
# 准备返回数据
result = {
"message": f"Hello, {name}! Greetings from Python.",
"timestamp": datetime.datetime.now().isoformat()
}
# 将结果以 JSON 格式输出到标准输出
print(json.dumps(result))
if __name__ == "__main__":
main()
Spring Boot Controller
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@RestController
public class PythonController {
private static final String PYTHON_SCRIPT_PATH = "src/main/resources/scripts/process_example.py";
@GetMapping("/hello-python")
public String callPythonScript(@RequestParam(defaultValue = "World") String name) {
ProcessBuilder processBuilder = new ProcessBuilder("python", PYTHON_SCRIPT_PATH, name);
processBuilder.redirectErrorStream(true); // 合并错误流和输出流
try {
Process process = processBuilder.start();
// 读取 Python 脚本的输出
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder output = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
output.append(line);
}
int exitCode = process.waitFor();
if (exitCode == 0) {
return "Python script executed successfully. Output: " + output;
} else {
return "Error executing Python script. Exit code: " + exitCode + ". Output: " + output;
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException("Failed to execute Python script", e);
}
}
}
通过 HTTP 请求 (REST API)
这种方式下,Python 脚本本身启动一个 Web 服务器(如 Flask, Django, FastAPI),Spring Boot 作为客户端向这个 Python 服务发送 HTTP 请求。
工作原理
- Python 应用(Flask 应用)独立启动并监听一个端口(如 5000)。
- Spring Boot 应用通过
RestTemplate或WebClient等 HTTP 客户端工具,向 Python 服务的 API 端点发送请求(通常是 POST,携带 JSON 数据)。 - Python 服务处理请求并返回 JSON 响应。
- Spring Boot 接收并解析响应。
优点
- 异步和非阻塞:Spring Boot 可以异步调用 Python 服务,不会阻塞主线程,提高吞吐量。
- 易于扩展:Python 服务可以独立部署、水平扩展(例如使用 Nginx 负载均衡多个 Python 实例)。
- 技术栈解耦:前后端完全分离,团队可以独立开发和维护。
- 标准通信:HTTP/JSON 是业界标准,工具链成熟。
缺点
- 部署复杂:需要管理两个独立的应用,涉及端口管理、服务发现等问题。
- 网络延迟:跨网络通信(即使是本地回环)比进程内通信有更高的延迟。
- 架构变重:从一个单体应用变成了一个微服务架构,增加了系统复杂性。
代码示例
Python Flask 服务 (python_server.py)
from flask import Flask, request, jsonify
import datetime
app = Flask(__name__)
@app.route('/process', methods=['POST'])
def process_data():
data = request.get_json()
if not data or 'name' not in data:
return jsonify({"error": "Missing 'name' in request body"}), 400
name = data['name']
result = {
"message": f"Hello, {name}! Greetings from Python via HTTP.",
"timestamp": datetime.datetime.now().isoformat()
}
return jsonify(result)
if __name__ == '__main__':
# 在生产环境中,应使用 Gunicorn 或 uWSGI 等应用服务器
app.run(port=5000, debug=True)
启动 Python 服务
在终端运行:
python python_server.py

Spring Boot Controller
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class HttpPythonController {
private final RestTemplate restTemplate;
private static final String PYTHON_SERVICE_URL = "http://localhost:5000/process";
public HttpPythonController(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
@PostMapping("/call-http-python")
public String callPythonService(@RequestBody Map<String, String> payload) {
// 构造请求体
Map<String, String> requestBody = new HashMap<>();
requestBody.put("name", payload.getOrDefault("name", "World"));
try {
// 发送 POST 请求并获取响应
String response = restTemplate.postForObject(PYTHON_SERVICE_URL, requestBody, String.class);
return "Successfully called Python HTTP service. Response: " + response;
} catch (Exception e) {
return "Error calling Python HTTP service: " + e.getMessage();
}
}
}
注意:你需要配置 RestTemplate Bean,或者直接使用 WebClient (推荐)。
通过 gRPC (高性能 RPC)
gRPC 是由 Google 开发的高性能、开源的通用 RPC 框架,它使用 Protocol Buffers (protobuf) 作为接口定义语言和数据序列化格式。
工作原理
- 定义服务:使用
.proto文件定义服务接口和消息格式。 - 生成代码:使用
protoc编译器为 Java 和 Python 生成客户端和服务端代码。 - 实现服务:Python 端实现生成的服务接口,Java 端调用生成的客户端代码。
- 通信:Java 和 Python 通过 gRPC 进行高效的二进制通信。
优点
- 高性能:基于 HTTP/2 和 Protocol Buffers,比 JSON/HTTP 快得多,延迟低。
- 强类型:
.proto文件定义了严格的接口契约,避免了因数据格式不一致导致的错误。 - 流式支持:支持客户端流、服务端流和双向流,非常适合实时数据传输场景。
- 跨语言:原生支持多种语言,集成非常规范。
缺点
- 学习曲线陡峭:需要学习 gRPC 和 Protocol Buffers 的概念和使用方法。
- 灵活性较低:接口一旦定义并生成代码,修改起来比较麻烦。
- 调试复杂:二进制协议不如 HTTP/JSON 直观,调试工具需要专门支持。
代码示例 (简略步骤)
定义 .proto 文件 (greeter.proto)
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.example.grpc";
option java_outer_classname = "GreeterProto";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
生成代码
为 Java 和 Python 分别安装 protoc 和相应的插件,然后编译 .proto 文件。
Python gRPC 服务端
from concurrent import futures
import grpc
import greeter_pb2
import greeter_pb2_grpc
class GreeterServicer(greeter_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return greeter_pb2.HelloReply(message=f"Hello, {request.name}! Greetings from gRPC.")
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
greeter_pb2_grpc.add_GreeterServicer_to_server(GreeterServicer(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
serve()
Spring Boot gRPC 客户端
import com.example.grpc.GreeterGrpc;
import com.example.grpc.GreeterProto;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GrpcPythonController {
// GrpcClient 会自动注入到 gRPC 客户端存根
@GrpcClient("python-service") // 需要在配置中指定这个服务的地址
private GreeterGrpc.GreeterBlockingStub greeterBlockingStub;
@GetMapping("/call-grpc-python")
public String callPythonGrpc(@RequestParam(defaultValue = "gRPC User") String name) {
GreeterProto.HelloRequest request = GreeterProto.HelloRequest.newBuilder().setName(name).build();
GreeterProto.HelloReply response = greeterBlockingStub.sayHello(request);
return "Successfully called Python gRPC service. Response: " + response.getMessage();
}
}
注意:Spring Boot 需要集成 grpc-spring-boot-starter 来简化 gRPC 客户端的使用。
通过 Jython (Java 内嵌 Python)
Jython 是一个用 Java 实现的 Python 解释器,它允许 Python 代码直接在 JVM 上运行,并能无缝调用 Java 类库。
工作原理
- 在 Spring Boot 项目中引入 Jython 依赖。
- 通过 Jython 提供的 API 加载并执行 Python 脚本。
- Python 脚本可以直接调用 Java 代码。
优点
- 真正的“嵌入”:没有进程创建开销,性能高。
- 无缝集成:Python 和 Java 对象可以互相直接调用,数据转换开销极小。
- 共享内存:两者运行在同一个 JVM 中,共享内存空间。
缺点
- 兼容性问题:Jython 不支持 Python 3,目前只支持非常古老的 Python 2.x 版本,这使其在现代项目中几乎不可用。
- 生态限制:无法使用绝大多数现代 Python 库(如 NumPy, Pandas, TensorFlow 等),因为这些库通常依赖 C 扩展。
- 维护停滞:Jython 项目活跃度很低,更新缓慢。
不推荐在新项目中使用 Jython,除非你有非常特殊的遗留需求(维护一个基于 Python 2 的脚本),否则应优先考虑其他方案。
总结与选型建议
| 方案 | 性能 | 实现复杂度 | 解耦性 | 适用场景 |
|---|---|---|---|---|
| Process (命令行) | 低 (进程开销) | 简单 | 好 | 一次性任务、脚本调用、低频调用 |
| HTTP (REST API) | 中 (网络开销) | 中等 | 最好 | 微服务架构、异步任务、Python 服务独立部署 |
| gRPC | 高 | 复杂 | 好 | 高性能计算、实时通信、对延迟敏感的场景 |
| Jython | 高 (无进程开销) | 简单 | 差 | 不推荐 (仅限 Python 2 遗留系统) |
如何选择?
- 快速原型/一次性任务:如果你的 Python 脚本只是偶尔被调用,且性能要求不高,方案一 (Process) 是最快、最简单的选择。
- 构建现代化、可扩展的系统:如果你的 Python 计算模块是一个核心服务,未来可能需要独立部署或扩展,方案二 (HTTP) 是最稳妥、最符合现代架构的选择。
- 追求极致性能:如果你的应用对延迟要求极其苛刻(例如高频交易、实时游戏),并且愿意投入前期学习成本,方案三 (gRPC) 是最佳的性能解决方案。
- 维护旧系统:如果你遇到一个古老的 Python 2 系统,且无法迁移,才考虑 方案四 (Jython),但请务必评估其风险。
对于大多数 Spring Boot 与 Python 集成的场景,从 HTTP API 开始 是最常见和最灵活的实践,如果后续发现性能瓶颈成为瓶颈,再考虑迁移到 gRPC。
