【1】注冊SpringMVC的前端控制器DispatcherServlet
① 預設配置方式
此配置作用下,SpringMVC的配置檔案預設位于
WEB-INF
下,預設名稱為
<servlet-name>-servlet.xml
,例如,以下配置所對應
SpringMVC
的配置檔案位于
WEB-INF
下,檔案名為
springMVCservlet.xml
<!-- 配置SpringMVC的前端控制器,對浏覽器發送的請求統一進行處理 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servletclass>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
設定
springMVC
的核心控制器所能處理的請求的請求路徑。
/
所比對的請求可以是
/login
或
.html
或
.js
或
.css
方式的請求路徑,但是
/
不能比對
.jsp
請求路徑的請求。
② 擴充配置方式
可通過
init-param
标簽設定SpringMVC配置檔案的位置和名稱,通過
load-on-startup
标簽設定
SpringMVC前端控制器DispatcherServlet的初始化時間
<!-- 配置SpringMVC的前端控制器,對浏覽器發送的請求統一進行處理 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servletclass>
<!-- 通過初始化參數指定SpringMVC配置檔案的位置和名稱 -->
<init-param>
<!-- contextConfigLocation為固定值 -->
<param-name>contextConfigLocation</param-name>
<!-- 使用classpath:表示從類路徑查找配置檔案,例如maven工程中的src/main/resources -->
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<url-pattern>
标簽中使用
/
和
/*
的差別
/
所比對的請求可以是
/login或.html或.js或.css方式
的請求路徑,但是
/
不能比對
.jsp
請求路徑的請
求.是以就可以避免在通路jsp頁面時,該請求被DispatcherServlet處理,進而找不到相應的頁面
/*
則能夠比對所有請求。例如在使用過濾器時,若需要對所有請求進行過濾,就需要使用
/*
的寫法。
【2】與Thymeleaf整合
建立springMVC的配置檔案
<!-- 自動掃描包 -->
<context:component-scan base-package="com.mvc.controller"/>
<!-- 配置Thymeleaf視圖解析器 -->
<bean id="viewResolver"
class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean
class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 視圖字首 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 視圖字尾 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
<!--
處理靜态資源,例如html、js、css、jpg若隻設定該标簽,則隻能通路靜态資源,其他請求則無法通路
此時必須設定<mvc:annotation-driven/>解決問題
-->
<mvc:default-servlet-handler/>
<!-- 開啟mvc注解驅動 -->
<mvc:annotation-driven>
<mvc:message-converters>
<!-- 處理響應中文内容亂碼 -->
<bean
class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="defaultCharset" value="UTF-8" />
<property name="supportedMediaTypes">
<list>
<value>text/html</value>
<value>application/json</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
浏覽器發送請求,若請求位址符合前端控制器的
url-pattern
,該請求就會被前端控制器
DispatcherServlet
處理。前端控制器會讀取SpringMVC的核心配置檔案,通過掃描元件找到控制器,将請求位址和控制器中
@RequestMapping
注解的
value
屬性值進行比對,若比對成功,該注解所辨別的控制器方法就是處理請求的方法。處理請求的方法需要傳回一個字元串類型的視圖名稱,該視圖名稱會被視圖解析器解析,加上字首和字尾組成視圖的路徑,通過Thymeleaf對視圖進行渲染,最終轉發到視圖所對應頁面。
【3】CharacterEncodingFilter
Servlet Filter 允許為請求指定一個字元編碼。這很有用,因為目前浏覽器通常不設定字元編碼,即使在HTML頁面或表單中指定了字元編碼。
如果請求尚未指定編碼,則此Filter可以應用其編碼,或者在任何情況下強制執行此Filter的編碼(
“forceEncoding”=“true”
)。在後一種情況下,編碼也将作為預設響應編碼應用(盡管這通常會被視圖中設定的完整内容類型覆寫)。
<filter>
<filter-name>CharacterEncodingFilter</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>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
解決GET請求亂碼的一種方式是可以修改
Tomcat的server.xml在Connector
标簽裡面配置
URIEncoding="UTF-8"
,但是隻是針對目前Tomcat哦。
原生Servlet中解決POST亂碼的一種方式是
request.setCharacterEncoding("UTF-8");
但是在SpringMVC中不好用。因為DispatchServlet在目标方法前從request中擷取了參數,故而在目标方法裡面再使用
request.setCharacterEncoding("UTF-8");
不生效。
同時注冊CharacterEncodingFilter與HiddenHttpMethodFilter次序
在web.xml中注冊時,必須先注冊
CharacterEncodingFilter
,再注冊
HiddenHttpMethodFilter
。原因如下:
- 在
中通過CharacterEncodingFilter
request.setCharacterEncoding(encoding)
方法設定字
符集的。
-
方法要求前面不能有任何擷取請求參數的操作request.setCharacterEncoding(encoding)
- 而 HiddenHttpMethodFilter 恰恰有一個擷取請求方式的操作:
String paramValue = request.getParameter(this.methodParam);
【4】域對象共享資料
① 使用ServletAPI向request域對象共享資料
@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request){
request.setAttribute("testScope", "hello,servletAPI");
return "success";
}
② 使用ModelAndView向request域對象共享資料
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
/**
* ModelAndView有Model和View的功能
* Model主要用于向請求域共享資料
* View主要用于設定視圖,實作頁面跳轉
*/
ModelAndView mav = new ModelAndView();
//向請求域共享資料
mav.addObject("testScope", "hello,ModelAndView");
//設定視圖,實作頁面跳轉
mav.setViewName("success");
return mav;
}
③ 使用Model向request域對象共享資料
@RequestMapping("/testModel")
public String testModel(Model model){
model.addAttribute("testScope", "hello,Model");
return "success";
}
④ 使用map向request域對象共享資料
@RequestMapping("/testMap")
public String testMap(Map<String, Object> map){
map.put("testScope", "hello,Map");
return "success";
}
⑤ 使用ModelMap向request域對象共享資料
@RequestMapping("/testModelMap")
public String testModelMap(ModelMap modelMap){
modelMap.addAttribute("testScope", "hello,ModelMap");
return "success";
}
⑥ Model、ModelMap、Map的關系
Model、ModelMap、Map類型的參數其實本質上都是 BindingAwareModelMap 類型的的執行個體。
public interface Model{}
public class ModelMap extends LinkedHashMap<String, Object> {}
public class ExtendedModelMap extends ModelMap implements Model {}
public class BindingAwareModelMap extends ExtendedModelMap {}
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SO3QzM2YzMyMDOhFDMjBTYyYzX2IDOyMjM4AzLcZDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
⑦ 向session域共享資料
@RequestMapping("/testSession")
public String testSession(HttpSession session){
session.setAttribute("testSessionScope", "hello,session");
return "success";
}
⑧ 向application域共享資料
@RequestMapping("/testApplication")
public String testApplication(HttpSession session){
ServletContext application = session.getServletContext();
application.setAttribute("testApplicationScope", "hello,application");
return "success";
}
【5】SpringMVC的視圖
SpringMVC中的視圖是View接口,視圖的作用渲染資料,将模型Model中的資料展示給使用者。SpringMVC視圖的種類很多,預設有轉發視圖和重定向視圖。
① 轉發視圖
當控制器方法中所設定的視圖名稱
沒有任何字首
時,此時的視圖名稱會被SpringMVC配置檔案中所配置
的視圖解析器解析,
視圖名稱拼接視圖字首和視圖字尾所得到的最終路徑
,會通過轉發的方式實作跳轉。
@RequestMapping("/")
public String index(){
return "index";
}
若使用的視圖技術為Thymeleaf,在SpringMVC的配置檔案中配置了Thymeleaf的視圖解析器,由此視圖解析器解析之後所得到的是
ThymeleafView
。
SpringMVC中預設的轉發視圖是
InternalResourceView
。當控制器方法中所設定的視圖名稱以
"forward:"
為字首時,建立
InternalResourceView
視圖,此時的視圖名稱不會被SpringMVC配置檔案中所配置的視圖解析器解析,而是會将字首
"forward:"
去掉,剩餘部分作為最終路徑通過轉發的方式實作跳轉。當工程引入jstl的依賴,轉發視圖會自動轉換為
JstlView
。
② 重定向視圖
SpringMVC中預設的重定向視圖是RedirectView。當控制器方法中所設定的視圖名稱以
"redirect:"
為字首時,建立RedirectView視圖,此時的視圖名稱不會被SpringMVC配置檔案中所配置的視圖解析器解析,而是會将字首
"redirect:"
去掉,剩餘部分作為最終路徑通過重定向的方式實作跳轉。
@RequestMapping("/testRedirect")
public String testRedirect(){
return "redirect:/testParam";
}
③ 視圖控制器view-controller
<!--
path:設定處理的請求位址
view-name:設定請求位址所對應的視圖名稱
-->
<mvc:view-controller path="/testView" view-name="success"></mvc:view-controller>