Spring MVC 以註解驅動簡化 Web 開發。本文系統講解 @Controller、@RequestMapping (含 URI 模板、通配符、限制條件)、參數綁定註解 (@RequestParam/@PathVariable/@CookieValue/@RequestHeader)、處理器方法參數/返回值類型、@ModelAttribute/@SessionAttributes 數據共享、自定義類型轉換器 (@InitBinder/WebBindingInitializer),附帶實戰代碼與最佳實踐。
@Controller
public class MyController { ... }
需在 Spring MVC 配置中掃描:
<context:component-scan base-package="com.example.controller">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
或在 Java Config 中 @ComponentScan。
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/list")
public String list() { ... } // 訪問 /user/list
}
@RequestMapping("/{userId}/profile")
public String profile(@PathVariable String userId, @PathVariable("nickName") String nick) { ... }
// 訪問 /123/profile?nickName=abc -> userId=123, nick=abc
@PathVariable("name")(需編譯保留參數名 -parameters)。
@RequestMapping("/api/*/version") // 匹配 /api/v1/version, /api/test/version
@RequestMapping("/resources/**") // 匹配多級路徑
@RequestMapping(value="/save", method=RequestMethod.POST, params="action=save", headers="content-type=application/json")
public String save() { ... }
| 註解 | 來源 | 關鍵屬性 |
|---|---|---|
| @RequestParam | 請求參數 | value/name, required(default true), defaultValue |
| @PathVariable | URI 模板變量 | value/name |
| @CookieValue | Cookie | value/name, required, defaultValue |
| @RequestHeader | 請求頭 | value/name, required, defaultValue (大小寫不敏感) |
注意:非 required=false 且參數缺失會拋 400 錯誤。
HttpServletRequest, HttpServletResponse, HttpSession, Principal, Locale, InputStream, OutputStream, Reader, Writer。WebRequest, Model, ModelMap, Map, Errors/BindingResult (緊跟 @Valid 實體後)。MultipartFile, Part。| 返回類型 | 處理邏輯 |
|---|---|
| ModelAndView | 包含視圖名與模型數據 |
| Model/ModelMap/Map | 僅模型,視圖由 RequestToViewNameTranslator 推導 |
| View | 直接渲染視圖 |
| String | 視圖名 |
| void | 自寫響應或推導視圖名 |
| @ResponseBody + 任意類型 | 經 HttpMessageConverter 序列化寫入響應體 (JSON/XML) |
| 其他 | 作為模型屬性,屬性名可用 @ModelAttribute 指定 |
@Controller
@RequestMapping("/demo")
@SessionAttributes(names="user", types=User.class) // 指定哪些屬性存入 Session
public class DemoController {
@ModelAttribute("initData")
public String init() { return "hello"; } // 執行於每個 @RequestMapping 方法前
@RequestMapping("/show")
public void show(@ModelAttribute("initData") String data, Writer w) throws IOException {
w.write(data); // 獲得 "hello"
}
}
@ModelAttribute("name") 指定,否則用返回類型首字母小寫。@SessionAttributes,匹配的屬性會在請求結束後存入 Session,下次請求從 Session 取出。
@RequestMapping("/edit")
public String edit(@ModelAttribute("user") User user) { ... } // 從模型/Session 獲取 user
value/names:指定屬性名。types:指定類型,屬性名為類型首字母小寫。SessionStatus.setComplete()。
@Controller
public class MyController {
@InitBinder
public void binder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyyMMdd"), true));
binder.registerCustomEditor(User.class, new PropertyEditorSupport() {
@Override public void setAsText(String text) { setValue(new User(text)); }
@Override public String getAsText() { return ((User)getValue()).getName(); }
});
}
}
@Component
public class GlobalBinder implements WebBindingInitializer {
@Override public void initBinder(WebDataBinder binder, WebRequest request) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
}
// Spring MVC 配置注入
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean class="com.example.GlobalBinder"/>
</property>
</bean>
每個帶 @RequestParam/@PathVariable/@RequestHeader/@CookieValue/@ModelAttribute 的參數都會觸發一次 initBinder。
Spring MVC 註解體系極其豐富,核心掌握:請求映射 → 參數綁定 → 模型構建 → 視圖解析 → 響應輸出。善用 @ModelAttribute/@SessionAttributes 簡化跨請求數據流轉,@InitBinder 解決特殊格式綁定,@ResponseBody 構建 REST API。