SpringMVC 註解開發實戰 (十):商品修改功能全流程與 Controller 返回值藝術
本文以「商品修改」為例,完整演示 SpringMVC 註解式開發流程:Mapper → Service → Controller → JSP,重點講解 `@RequestMapping` 進階用法、Controller 多種返回值類型 (`ModelAndView`、`String`、`void`) 的語義差異與適用場景,助你掌握 Web 層開發精髓。
一、需求流程
- 進入商品列表頁 (`/items/queryItems.action`)。
- 點擊「修改」→ 根據 ID 查詢商品 → 跳轉修改頁 (`/items/editItems.action`),回顯數據。
- 修改提交 (`/items/editItemsSubmit.action`) → 更新數據庫 → 返回成功頁或重定向列表。
二、Mapper 層 (MyBatis 逆向工程生成)
- `Items selectByPrimaryKey(Integer id)` — 查詢單條。
- `int updateByPrimaryKeyWithBLOBs(Items record)` — 全字段更新 (含大文本)。
三、Service 層
public interface ItemsService {
ItemsCustom findItemsById(Integer id) throws Exception;
void updateItems(Integer id, ItemsCustom itemsCustom) throws Exception;
}
@Service
public class ItemsServiceImpl implements ItemsService {
@Autowired private ItemsMapper itemsMapper;
public ItemsCustom findItemsById(Integer id) {
Items items = itemsMapper.selectByPrimaryKey(id);
ItemsCustom custom = new ItemsCustom();
BeanUtils.copyProperties(items, custom); // 屬性拷貝
return custom;
}
public void updateItems(Integer id, ItemsCustom custom) {
// 業務校驗:id 非空、價格合法等
custom.setId(id); // 必須回填 ID,updateByPrimaryKeyWithBLOBs 依賴主鍵
itemsMapper.updateByPrimaryKeyWithBLOBs(custom);
}
}
四、Controller 層核心代碼
@Controller
@RequestMapping("/items")
public class ItemsController {
@Autowired private ItemsService itemsService;
// 1. 商品列表
@RequestMapping("/queryItems")
public ModelAndView queryItems() throws Exception {
List list = itemsService.findItemsList(null);
ModelAndView mv = new ModelAndView();
mv.addObject("itemsList", list);
mv.setViewName("items/itemsList"); // 視圖解析器拼接:/WEB-INF/jsp/items/itemsList.jsp
return mv;
}
// 2. 修改頁面回顯 — 支援 GET/POST
@RequestMapping(value="/editItems", method={RequestMethod.GET, RequestMethod.POST})
public ModelAndView editItems() throws Exception {
ItemsCustom custom = itemsService.findItemsById(1); // 實際從請求參數獲取 ID
ModelAndView mv = new ModelAndView();
mv.addObject("itemsCustom", custom);
mv.setViewName("items/editItems");
return mv;
}
// 3. 修改提交
@RequestMapping("/editItemsSubmit")
public ModelAndView editItemsSubmit(HttpServletRequest request, Integer id, ItemsCustom itemsCustom) throws Exception {
itemsService.updateItems(id, itemsCustom);
ModelAndView mv = new ModelAndView();
mv.setViewName("success");
return mv;
}
}
五、@RequestMapping 進階用法
| 用法 | 示例 | 作用 |
| 類級別根路徑 | `@RequestMapping("/items")` | URL 分類管理,子路徑自動拼接 |
| 方法級別映射 | `@RequestMapping("/editItems")` | 精確匹配 URL |
| 限制 HTTP 方法 | `method={RequestMethod.POST, RequestMethod.GET}` | 安全防護,拒絕非預期方法 (405) |
| Ant 風格模糊匹配 | `/items/**`、`/items/*.action` | 批量映射,慎用避免衝突 |
| 參數條件映射 | `params="id"`、`params="!id"` | 同一 URL 不同參數路由到不同方法 |
| Header 條件映射 | `headers="content-type=application/json"` | RESTful API 版本協商 |
六、Controller 返回值類型深度解析
| 返回類型 | 語義 | 典型場景 | 視圖解析 |
ModelAndView | 攜帶 Model 數據 + View 名稱 | 傳統頁面渲染,需同時設置數據與視圖 | ViewResolver 拼接前綴後綴 |
String (視圖名) | 邏輯視圖名 | 僅需指定視圖,Model 通過參數 `Model`/`ModelMap` 填充 | 同上 |
String `redirect:` | 重定向 (HTTP 302) | **表單提交後** 防止重複提交 (PRG 模式),地址欄 URL 變化 | 不走 ViewResolver,直接響應 Location |
String `forward:` | 服務端轉發 | 內部流程跳轉,地址欄不變,Request 共享 | RequestDispatcher.forward |
void | 自行控制響應 | AJAX 返回 JSON、文件下載、流式輸出、自定義狀態碼 | 無,手動 `response.getWriter()` / `outputStream` |
| `@ResponseBody` + 對象 | 直接序列化為 JSON/XML | RESTful API、異步請求 | HttpMessageConverter 處理 |
七、最佳實踐:PRG 模式 (Post-Redirect-Get)
@RequestMapping("/editItemsSubmit")
public String editItemsSubmit(Integer id, ItemsCustom custom) {
itemsService.updateItems(id, custom);
// 重定向到列表頁,防止 F5 重複提交
return "redirect:queryItems.action";
}
核心優勢:瀏覽器歷史記錄不保留 POST 請求,用戶刷新/後退不會重複提交表單。
八、JSP 表單綁定關鍵點
- 表單 `name` **必須與 POJO 屬性名一致** (非參數名),SpringMVC 自動綁定嵌套屬性 (如 `itemsCustom.name`)。
- 日期類型需註冊 `Converter` (參考上篇)。
總結
SpringMVC 註解開發核心在於:**URL 與方法精準映射**、**Model 數據與視圖解耦**、**返回值類型語義化選擇**。掌握 `ModelAndView`/`String`/`void`/`redirect:`/`forward:`/`@ResponseBody` 六大返回模式,並養成 PRG 模式習慣,即可編寫出清晰、健壯、易維護的 Web 控制層代碼。
- 上一篇文章: ZooKeeper 集群部署與 Java 客戶端實戰:從單機模擬到生產級配置
- 下一篇文章: SpringMVC 整合 MyBatis 實戰 (九):DispatcherServlet 配置、視圖解析器與 Controller 編寫規範
Copyright ©
程式碼之家 All Rights Reserved