首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring MVC Controller 完整指南:@Controller、@RequestMapping 進階映射、參數綁定、類型轉換與 Session 管理

     編輯:Java 綜合教學

Spring MVC Controller 完整指南:@Controller、@RequestMapping 進階映射、參數綁定、類型轉換與 Session 管理

Spring MVC 中 Controller 負責接收請求、協調業務邏輯、封裝模型資料並指向視圖。本文系統整理 @Controller 定義、@RequestMapping 多維映射、方法參數/返回值支援、@ModelAttribute/@SessionAttributes 資料共享、以及自訂類型轉換器。

一、定義 Controller:@Controller + 組件掃描

@Controller
public class MyController {
    @RequestMapping("/showView")
    public ModelAndView showView() {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("viewName");
        mav.addObject("attrName", "attrValue");
        return mav;
    }
}

兩種註冊方式:

  1. XML 顯式定義:<bean class="com.xxx.MyController"/>
  2. 組件掃描(推薦):<context:component-scan base-package="com.xxx.web.controller"> 可排除 @Service 等。

二、@RequestMapping 多維映射

1. 類別層級與方法層級組合

  • 類別無 @RequestMapping → 方法路徑為絕對路徑(相對 context root)。
  • 類別有 @RequestMapping("/test") → 方法路徑相對於類別路徑(/test/showView)。

2. URI 模板與 @PathVariable

@Controller
@RequestMapping("/test/{category}")
public class MyController {
    @RequestMapping("/detail/{id}")
    public ModelAndView detail(@PathVariable String category, @PathVariable int id) { ... }
}
  • /test/books/detail/101 → category="books", id=101。
  • @PathVariable("id") 可指定模板變數名,避免非 debug 編譯失效。
  • 支援通配符 *:@RequestMapping("*/wildcard")。

3. 參數綁定註解

註解來源屬性必要性
@RequestParam請求參數value/name, required(default true), defaultValuerequired=false 可選
@CookieValueCookievalue, required, defaultValue同 @RequestParam
@RequestHeader請求頭value, required, defaultValue大小寫不敏感
@RequestMapping("/param")
public String param(@RequestParam(required=false) String name, @RequestParam("age") int age) { ... }

4. 進階縮小映射範圍

  • params:@RequestMapping(value="/test", params={"p1=v1", "p2", "!p3"}) → p1 必等於 v1、p2 必存在、p3 必不存在。
  • method:method={RequestMethod.GET, RequestMethod.POST} 限制 HTTP 方法。
  • headers:headers={"Host=localhost", "Accept"} 限制請求頭。

三、支援的方法參數類型

  1. Servlet API:HttpServletRequest, HttpServletResponse, HttpSession(注意 Session 可能為 null)。
  2. WebRequest、NativeWebRequest。
  3. IO 流:InputStream/Reader(請求體)、OutputStream/Writer(回應體)。
  4. 綁定註解參數:@PathVariable, @RequestParam, @CookieValue, @RequestHeader。
  5. @ModelAttribute 標記的命令物件/表單物件。
  6. Map/Model/ModelMap:注入模型資料供視圖渲染。
  7. 實體類別(命令物件):自動綁定請求參數到屬性。
  8. MultipartFile:檔案上傳。
  9. Errors/BindingResult:緊接在驗證物件之後,保存驗證結果。

四、支援的返回值類型

  1. ModelAndView:模型+視圖名稱。
  2. Model/ModelMap/Map:僅模型,視圖名由 RequestToViewNameTranslator 推斷。
  3. View 物件:直接渲染,可配合模型參數。
  4. String:視圖名稱,可配合模型參數。
  5. void:自寫回應或由 RequestToViewNameTranslator 推斷視圖。
  6. 加 @ResponseBody:透過 HttpMessageConverter 直接寫入回應體(REST API 常用)。
  7. 其他類型:視為模型單一屬性,屬性名預設為類名首字母小寫,可用 @ModelAttribute("name") 指定。

五、@ModelAttribute 與 @SessionAttributes 資料共享

1. @ModelAttribute 標記方法(在 @RequestMapping 方法前執行)

@ModelAttribute("hello")
public String putHello() { return "world"; }

@RequestMapping("/say")
public void say(@ModelAttribute("hello") String hello, Writer w) throws IOException {
    w.write("Hello " + hello); // 輸出 Hello world
}
  • 返回值存入模型(預設)或Session(若類別標註 @SessionAttributes)。
  • 屬性名:@ModelAttribute("name") 指定,否則用返回類型類名首字母小寫。

2. @SessionAttributes 宣告 Session 存放屬性

@Controller
@RequestMapping("/myTest")
@SessionAttributes(value={"intValue","strValue"}, types={User.class})
public class MyController { ... }
  • value:屬性名列表;types:類型列表(屬性名為類名首字母小寫)。
  • 並集關係:符合名稱或類型者皆存入 Session。
  • 時機:處理器方法執行完成後,Spring 將模型中符合條件的屬性複製到 Session。首次請求 Session 仍為空,第二次請求才可取得。

3. @ModelAttribute 標記參數(從模型/Session 取值)

@RequestMapping("/use")
public void use(@ModelAttribute("user1") User u1, @ModelAttribute User user, HttpSession session) { ... }
  • 先找 Session,再找模型;找不到拋異常(除非 @ModelAttribute 未指定 name 且類型不匹配)。

六、自訂類型轉換器

1. 局部轉換器:@InitBinder + WebDataBinder

@Controller
public class MyController {
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyyMMdd"), true));
        // 自訂 PropertyEditor
        binder.registerCustomEditor(User.class, new PropertyEditorSupport() {
            @Override public void setAsText(String text) { setValue(new User(1, text)); }
            @Override public String getAsText() { return ((User)getValue()).getUsername(); }
        });
    }
    @RequestMapping("/date/{d}")
    public void handle(@PathVariable Date d, Writer w) throws IOException { w.write(d.toString()); }
}
  • 每個綁定註解參數(@RequestParam 等)會觸發一次 initBinder。
  • 僅在當前 Controller 生效。

2. 全域轉換器:實作 WebBindingInitializer

public class MyWebBindingInitializer implements WebBindingInitializer {
    @Override public void initBinder(WebDataBinder binder, WebRequest request) {
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyyMMdd"), true));
    }
}

XML 註冊:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="webBindingInitializer">
        <bean class="com.xxx.MyWebBindingInitializer"/>
    </property>
</bean>
  • 所有 Controller 共享,每次綁定皆執行。

七、總結與最佳實踐

  • 優先使用 @RestController(@Controller + @ResponseBody)開發 REST API。
  • 表單提交使用 @ModelAttribute 命令物件 + BindingResult 驗證,配合 JSR-303 註解(@Valid)。
  • Session 資料謹慎使用 @SessionAttributes,避免過大物件佔用記憶體;考慮 Redis 分散式 Session。
  • 類型轉換:Spring 3+ 建議使用 Formatter/ConversionService 替代 PropertyEditor,支援線程安全與泛型。
  • 參數綁定失敗預設拋 BindException,可用 @ControllerAdvice + @ExceptionHandler 統一處理。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved