SpringMVC框架是基於Spring框架,可以讓我們更為方便的進行Web的開發,實現前後端分離 思路和原理 我們之前仿照SpringMVC定義了一個自定義MVC框架,兩者的思路其實都是一樣的。 建議結合兩篇文章進行學習 "JSP學習筆記(6)—— 自定義MVC框架" 首先,提供一個前置攔截器(D ...
SpringMVC框架是基於Spring框架,可以讓我們更為方便的進行Web的開發,實現前後端分離
思路和原理
我們之前仿照SpringMVC定義了一個自定義MVC框架,兩者的思路其實都是一樣的。
建議結合兩篇文章進行學習
首先,提供一個前置攔截器(DispatchServlet),攔截url請求,之後,根據url請求,跳轉到Controller層,執行操作,之後再返回數據
入門
我的demo是使用了maven框架
1.創建maven項目
按照下圖進行配置
2.添加依賴
修改pom.xml,添加依賴
剛開始的時候,使用的是最新版本(5.x.x),然後發現有個奇怪的錯誤,折騰了許久找不到方法,於是便用了4.x.x版本的,果然沒有出現問題了,果然是新版本都不好用。。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--日誌-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.9.release</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.9.release</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.9.release</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.9.release</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.9.release</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.9.release</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.9.release</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.9.release</version>
</dependency>
<!--AOP-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.9.release</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>RELEASE</version>
</dependency>
<!-- springmvc依賴的json庫(如果使用@responsebody註解返回json數據) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- jstl 1.2.5 version libarary -->
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-spec</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-impl</artifactId>
<version>1.2.5</version>
</dependency>
<!-- oracle driver -->
<dependency>
<groupId>com.github.noraui</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
</dependency>
<!-- mybatis orm框架 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- spring整合mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<!-- 文件上傳與下載 -->
<!--
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
-->
3.項目結構優化
由於是根據maven模板新建的項目,所以項目結構還需要添加一些文件夾
在main文件夾下新建java文件夾
把java文件夾設置為source directory
在java文件夾下新建自己的包名,然後新建一個controller文件夾和model文件夾,順便也新建一個resources的文件夾,和上面同樣的步驟,設置為resources directory
除此之外,還需要在webapp文件夾下新建一個views文件夾
4.設置Tomcat配置
我這裡是設置好了,沒有設置的話,是沒有下拉菜單的,但是有個add configuration的選項
選擇tomcat的設置,選擇local,如果沒有Tomcat的選項,可以點擊選項最下麵的show more
點擊之後,添加構造物
選擇那個exploded的選項
設置url
之後開始運行Web程式,就可以通過訪問http://localhost:8080/springmvcdemo
來訪問Web項目的首頁
5.新建springmvc配置文件
springmvc配置文件和之前的spring文件一樣,都是進行相關的bean的配置,這裡由於是資源文件,所以按照規則我們放入resources文件夾中
springmvc-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/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">
<!-- 對web包中的所有類進行掃描,以完成Bean創建和自動依賴註入的功能-->
<!-- 把標記了controller和requestmapping註解的類和方法進行保存,之後通過反射調用 -->
<context:component-scan base-package="com.wan.controller"/>
<!--支持spring3.0+ 新的mvc註解,不加有些註解功能不行,如json轉換的@ResponseBody
<context:annotation-config/>
將隱式地向 Spring 容器註冊
1. AutowiredAnnotationBeanPostProcessor 解決數據或組件自動裝配
2. CommonAnnotationBeanPostProcessor 解決相容JSR250規範的註解:@Resource,@PostConstruct,...
3. PersistenceAnnotationBeanPostProcessor 解決持久化註解處理
4. RequiredAnnotationBeanPostProcessor
這 4 個 BeanPostProcessor。
enable-matrix-variables="true": 開啟矩陣變數獲取數據的特性
-->
<mvc:annotation-driven enable-matrix-variables="true">
<mvc:async-support default-timeout="10"/><!--子元素可指定非同步攔截器-->
</mvc:annotation-driven>
<!-- 配置*.js,*.css,*.jpg,*.html等的請不由DispatcherServlet處理,而直接交tomcat服務的預設Servlet來處理,
不同的伺服器其預設Servlet的名字是不同,但tomcat預設Servlet的名字叫“default”
-->
<mvc:default-servlet-handler/>
<!--對模型視圖名稱的解析,即在模型視圖名稱添加前尾碼
UserController.login(){
return "success"; //spring mvc 解析為一個對應的jsp(視圖)/views/success.jsp
}
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/views/" p:suffix=".jsp">
<!-- /views/[login].jsp -->
<!-- 與p:prefix, p:suffix 等價
<property name="prefix" value="/views/" />
<property name="suffix" value=".jsp" />
-->
<!-- 如果使用jstl的話,配置下麵的屬性 -->
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
</bean>
</beans>
配置中有個bean類,是配置視圖解析器(也就是最後的那個bean標簽),我們使用的是InternalResourceViewResolver
此解析器會把請求處理類(controller類)處理方法的返回值按照“首碼+方法返回值+尾碼”的格式進行加工,並把加工後的返回值作為路徑進行跳轉
除此之外,還有其他的解析器,下麵會進行補充說明
6.配置web.xml文件
由於我們使用的maven的模板創建的web項目,web.xml裡面的內容並不是我們所需要的,所以還得進行內容的更改
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>SpringMVC Demo</display-name>
<!-- springmvc 核心控制器,將springMVC整合到項目里-->
<servlet>
<servlet-name>springmvc-DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 配置spring mvc的組件:掃描controller, view resovle -->
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
<!-- 伺服器啟動時載入順序 -->
<load-on-startup>1</load-on-startup>
<!-- 非同步請求處理支持 -->
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>springmvc-DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
7.測試
我們用一個簡單的例子去瞭解springmvc的使用方式
我們編寫一個controller類,用來模擬實現登錄操作,登錄成功,跳轉到登錄成功的頁面success.jsp
UserController.java
package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author StarsOne
* @date Create in 2019/9/28 0028 14:27
* @description
*/
@Controller
public class UserController {
@RequestMapping("/user/login")
public String login() {
//這裡的返回,之後會加上首碼和尾碼
//相當於頁面跳轉到 views/success.jsp 頁面
return "success";
}
}
success.jsp
中,只有一個簡單的“登錄成功”文字
index.jsp中,有個鏈接,請求url為user/login
<a href="user/login">登錄</a>
之後就是可以跳轉到了頁面
PS:上面方法返回了一個success,,會被自動加入首碼和尾碼,註意,這裡是進行的請求轉發
除此之外,我們還可以加上forward
或redirect
首碼來進行請求轉發或重定向
但是,如果使用這兩種首碼,之後視圖解析器就不會自動添加首碼和尾碼了。所以,我們得指定具體跳轉的url地址。
@RequestMapping("/user/login")
public String login() {
//請求轉發
return "forward:/views/success.jsp";
}
@RequestMapping("/user/login")
public String login() {
//重定向
return "redirect:/views/success.jsp";
}
RequestMapping註解
高級使用
springmvc框架中的RequestMapping註解不像我們之前自定義MVC框架的註解那樣簡單,它的還可以標註一個類
例如:
package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author StarsOne
* @date Create in 2019/9/28 0028 14:27
* @description
*/
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/login")
public String login() {
//這裡的返回,相當於頁面跳轉到 views/success.jsp 頁面
return "success";
}
}
我們鏈接上的url請求就是/user/login
,而不能使用login
屬性說明及使用
屬性 | 說明 |
---|---|
value | 指定請求的實際url地址,是預設屬性,如@RequestMapping("/login") 相當於@RequestMapping(value="/login" |
method | 指定請求的方法,post或get |
params | 規定請求中的參數必須滿足一定的條件 |
header | 規定請求中的請求頭(header)必須滿足一定的條件 |
1.method
package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author StarsOne
* @date Create in 2019/9/28 0028 14:27
* @description
*/
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/login",method="RequestMethod.POST")
public String login() {
//這裡的返回,相當於頁面跳轉到 views/success.jsp 頁面
return "success";
}
}
之後如果請求不是post方式,就會出現405錯誤
2.params
使用此屬性可以對請求的參數進行約束
例子:
package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author StarsOne
* @date Create in 2019/9/28 0028 14:27
* @description
*/
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/login",params={"name","age!=23"})
public String login() {
//這裡的返回,相當於頁面跳轉到 views/success.jsp 頁面
return "success";
}
}
上面的例子約束的url的請求參數必須要包含有name和age,且age不能等於23,如果不滿足條件,就會發生404錯誤
如:
<!-- 滿足條件的url請求 -->
<a href="user/login?name=zhang&age=21">登錄</a>
params中可以接收以下表達式
表達式 | 說明 |
---|---|
paramName | url請求必須包含paramName此參數名 |
!paramName | url請求不能包含paramName此參數名 |
paramName!=xx | url請求必須包含paramName此參數名,且此參數數值不等於xx |
header比較少用,這裡就不補充了
獲得請求url參數值
獲得url請求的參數值,我們可以使用RequestParam註解
使用此註解,可以把url請求參數的數值賦值給方法參數
下麵是@RequestParam註解的常用屬性說明
屬性 | 說明 |
---|---|
value | 請求攜帶參數的參數名 |
required | 標識請求url參數是必須存在某個具體的參數,true(預設):必須存在,不存在則會發生異常;false:不存在 |
defaultValue | 給方法參數賦一個預設值,如果請求url不存在此參數,則使用預設值 |
package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author StarsOne
* @date Create in 2019/9/28 0028 14:27
* @description
*/
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/login")
public String login(@RequestParam(value="username") String name) {
//這裡的返回,相當於頁面跳轉到 views/success.jsp 頁面
return "success";
}
}
請求url為user/login?username=zhang
,之後便會把此請求參數賦值給方法參數name
和我們自定義mvc框架一樣,springmvc框架中,我們也可以直接使用實體類、session、request、response作為方法的參數
@RequestMapping("/user/login")
public login(Student student){
...
}
@RequestMapping("/user/login")
public login(HttpServletRequest request,HttpServletResponse response,HttpSession session){
...
}
與RequestParam
類似的還有這兩個RequestHeader
和CookieValue
這兩個註解我現在沒怎麼用到,暫時瞭解一下,不作補充
- RequestHeader註解,主要是用來獲得請求頭的數據
- CookieValee註解,主要是用來獲得一個cookieValue
返回json數據
我們使用@ResponseBody
,方法返回實體類或者集合的時候,springmvc就會自動幫我們轉為json數據
使用之前需要導入這兩個jar,jackson-core.jar
和jackson-databind.jar
,之前的依賴已經包含下麵這兩個jar了
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.3</version>
</dependency>
UserController.java
package com.wan.controller;
import com.wan.model.Teacher;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author StarsOne
* @date Create in 2019/9/28 0028 14:27
* @description
*/
@Controller
@RequestMapping("/user")
public class UserController {
@ResponseBody
@RequestMapping("/login")
public Teacher login() {
return new Teacher("001", "張三");
}
}
之後在jsp頁面中使用ajax非同步請求
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script type='text/javascript'>
function getData() {
$.getJSON("user/login", function(json){
console.log(json);
});
}
</script>
</head>
<body>
<button onclick="getData()">登錄</button>
</body>
</html>
就可以在控制台看到列印出來的json數據
處理Model數據
SpringMVC中,M其實就是代表著Model(模型),也就是相當於數據
假設我們要從數據查詢數據:先從頁面(View)發送url請求,然後控制器(Controller)通過Service/Dao從資料庫中獲得了數據(Model),並把數據進行處理,使得數據能夠傳回頁面(View)並顯示。
如果是非同步請求的話,我們可以返回一個json數據到頁面,如果不是的話,我們就得把數據存放在request或session的作用域里,之後由頁面(View)從作用域中取出數據並顯示
SpringMVC提供了四種方法來處理那些需要從作用域中取出數據顯示的視圖
- ModelAndView
- Map、ModelMap和Model
- @SessionAttributes
- @ModelAttribute
1.ModelAndView
此類一般用來作方法的返回值來實現返回一個帶數據的頁面(View)
UserController.java
package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author StarsOne
* @date Create in 2019/9/28 0028 14:27
* @description
*/
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/login")
public ModelAndView login() {
String view = "success";
ModelAndView mav = new ModelAndView(view);
Teacher teacher = new Teacher("001","張三");
//相當於request.addAttribute("teacher",teacher)
mav.addObject("teacher",teacher);
return mav;
}
}
success.jsp中取出數據並顯示
<body>
${requestScope.student.tno}
</body>
上面的例子和之前一樣,還是會加上首碼和尾碼,得到views/success.jsp
2.Map、ModelMap和Model
Map、ModelMap和Model一般使用作為方法的參數,之後,通過put方法往裡面存入數據
package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author StarsOne
* @date Create in 2019/9/28 0028 14:27
* @description
*/
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/login")
public String login(Map<String,Object> map) {
String view = "success";
Teacher teacher = new Teacher("001","張三");
//相當於request.addAttribute("teacher",teacher)
map.put("teacher",teacher);
return "success";
}
}
ModelMap和Map的使用方法一樣
還可以使用Model
@RequestMapping("/login")
public String login(Model model) {
String view = "success";
Teacher teacher = new Teacher("001","張三");
//相當於request.addAttribute("teacher",teacher)
model.addAttribute("teacher",teacher);
return "success";
}
Model類還可以使用添加一個map數據,addAllAttribute(Map<String,?> map)
3.@SessionAttributes
前面的兩個方法,都是放入到request的作用域里,如果我們想放入session作用域,可以使用@SessionAttributes註解,一般標註在類上
@SessionAttributes可以將指定的對象加入到session範圍,也可以將某個類型的對象加入到session中
下麵的例子,指定了key為teacher的對象,添加到了session作用域
package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author StarsOne
* @date Create in 2019/9/28 0028 14:27
* @description
*/
@Controller
@RequestMapping("/user")
@SessionAttributes(value="teacher")
public class UserController {
@RequestMapping("/login")
public String login(Map<String,Object> map) {
String view = "success";
Teacher teacher = new Teacher("001","張三");
//在添加到request作用域,同時也添加了session作用域
map.put("teacher",teacher);
return "success";
}
}
把Teacher類型的對象添加到session作用域中
package com.wan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author StarsOne
* @date Create in 2019/9/28 0028 14:27
* @description
*/
@Controller
@RequestMapping("/user")
@SessionAttributes(type=Teacher.class)
public class UserController {
@RequestMapping("/login")
public String login(Map<String,Object> map) {
String view = "success";
Teacher teacher = new Teacher("001","張三");
//在添加到request作用域,同時也添加了session作用域
map.put("teacher",teacher);
return "success";
}
}
4.@ModelAttribute
使用情況:
我們需要對數據進行更新,但我們只能更新數據的某個屬性。
我們點擊編輯之後,只有一個輸入框讓我們輸入,用來更改那個屬性,我們輸入更改後的屬性值,更新的時候會發現,controller裡面的數據,傳入的對象除了更改的那個屬性值,其他的屬性值都是為null,我們不希望這種情況,所以,使用此註解
此註解用來修飾controller里的某個方法,然後就會在執行controller中@RequestMapping的方法之前執行,把傳入的對象中的數據更新,之後執行修改操作的話,只會把對象需要修改的屬性值更改,其他的屬性值不變(不為null了)
我個人覺得這樣好像比較麻煩,上面的情況有個更好的解決辦法,就是不要使用唯一的輸入框,而是使用多個輸入框,把不能更改的那幾項輸入框設置disable,之後提交表單也能成功傳入其他的屬性值
視圖解析器
工作流程
springmvc框架中,請求處理方法(Controller中的方法)執行完成後,最終返回一個ModelAndView 對象。
Spring MVC 藉助視圖解析器(ViewResolver)得到最終的視圖對象(View),最終的視圖可以是JSP ,也可能是Excel、JFreeChart 等各種表現形式的視圖
對於最終究竟採取何種視圖對象對模型數據進行渲染(也就是我們常說的把數據從request等作用域取出來顯示到頁面上),處理器並不關心,處理器工作重點聚焦在生產模型數據的工作上,從而實現MVC 的充分解耦
對於那些返回String,View 或ModeMap 等類型的處理方法,Spring MVC 也會在內部將它們裝配成一個ModelAndView 對象,它包含了邏輯名和模型對象的視圖;
如下圖:
View
springmvc中的View其實是個介面,下麵是常見的View介面的實現類
視圖類型 | 實現類 | 說明 |
---|---|---|
URL視圖類型 | InternalResourceView | 將JSP或其他資源封裝成一個視圖。被視圖解析器InternalResourceViewResolver預設使用。 |
URL視圖類型 | JstlView | InternalResourceView的子類。如果JSP中使用了JSTL的國際化標簽,就需要使用該視圖類 |
文檔視圖 | AbstractExcelView | Excel文檔視圖的抽象類 |
文檔視圖 | AbstractPdfView | PDF文檔視圖的抽象類 |
報表視圖 | ConfigurableJasperReportsView | |
報表視圖 | JasperReportsHtmlView | |
報表視圖 | JasperReportsPdfView | |
報表視圖 | JasperReportsXlsView | |
JSON視圖 | MappingJackson2JsonView | 將數據通過Jackson框架的ObjectMapper對象,以JSON方式輸出 |
ViewResolver以及子類
ViewResolver和View一樣,也是個介面
視圖解析器類型 | 類名 | 說明 |
---|---|---|
解析為映射文件 | UrlBasedViewResolver | 它簡單實現了ViewResolver介面, 不用任何映射就能通過邏輯視圖名稱訪問資源 |
解析為映射文件 | InternalResourceViewResolver | 將邏輯視圖名解析為一個路徑 |
解析為bean | BeanNameViewResolver | 將邏輯視圖名解析為bean的name屬性,從而根據name屬性去找對應的bean |
解析為bean | ResourceBundleResolver | 和BeanNameViewResolver一樣,只不過定義的view-bean都在一個properties文件中,用這個類進行載入這個properties文件 |
解析為bean | XmlViewResolver | 和ResourceBundleResolver一樣,只不過定義的view-bean在一個xml文件中,用這個類來載入xml文件 |
解析為模版文件 | VelocityViewResolver | 對Velocity模版引擎的支持 |
解析為模版文件 | FreeMarkerViewResolver | 對FreeMarker模版引擎的支持 |
這裡,我只介紹以下前兩種,也就是我們用過的類型。更多請參考我們下麵給出的鏈接
AbstractCachingViewResolver,這個類為抽象類,實現了ViewResolver介面,抽象類只能被繼承,無法創建實例。
UrlBasedViewResolver就是繼承於AbstractCachingViewResolver這個類,從而擴展了功能。
AbstractCachingViewResolver介紹:
這種視圖解析器會把它曾經解析過的視圖保存起來,然後每次要解析視圖的時候先從緩存裡面找。
如果找到了對應的視圖就直接返回,如果沒有就創建一個新的視圖對象,然後把它放到一個用於緩存的map中,接著再把新建的視圖返回。
使用這種視圖緩存的方式可以把解析視圖的性能問題降到最低。
UrlBasedViewResolver介紹:
繼承了AbstractCachingViewResolver,主要就是提供的一種拼接URL的方式來解析視圖,它可以讓我們通過prefix
屬性指定一個指定的首碼,通過suffix
屬性指定一個指定的尾碼,然後把返回的邏輯視圖名稱加上指定的首碼和尾碼就是指定的視圖URL了。
InternalResourceViewResolver介紹:
這個類是繼承於UrlBasedViewResolver,UrlBasedViewResolver具有的功能它都有,而且還有它自己的特性。從字面翻譯,InternalResourceViewResolver就是內部資源解析器。
InternalResourceViewResolver會把返回的視圖名稱都解析為InternalResourceView對象,InternalResourceView會把Controller處理器方法返回的模型屬性都存放到對應的request屬性中,然後通過RequestDispatcher在伺服器端把請求forword重定向到目標URL。
參考鏈接:Spring MVC-從零開始-view-ViewResolver
靜態資源訪問
情景
如果我們想要通過一個url去訪問我們項目中的一個圖片、js文件、視頻等靜態資源,會發現報404錯誤
原因是我們定義一個前置Servlet,處理了所有的url請求,但是,由於未能找到RequestMapping註解上的相匹配的url,所以就會出現404錯誤
解決方法
在springmvc配置文件中添<mvc:default-servlet-handler/>
和<mvc:annotation-driven></mvc:annotation-driven>
即可解決問題
之前給出的springmvc配置文件中,其實已經添加了這兩個標簽,在這裡稍微介紹一下作用
<mvc:default-servlet-handler/>
作用:在SpringMVC上下文中,定義了一個DefaultServletHttpRequestHandler,它會對鄋DispatcherServlet處理的請求進行檢查,如果發現某個請求沒有對應的@RequestMapping進行處理,就會將該請求交個Web伺服器預設的Servlet進行處理,二預設的Servlet就會直接根據url去訪問該資源
<mvc:annotation-driven></mvc:annotation-driven>
作用:訪問靜態資源的同時,眼能夠正常的訪問其他非靜態資源
兩個標簽都要添加
中文亂碼方法(補充)
1. 設置頁面編碼
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
2.配置過濾器
在web.xml中配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>SpringMVC Demo</display-name>
<!-- 中文轉碼必須加到核心控制器前面 -->
<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>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
<!-- springmvc 核心控制器,將springMVC整合到項目里-->
<servlet>
<servlet-name>springmvc-DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 配置spring mvc的組件:掃描controller, view resovle -->
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
<!-- 伺服器啟動時載入順序 -->
<load-on-startup>1</load-on-startup>
<!-- 非同步請求處理支持 -->
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>springmvc-DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
更多方法,請查看參考鏈接