傳統 AJAX 直接接收 HTML 片段或純文字回應,雖然簡單但靈活性差、前後端耦合度高。現代 Web 開發標準化採用 **JSON** 作為資料交換格式。本文詳細講解從 Servlet 後端構建 JSON、前端 jQuery 解析渲染的完整鏈路,助你實現真正的前後端分離雛形。
推薦使用 **Jackson** 或 **Gson** 庫,手動拼接 JSON 字串極易出錯且難維護。
// 依賴: Jackson (jackson-databind)
@WebServlet("/api/users")
public class UserServlet extends HttpServlet {
private ObjectMapper mapper = new ObjectMapper(); // Jackson 核心
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
List users = userService.findAll(); // 假設查詢邏輯
resp.setContentType("application/json;charset=UTF-8");
// 直接序列化寫入輸出流,高效且無編碼煩惱
mapper.writeValue(resp.getOutputStream(), users);
}
}
關鍵在於設定 `dataType: 'json'`,jQuery 會自動解析 `responseText` 為 JS 物件/陣列,直接在 `success` 回調中使用。
$.ajax({
url: '/api/users',
type: 'GET',
dataType: 'json', // 關鍵:自動解析 JSON
success: function(users) { // users 已是 JS 陣列 [User, User, ...]
console.log('收到用戶數:', users.length);
// 範例:動態渲染表格
var $tbody = $('#userTable tbody').empty();
$.each(users, function(i, user) {
$tbody.append(
'<tr>' +
'<td>' + user.id + '</td>' +
'<td>' + user.name + '</td>' +
'<td>' + user.email + '</td>' +
'</tr>'
);
});
},
error: function(xhr, status, err) {
console.error('請求失敗:', status, err);
}
});
前端發送 JSON 給後端,需設定 `contentType: 'application/json'` 並手動序列化:
var newUser = { name: '李四', email: 'lisi@example.com' };
$.ajax({
url: '/api/users',
type: 'POST',
contentType: 'application/json;charset=UTF-8', // 告訴後端我發的是 JSON
data: JSON.stringify(newUser), // JS 物件 -> JSON 字串
dataType: 'json', // 期望回應也是 JSON
success: function(savedUser) {
alert('新增成功,ID: ' + savedUser.id);
}
});
後端 Servlet 使用 `mapper.readValue(req.getInputStream(), User.class)` 反序列化。
| 現象 | 原因 | 解決 |
|---|---|---|
| 前端 `success` 不執行,`error` 回調 `parsererror` | 後端輸出非合法 JSON (如多輸出空白行、JSP 混雜 HTML、拋出異常堆疊) | 確保 Servlet **只** 輸出 JSON;設定 `resp.setContentType("application/json")`;全域異常處理器返回 JSON 格式錯誤碼 |
| 中文亂碼 | 編碼不一致 | 全鏈路 UTF-8:DB 連線、JSP `pageEncoding`、Servlet `resp.setCharacterEncoding`、JSON 庫預設即 UTF-8 |
| 大數據量序列化慢 / OOM | 一次性載入全量物件到記憶體 | 使用 Jackson `JsonGenerator` 流式寫入;或分頁載入 |
| 日期格式不一致 | 預設序列化為 timestamp 數字 | 配置 `mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))` 或用 `@JsonFormat` 註解 |
**「後端只做資料,前端只做視圖」**,JSON 是連接兩者的標準橋樑。拥抱 Jackson/Gson + jQuery `dataType: 'json'`,徹底告別字串拼接與 HTML 片段注入的混亂時代,為後續引入 Vue/React/Axios 打下堅實基礎。