SpringMVC 作為 Java Web 開發事實標準,其核心價值在於 請求分發、參數綁定、視圖解析、異常處理、攔截器鏈 五大核心流程的標準化與可擴展。本文結合架構圖解,系統總結 註解開發、參數綁定、數據校驗、數據回顯、異常處理、文件上傳、JSON 交互、RESTful 支持、攔截器應用 九大實戰模塊,構建完整知識圖譜。
用戶請求 HTTP Request
↓
DispatcherServlet (前端控制器,統一入口)
↓
HandlerMapping (處理器映射器) → 根據 URL 查找 Handler (Controller 方法)
↓
HandlerAdapter (處理器適配器) → 適配調用 Handler (參數綁定、返回值處理)
↓
Handler (Controller 方法) → 業務邏輯,返回 ModelAndView / String / void / @ResponseBody
↓
ViewResolver (視圖解析器) → 邏輯視圖名 → 物理視圖 (JSP/Thymeleaf/FreeMarker)
↓
View (視圖渲染) → 輸出 HTML/JSON/XML
↓
HTTP Response
load-on-startup=1 啟動時初始化。RequestMappingHandlerMapping (註解模式) 維護 URL→HandlerMethod 映射表。RequestMappingHandlerAdapter 負責參數解析、類型轉換、數據校驗、返回值處理。InternalResourceViewResolver (JSP)、ThymeleafViewResolver 等。
<!-- 替代傳統 HandlerMapping/Adapter 配置 -->
<mvc:annotation-driven
conversion-service="conversionService"
validator="validator">
</mvc:annotation-driven>
<!-- 掃描 Controller -->
<context:component-scan base-package="com.example.controller" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
| 註解 | 作用 | 關鍵屬性 |
|---|---|---|
@Controller | 標識控制器 Bean,交給組件掃描註冊 | - |
@RequestMapping | URL 映射,可作用於類/方法 | value/path, method, params, headers, consumes, produces |
@ResponseBody | 返回值直接寫入 HTTP Body (JSON/XML) | - |
@RestController | @Controller + @ResponseBody 組合 (JDK 4.0+) | - |
HttpServletRequest, HttpServletResponse, HttpSession, Principal, Locale, InputStream, OutputStreamModel, ModelMap, ModelAndView (向請求域放數據)user.address.city)List<Item> items, String[] ids (同名參數多值)QueryVo { User user; List<Integer> ids; } 綁定複雜查詢條件
public void save(@RequestParam("user_name") String username,
@RequestParam(value="age", required=false, defaultValue="18") Integer age) {}
// 1. 實現 Converter
public class StringToDateConverter implements Converter {
public Date convert(String source) {
try { return new SimpleDateFormat("yyyy-MM-dd").parse(source); }
catch (ParseException e) { throw new IllegalArgumentException(e); }
}
}
// 2. 注入 ConversionService
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set><bean class="com.example.converter.StringToDateConverter"/></set>
</property>
</bean>
<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>5.2.4.Final</version></dependency>
<dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><version>1.1.0.Final</version></dependency>
public class User {
@NotBlank(message="用戶名不能為空")
@Size(min=3, max=20, message="用戶名長度 3-20")
private String username;
@Email(message="郵箱格式錯誤")
private String email;
}
@PostMapping("/user")
public String save(@Validated User user, BindingResult result, Model model) {
if (result.hasErrors()) {
// 回顯錯誤信息
return "userForm";
}
userService.save(user);
return "redirect:/users";
}
public interface Insert {} public interface Update {}
@NotNull(groups=Update.class) private Long id; // 更新時必須有 id
@Validated(Insert.class) // 指定分組
user)。@ModelAttribute("userVo") User user → 請求域 Key = "userVo"。model.addAttribute("user", user),最靈活、推薦。
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ServiceException.class) // 業務異常
public ModelAndView handleServiceEx(ServiceException e) {
return new ModelAndView("error", "message", e.getMessage());
}
@ExceptionHandler(Exception.class) // 系統異常
public ModelAndView handleSysEx(Exception e) {
log.error("系統異常", e);
return new ModelAndView("error", "message", "系統繁忙,請稍後重試");
}
@ExceptionHandler(Exception.class)
@ResponseBody // AJAX 請求返回 JSON
public Result handleAjaxEx(Exception e, HttpServletRequest request) {
if (isAjax(request)) return Result.error("系統異常");
return null; // 非 AJAX 走視圖解析
}
}
原則:DAO/Service 拋業務異常,Controller 拋參數/流程異常,最終由全局處理器統一響應。
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760"/> <!-- 10MB -->
<property name="defaultEncoding" value="UTF-8"/>
</bean>
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) throws IOException {
if (!file.isEmpty()) {
String path = "/upload/" + UUID.randomUUID() + "_" + file.getOriginalFilename();
file.transferTo(new File(path));
}
return "success";
}
前端 <form enctype="multipart/form-data">。
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.8</version></dependency>
@PostMapping(value="/user", consumes="application/json", produces="application/json")
@ResponseBody
public User create(@RequestBody User user) { // 請求體 JSON → User
return userService.save(user); // User → 響應體 JSON
}
<mvc:annotation-driven> 自動註冊 MappingJackson2HttpMessageConverter。
@GetMapping("/users/{id}")
public User get(@PathVariable Long id) { return userService.get(id); }
@PutMapping("/users/{id}")
public User update(@PathVariable Long id, @RequestBody User user) { ... }
@DeleteMapping("/users/{id}")
public void delete(@PathVariable Long id) { ... }
瀏覽器表單不支持 PUT/DELETE,需配置 HiddenHttpMethodFilter 將 _method=PUT 參數轉為 HTTP Method。
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
靜態資源訪問:<mvc:resources mapping="/static/**" location="/static/"/>。
@RequirePermission 精細控制。SpringMVC 知識體系橫跨 架構原理、註解驅動、參數綁定、校驗、異常、文件、JSON、REST、攔截 九大維度。建議按「架構圖 → 核心配置 → 實戰模塊 → 源碼追蹤」路徑學習:先跑通 mvc:annotation-driven 全家桶,再逐個模塌替換默認實現 (如自定義 HandlerMethodArgumentResolver、HandlerExceptionResolver),最終閱讀 DispatcherServlet.doDispatch() 源碼,將知識點串成線,形成自己的「SpringMVC 內核模型」。