api vs jsp 绑定风格
这是一个关于 Java Web Servlet 接口的示例,我将为您创建两个 Servlet:
- 一个支持 cURL 或任何标准 HTTP 客户端调用的接口 (
CurlCallableServlet)。 - 一个通常不直接 设计为 cURL 调用,而是与 JSP 页面集成(用于渲染视图)的接口 (
JspBoundServlet)。
请注意:从技术上讲,任何暴露 HTTP 端点的 Servlet 都可以被 cURL 调用。这里的"不支持"主要是指它的设计意图和通常用法:它通常会将请求转发给一个 JSP 页面来生成完整的 HTML 响应,而不是像 API 接口那样直接返回数据。
1. 支持 cURL 调用的 Servlet (API 风格)
这个 Servlet 通常用于提供 API 服务,它直接返回数据(例如 JSON 或纯文本),可以轻松地被 cURL 或其他编程客户端调用。
文件: CurlCallableServlet.java
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// 使用 @WebServlet 注解,映射到 /api/data 路径
@WebServlet("/api/data")
public class CurlCallableServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. 设置响应的内容类型为 JSON,方便客户端(如 cURL)解析
response.setContentType("application/json");
// 2. 设置字符编码
response.setCharacterEncoding("UTF-8");
// 3. 构造要返回的数据
String name = request.getParameter("name");
String message = (name != null && !name.isEmpty()) ?
"Hello, " + name + "! Data fetched successfully." :
"Data fetched successfully for an anonymous user.";
// 4. 简单 JSON 格式输出
String jsonResponse = String.format(
"{\"status\":\"success\", \"message\":\"%s\", \"timestamp\":%d}",
message, System.currentTimeMillis());
// 5. 写入响应
PrintWriter out = response.getWriter();
out.print(jsonResponse);
out.flush();
}
}
cURL 调用示例 (假设您的应用运行在 http://localhost:8080):
# 简单的 GET 请求
curl http://localhost:8080/yourapp/api/data
# 带有参数的 GET 请求
curl "http://localhost:8080/yourapp/api/data?name=UserA"
# 预期输出类似:
# {"status":"success", "message":"Hello, UserA! Data fetched successfully.", "timestamp":1701234567890}
2. 不支持 cURL 调用的 Servlet (JSP 绑定风格)
这个 Servlet 通常用于 MVC (Model-View-Controller) 模式的 Controller 部分。它的主要工作是处理请求、准备数据,然后使用 RequestDispatcher 将控制权转发 给一个 JSP 视图来渲染完整的 HTML 页面。如果用 cURL 调用,它会返回一个完整的 HTML 页面,而不是简洁的数据,所以通常认为它"不支持"直接作为 API 调用。
文件: JspBoundServlet.java
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// 映射到 /app/page 路径
@WebServlet("/app/page")
public class JspBoundServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. **不设置 ContentType** (通常由 JSP 来处理最终的 HTML 响应)
// 2. 准备数据 (Model)
String user = "Guest";
String time = new java.util.Date().toString();
// 3. 将数据放入 request 作用域,供 JSP 访问
request.setAttribute("username", user);
request.setAttribute("serverTime", time);
// 4. **转发**请求到 JSP 视图 (View)
// 核心区别:它不自己写响应,而是把响应生成任务交给 JSP。
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/views/welcome.jsp");
dispatcher.forward(request, response);
// 注意:在这个 Servlet 方法中,response.getWriter().print(...) 不会被调用
// 所有输出都由 JSP 负责。
}
}
JSP 文件: /WEB-INF/views/welcome.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Welcome Page</title>
</head>
<body>
<h1>Hello, ${username}!</h1>
<p>This is a view rendered by JSP.</p>
<p>Current Server Time: <strong>${serverTime}</strong></p>
<button onclick="alert('This is a button for a real user.')">Click Me</button>
</body>
</html>
cURL 调用示例 (假设您的应用运行在 http://localhost:8080):
curl http://localhost:8080/yourapp/app/page
# 预期输出:返回的是整个 HTML 页面内容,包含 <head>, <body> 等标签,
# 客户端(cURL)通常只想要数据的场景下,这种输出是不合适的。
# <!DOCTYPE html><html><head>...</head><body>...</body></html>
总结比较
| 特性 | CurlCallableServlet (API 风格) | JspBoundServlet (JSP 绑定风格) |
|---|---|---|
| 设计意图 | 提供结构化数据(JSON/XML)作为 API | 作为控制器,处理请求后转发给视图(JSP) |
| 响应内容 | application/json 或 text/plain |
text/html (由 JSP 生成) |
| 主要方法 | response.getWriter().print(...) 直接输出数据 |
request.getRequestDispatcher().forward(...) 转发到 JSP |
| cURL 适用性 | 非常适用 (返回简洁数据) | 不适用 (返回完整的 HTML 页面) |