Spring MVC 應用的啟動入口是 web.xml,正確配置它能確保 DispatcherServlet 與 Spring 容器順利協作。本文將從監聽器、Servlet 映射、多配置文件加載、視圖解析等關鍵點進行深度解析。
若需加載多個 Spring 配置文件(如分離 Controller、Service、DAO 層),必須先註冊 ContextLoaderListener,再透過 context-param 指定 contextConfigLocation,多個路徑以逗號分隔:
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml,/WEB-INF/controllers.xml,/WEB-INF/service.xml</param-value> </context-param>
若未指定 init-param,DispatcherServlet 會預設尋找 [servlet-name]-servlet.xml(如 dispatch-servlet.xml)。
servlet-mapping 決定由 DispatcherServlet 接管的 URL 模式。常見寫法有:
*.do — 傳統 Struts 風格,僅攔截 .do 結尾請求/ — REST 風格,攔截所有請求(含靜態資源,需額外配置 default-servlet-handler)*.* — 不推薦,會導致靜態資源同被攔截<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
該文件專注於 Web 層組件:控制器掃描、視圖解析器、註解驅動等。
<beans ...>
<!-- 啟用註解掃描,base-package 指向 Controller 包 -->
<context:component-scan base-package="controller" />
<!-- 註解方法處理器適配器 (Spring 3.0+ 建議改用 mvc:annotation-driven) -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<!-- 視圖解析器:前綴 /jsp/,後綴 .jsp -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/jsp/" p:suffix=".jsp" />
</beans>
控制器返回 blog/index 經解析後將定向至 /jsp/blog/index.jsp。
@Controller
public class TestController {
@RequestMapping("test/login.do")
public String testLogin(@RequestParam("username") String username,
String password, HttpServletRequest request) {
if (!"admin".equals(username) || !"admin".equals(password)) {
return "loginError"; // 對應 /jsp/loginError.jsp
}
return "loginSuccess";
}
@RequestMapping("/test/login2.do")
public ModelAndView testLogin2(String username, String password, int age) {
if (!"admin".equals(username) || !"admin".equals(password) || age < 5) {
return new ModelAndView("loginError");
}
// 重定向寫法
return new ModelAndView("redirect:../index.jsp");
}
@RequestMapping("/test/login3.do")
public ModelAndView testLogin3(User user) { // 自動綁定表單對象
// ...
}
@Resource(name = "loginService")
private LoginService loginService;
@RequestMapping("/test/login4.do")
public String testLogin4(User user) {
return loginService.login(user) ? "loginSuccess" : "loginError";
}
}
@Controller
@RequestMapping("/test2/login.do") // 父路徑
public class TestController2 {
@RequestMapping // 空路徑 -> /test2/login.do
public String testLogin(String username, String password, int age) { ... }
@RequestMapping(params = "method=1", method = RequestMethod.POST)
public String testLogin2(String username, String password) { ... }
@RequestMapping(params = "method=2")
public String testLogin3(String username, String password, int age) { ... }
}
@Controller
@RequestMapping("/test3/*")
public class TestController3 {
@RequestMapping("login.do") // 實際匹配 /test3/login.do
public String testLogin(String username, String password, int age) { ... }
}
// 從 URL 路徑提取參數
@RequestMapping(value = "/comment/{blogId}", method = RequestMethod.POST)
public void comment(Comment comment, @PathVariable int blogId,
HttpSession session, HttpServletResponse response) throws IOException {
// blogId 從 /comment/1.do 獲取值 1
}
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
合理拆分配置文件、選擇適當的 URL 映射模式、善用註解驅動開發,是構建清晰可維護 Spring MVC 應用的關鍵。實際專案中建議採用 / 映射並配置靜態資源處理,同時開啟 <mvc:annotation-driven> 替代舊式 Adapter。