1. 程式人生 > >Spring框架學習筆記(3)——SpringMVC框架

Spring框架學習筆記(3)——SpringMVC框架

SpringMVC框架是基於Spring框架,可以讓我們更為方便的進行Web的開發,實現前後端分離

思路和原理

我們之前仿照SpringMVC定義了一個自定義MVC框架,兩者的思路其實都是一樣的。

建議結合兩篇文章進行學習

JSP學習筆記(6)—— 自定義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,,會被自動加入字首和字尾,注意,這裡是進行的請求轉發

除此之外,我們還可以加上forwardredirect字首來進行請求轉發或重定向

但是,如果使用這兩種字首,之後檢視解析器就不會自動新增字首和字尾了。所以,我們得指定具體跳轉的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類似的還有這兩個RequestHeaderCookieValue

這兩個註解我現在沒怎麼用到,暫時瞭解一下,不作補充

  • RequestHeader註解,主要是用來獲得請求頭的資料
  • CookieValee註解,主要是用來獲得一個cookieValue

返回json資料

我們使用@ResponseBody,方法返回實體類或者集合的時候,springmvc就會自動幫我們轉為json資料

使用之前需要匯入這兩個jar,jackson-core.jarjackson-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>

更多方法,請檢視參考連結

參考連結:徹底解決springMVC中文亂