1. Spring與Web環(huán)境集成
1.1 ApplicationContext應(yīng)用上下文獲取方式
應(yīng)用上下文對象是通過new ClasspathXmlApplicationContext(spring配置文件) 方式獲取的,但是每次從容器中獲得Bean時(shí)都要編寫new ClasspathXmlApplicationContext(spring配置文件) ,這樣的弊端是配置文件加載多次,應(yīng)用上下文對象創(chuàng)建多次。
在Web項(xiàng)目中,可以使用ServletContextListener監(jiān)聽Web應(yīng)用的啟動(dòng),我們可以在Web應(yīng)用啟動(dòng)時(shí),就加載Spring的配置文件,創(chuàng)建應(yīng)用上下文對象ApplicationContext,在將其存儲(chǔ)到最大的域servletContext域中,這樣就可以在任意位置從域中獲得應(yīng)用上下文ApplicationContext對象了。
1.1.1手動(dòng)實(shí)現(xiàn)ServletContextListener
項(xiàng)目路徑

- 新建一個(gè)package叫l(wèi)istener,新建ContexLoaderListener.class
public class ContexLoaderListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
@Override
public void contextInitialized(ServletContextEvent servletContextEvent){
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
//將Spring應(yīng)用上下文對象存儲(chǔ)到ServletContext域中
ServletContext servletContext = servletContextEvent.getServletContext();
servletContext.setAttribute("app",app);
System.out.println("spring容器創(chuàng)建完畢");
}
}
web.xml中加入一句
<listener>
<listener-class>cn.edu.ustc.listener.ContexLoaderListener</listener-class>
</listener>
修改UserServlet
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
// request.getServletContext();
ServletContext servletContext = this.getServletContext();
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
UserService userService = app.getBean(UserService.class);
userService.save();
}
運(yùn)行結(jié)果:
spring容器創(chuàng)建完畢
save...
優(yōu)化上面代碼
applicationContext.xml文件名寫死了,如果我就不想叫這個(gè)名字呢?我就想叫abc.xml,app這個(gè)名字我也不想每次都寫了,怎么辦呢?
web.xml加入
<!-- 全局初始化參數(shù)-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>applicationContext.xml</param-value>
</context-param>
listener包中新建WebApplicationContextUtils.java
public class WebApplicationContextUtils {
public static ApplicationContext getWebApplicationoContext(ServletContext servletContext){
return (ApplicationContext)servletContext.getAttribute("app");
}
}
回到ContexLoaderListener類
public void contextInitialized(ServletContextEvent servletContextEvent){
ServletContext servletContext = servletContextEvent.getServletContext();
//讀取web.xml中全局參數(shù)
String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
ApplicationContext app = new ClassPathXmlApplicationContext(contextConfigLocation);
//將Spring應(yīng)用上下文對象存儲(chǔ)到ServletContext域中
servletContext.setAttribute("app",app);
System.out.println("spring容器創(chuàng)建完畢");
}
UserServlet.java
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
//request.getServletContext(); 兩者都可以
ServletContext servletContext = this.getServletContext();
//ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
ApplicationContext app = WebApplicationContextUtils.getWebApplicationoContext(servletContext);
UserService userService = app.getBean(UserService.class);
userService.save();
}
1.2 Spring提供獲取應(yīng)用上下文的工具
上面的分析不用手動(dòng)實(shí)現(xiàn),Spring提供了一個(gè)監(jiān)聽器ContextLoaderListener就是對上述功能的封裝,該監(jiān)聽器內(nèi)部加載Spring配置文件,創(chuàng)建應(yīng)用上下文對象,并存儲(chǔ)到ServletContext域中,提供了一個(gè)客戶端工具WebApplicationContextUtils供使用者獲得應(yīng)用上下文對象。
所以我們需要做的只有兩件事:
①在web.xml中配置ContextLoaderListener監(jiān)聽器(導(dǎo)入spring-web坐標(biāo))
②使用WebApplicationContextUtils獲得應(yīng)用上下文對象ApplicationContext
1.3 導(dǎo)入Spring集成web的坐標(biāo)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
1.4 配置ContextLoaderListener監(jiān)聽器
<!--全局參數(shù)-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--Spring的監(jiān)聽器-->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
1.5 通過工具獲得應(yīng)用上下文對象
ApplicationContext applicationContext =
WebApplicationContextUtils.getWebApplicationContext(servletContext);
Object obj = applicationContext.getBean("id");
知識(shí)要點(diǎn)
Spring集成web環(huán)境步驟
? ①配置ContextLoaderListener監(jiān)聽器
? ②使用WebApplicationContextUtils獲得應(yīng)用上下文
2. SpringMVC的簡介
2.1 SpringMVC概述
SpringMVC 是一種基于 Java 的實(shí)現(xiàn) MVC 設(shè)計(jì)模型的請求驅(qū)動(dòng)類型的輕量級(jí) Web 框架,屬于SpringFrameWork 的后續(xù)產(chǎn)品,已經(jīng)融合在 Spring Web Flow 中。
SpringMVC 已經(jīng)成為目前最主流的MVC框架之一,并且隨著Spring3.0 的發(fā)布,全面超越 Struts2,成為最優(yōu)秀的 MVC 框架。它通過一套注解,讓一個(gè)簡單的 Java 類成為處理請求的控制器,而無須實(shí)現(xiàn)任何接口。同時(shí)它還支持 RESTful 編程風(fēng)格的請求。
2.2 SpringMVC快速入門
需求:客戶端發(fā)起請求,服務(wù)器端接收請求,執(zhí)行邏輯并進(jìn)行視圖跳轉(zhuǎn)。
開發(fā)步驟

①導(dǎo)入SpringMVC相關(guān)坐標(biāo)
②配置SpringMVC核心控制器DispathcerServlet
③創(chuàng)建Controller類和視圖頁面
④使用注解配置Controller類中業(yè)務(wù)方法的映射地址
⑤配置SpringMVC核心文件 spring-mvc.xml
⑥客戶端發(fā)起請求測試
代碼實(shí)現(xiàn)
①導(dǎo)入Spring和SpringMVC的坐標(biāo)、導(dǎo)入Servlet和Jsp的坐標(biāo)
<!--Spring坐標(biāo)-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--SpringMVC坐標(biāo)-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--Servlet坐標(biāo)-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!--Jsp坐標(biāo)-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
②在web.xml配置SpringMVC的核心控制器
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
③創(chuàng)建Controller和業(yè)務(wù)方法
public class UserController {
public String save(){
System.out.println("Controllere save running");
return "success.jsp";
}
}
③創(chuàng)建視圖頁面index.jsp
<html>
<body>
<h1>
Success
</h1>
</body>
</html>
④配置注解
@Controller
public class QuickController {
@RequestMapping("/quick")
public String quickMethod(){
System.out.println("Controllere save running");
return "success.jsp";
}
}
⑤創(chuàng)建spring-mvc.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--配置注解掃描-->
<context:component-scan base-package="cn.edu.ustc"/>
</beans>
⑥訪問測試地址
http://localhost:8080/spring_mvc_war_exploded/quick
控制臺(tái)打印
save
Controllere save running
頁面顯示

2.3 SpringMVC流程圖示


2.4 知識(shí)要點(diǎn)
SpringMVC的開發(fā)步驟
①導(dǎo)入SpringMVC相關(guān)坐標(biāo)
②配置SpringMVC核心控制器DispathcerServlet
③創(chuàng)建Controller類和視圖頁面
④使用注解配置Controller類中業(yè)務(wù)方法的映射地址
⑤配置SpringMVC核心文件 spring-mvc.xml
⑥客戶端發(fā)起請求測試
3. SpringMVC的組件解析
3.1 SpringMVC的執(zhí)行流程

①用戶發(fā)送請求至前端控制器DispatcherServlet。
②DispatcherServlet收到請求調(diào)用HandlerMapping處理器映射器。
③處理器映射器找到具體的處理器(可以根據(jù)xml配置、注解進(jìn)行查找),生成處理器對象及處理器攔截器(如果有則生成)一并返回給DispatcherServlet。
④DispatcherServlet調(diào)用HandlerAdapter處理器適配器。
⑤HandlerAdapter經(jīng)過適配調(diào)用具體的處理器(Controller,也叫后端控制器)。
⑥Controller執(zhí)行完成返回ModelAndView。
⑦HandlerAdapter將controller執(zhí)行結(jié)果ModelAndView返回給DispatcherServlet。
⑧DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器。
⑨ViewReslover解析后返回具體View。
⑩DispatcherServlet根據(jù)View進(jìn)行渲染視圖(即將模型數(shù)據(jù)填充至視圖中)。DispatcherServlet響應(yīng)用戶。
3.2 SpringMVC組件解析
- 前端控制器:DispatcherServlet
? 用戶請求到達(dá)前端控制器,它就相當(dāng)于 MVC 模式中的 C,DispatcherServlet 是整個(gè)流程控制的中心,由
它調(diào)用其它組件處理用戶的請求,DispatcherServlet 的存在降低了組件之間的耦合性。
- 處理器映射器:HandlerMapping
? HandlerMapping 負(fù)責(zé)根據(jù)用戶請求找到 Handler 即處理器,SpringMVC 提供了不同的映射器實(shí)現(xiàn)不同的映射方式,例如:配置文件方式,實(shí)現(xiàn)接口方式,注解方式等。
- 處理器適配器:HandlerAdapter
? 通過 HandlerAdapter 對處理器進(jìn)行執(zhí)行,這是適配器模式的應(yīng)用,通過擴(kuò)展適配器可以對更多類型的處理器進(jìn)行執(zhí)行。
- 處理器:Handler
? 它就是我們開發(fā)中要編寫的具體業(yè)務(wù)控制器。由 DispatcherServlet 把用戶請求轉(zhuǎn)發(fā)到 Handler。由Handler 對具體的用戶請求進(jìn)行處理。
- 視圖解析器:View Resolver
? View Resolver 負(fù)責(zé)將處理結(jié)果生成 View 視圖,View Resolver 首先根據(jù)邏輯視圖名解析成物理視圖名,即具體的頁面地址,再生成 View 視圖對象,最后對 View 進(jìn)行渲染將處理結(jié)果通過頁面展示給用戶。
- 視圖:View
? SpringMVC 框架提供了很多的 View 視圖類型的支持,包括:jstlView、freemarkerView、pdfView等。最常用的視圖就是 jsp。一般情況下需要通過頁面標(biāo)簽或頁面模版技術(shù)將模型數(shù)據(jù)通過頁面展示給用戶,需要由程序員根據(jù)業(yè)務(wù)需求開發(fā)具體的頁面
3.3 SpringMVC注解解析
@RequestMapping
作用:用于建立請求 URL 和處理請求方法之間的對應(yīng)關(guān)系
位置:
? 類上,請求URL 的第一級(jí)訪問目錄。此處不寫的話,就相當(dāng)于應(yīng)用的根目錄
? 方法上,請求 URL 的第二級(jí)訪問目錄,與類上的使用@ReqquestMapping標(biāo)注的一級(jí)目錄一起組成訪問虛擬路徑
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/quick")
public String save(){
System.out.println("Controllere save running");
return "/success.jsp";//前面加一個(gè)斜杠"/"表示當(dāng)前資源路徑下的文件,否則就是/user/quick/下的文件了
}
}
輸入:http://localhost:8080/user/quick
結(jié)果:顯示success頁面。
屬性:
? value:用于指定請求的URL。它和path屬性的作用是一樣的
? method:用于指定請求的方式
@RequestMapping(value = "/quick",method = RequestMethod.GET)
? params:用于指定限制請求參數(shù)的條件。它支持簡單的表達(dá)式。要求請求參數(shù)的key和value必須和配置的一模一樣
例如:
? params = {"accountName"},表示請求參數(shù)必須有accountName
? params = {"moeny!100"},表示請求參數(shù)中money不能是100
1.mvc命名空間引入
命名空間:xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
約束地址:http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
組件掃描
SpringMVC基于Spring容器,所以在進(jìn)行SpringMVC操作時(shí),需要將Controller存儲(chǔ)到Spring容器中,如果使用@Controller注解標(biāo)注的話,就需要使用<context:component-scan base-package=“cn.edu.ustc.controller"/>進(jìn)行組件掃描。
3.4 SpringMVC的XML配置解析
SpringMVC有默認(rèn)組件配置,默認(rèn)組件都是DispatcherServlet.properties配置文件中配置的,該配置文件地址org/springframework/web/servlet/DispatcherServlet.properties,該文件中配置了默認(rèn)的視圖解析器,

如下:
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
翻看該解析器源碼,可以看到該解析器的默認(rèn)設(shè)置,如下:
public class InternalResourceViewResolver extends UrlBasedViewResolver{
...
/**
* A convenience constructor that allows for specifying {@link #setPrefix prefix}
* and {@link #setSuffix suffix} as constructor arguments.
* @param prefix the prefix that gets prepended to view names when building a URL
* @param suffix the suffix that gets appended to view names when building a URL
* @since 4.3
*/
public InternalResourceViewResolver(String prefix, String suffix) {
this();
setPrefix(prefix);
setSuffix(suffix);
}
...
}
該類繼承了一個(gè)叫UrlBasedViewResolver的類
這個(gè)類中有一些默認(rèn)的設(shè)置
public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered {
public static final String REDIRECT_URL_PREFIX = "redirect:";
public static final String FORWARD_URL_PREFIX = "forward:";
private String prefix = "";
private String suffix = "";
}
REDIRECT_URL_PREFIX = "redirect:" --重定向前綴
FORWARD_URL_PREFIX = "forward:" --轉(zhuǎn)發(fā)前綴(默認(rèn)值)
prefix = ""; --視圖名稱前綴
suffix = ""; --視圖名稱后綴
回到userController.java,return語句其實(shí)省略了前綴forward
實(shí)際上應(yīng)該是
return "forward:/success.jsp";
瀏覽器地址欄輸入http://localhost:8080/user/quick,頁面顯示Success,注意這時(shí)候的地址沒有變化
如果是
return "redirect:/success.jsp";
瀏覽器跳轉(zhuǎn)到地址http://localhost:8080/success.jsp
- 視圖解析器
我們可以通過屬性注入的方式修改視圖的的前后綴
webapp目錄下新建一個(gè)jsp文件夾,將success.jsp放進(jìn)去
<!--Controller的組件掃描-->
<context:component-scan base-package="cn.edu.ustc.controller"/>
<!--配置內(nèi)部資源視圖解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--/jsp/success.jsp-->
<property name="prefix" value="/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
3.5 知識(shí)要點(diǎn)
SpringMVC的相關(guān)組件
前端控制器:DispatcherServlet
處理器映射器:HandlerMapping
處理器適配器:HandlerAdapter
處理器:Handler
視圖解析器:View Resolver
視圖:View
SpringMVC的注解和配置
請求映射注解:@RequestMapping
視圖解析器配置:
REDIRECT_URL_PREFIX = "redirect:"
FORWARD_URL_PREFIX = "forward:"
prefix = "";
suffix = "";