Spring MVC 的流程控制三大支柱:
<bean id="defaultHandlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean name="/hello.html" class="com.example.HelloController"/>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/hello*.html" value-ref="helloController"/>
<entry key="/api/**" value-ref="apiController"/>
</map>
</property>
<property name="interceptors">
<list><ref bean="timeInterceptor"/></list>
</property>
</bean>
<bean id="helloController" class="com.example.HelloController"/>
public class TimeInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
long start = System.nanoTime();
req.setAttribute("startTime", start);
System.out.println("preHandle " + new Date());
return true; // false 終止後續流程
}
@Override
public void postHandle(HttpServletRequest req, HttpServletResponse res,
Object handler, ModelAndView mv) {
System.out.println("postHandle " + new Date());
}
@Override
public void afterCompletion(HttpServletRequest req, HttpServletResponse res,
Object handler, Exception ex) {
long start = (Long) req.getAttribute("startTime");
System.out.printf("afterCompletion %s 耗時 %d ms%n", new Date(), (System.nanoTime()-start)/1_000_000);
}
}
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list><ref bean="timeInterceptor"/></list>
</property>
<property name="urlMap"> ... </property>
</bean>
同一 Mapping 下的所有 Controller 共享攔截器鏈;不同 Mapping 可配置不同鏈。
| 繼承類別 | 適用場景 | 關鍵方法 |
|---|---|---|
AbstractController |
單一請求處理,最基礎 | `handleRequestInternal(req, res)` |
MultiActionController |
單類別聚合多個相關動作(CRUD) | 自訂方法 `insert(req,res)`、`delete(req,res)` + `MethodNameResolver` |
AbstractCommandController |
表單綁定,自動將請求參數填充 Command 物件 | `handle(req, res, command, errors)` + `setCommandClass(User.class)` |
SimpleFormController |
完整表單流程(顯示→驗證→提交→成功視圖) | `formBackingObject`、`onSubmit`、`referenceData` |
public class UserController extends MultiActionController {
public ModelAndView list(HttpServletRequest req, HttpServletResponse res) {
return new ModelAndView("userList", "users", userService.findAll());
}
public ModelAndView create(HttpServletRequest req, HttpServletResponse res) {
// 手動綁定或用 ServletRequestDataBinder
return new ModelAndView("redirect:/user/list.html");
}
}
<bean id="userController" class="com.example.UserController"/>
<bean id="multiMapping" class="org.springframework.web.servlet.mvc.multiaction.MultiActionController">
<property name="delegate" ref="userController"/>
<property name="methodNameResolver">
<bean class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<prop key="/user/list.html">list</prop>
<prop key="/user/create.html">create</prop>
</props>
</property>
</bean>
</property>
</bean>
public class LoginController extends AbstractCommandController {
public LoginController() { setCommandClass(LoginForm.class); }
@Override
protected ModelAndView handle(HttpServletRequest req, HttpServletResponse res,
Object cmd, BindException errors) {
LoginForm form = (LoginForm) cmd;
if (errors.hasErrors()) return new ModelAndView("loginForm");
if (authService.login(form.getUsername(), form.getPassword())) {
return new ModelAndView("redirect:/home.html");
}
errors.reject("invalid.credentials");
return new ModelAndView("loginForm");
}
}
框架自動:實例化 `LoginForm` → 依名稱綁定請求參數 → 驗證(若有 `Validator`)→ 傳入 `handle`。
Spring MVC 的流程控制核心是「映射解耦、攔截橫切、Controller 多態」。掌握 XML 時代的三大組件演進脈絡,能更深刻理解現代註解式實現的設計初衷。