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

来源:https://www.cnblogs.com/kexing/archive/2019/10/01/11615562.html
-Advertisement-
Play Games

SpringMVC框架是基於Spring框架,可以讓我們更為方便的進行Web的開發,實現前後端分離 思路和原理 我們之前仿照SpringMVC定義了一個自定義MVC框架,兩者的思路其實都是一樣的。 建議結合兩篇文章進行學習 "JSP學習筆記(6)—— 自定義MVC框架" 首先,提供一個前置攔截器(D ...


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中文亂碼


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 未經允許,不得轉載 原作者: "字母哥博客" 本文完整系列出自: "springboot深入淺出系列" 一、使用IntellijIDEA建立第一個spring boot 項目 通常只有專業版付費版才預設帶有Spring Initialzr功能,如果你的IDEA沒有這個選項。可以參照本文末尾《附文:S ...
  • 代碼實現了利用遞歸對數組進行快速排序,其中limit為從已有的隨機數文件中輸入的所要進行排序的數據的數量(生成隨機數並寫入文件的過程已在前篇中寫出)。 演算法主要利用哨兵元素對數據進行分塊,遞歸無限細分之後實現排序。 代碼同樣利用clock函數對演算法的執行時間進行計算以進行演算法的效率評估。 為了驗證排 ...
  • 由於可能需要對分治策略實現二分搜索的演算法效率進行評估,故使用大量的隨機數對演算法進行實驗(生成隨機數的方法見前篇隨筆)。 由於二分搜索需要數據為有序的,故在進行搜索前利用函數庫中sort函數對輸入的數據進行排序。 代碼主要用到的是經典的二分查找加上遞歸。 其中limit為所要從隨機數文件中提取的數據的 ...
  • 01背包 n個物品,v的體積,求最多能裝下的價值 每個物品只能拿一次 https://www.acwing.com/problem/content/2/ 1 #include<bits/stdc++.h> 2 using namespace std; 3 int main(){ 4 int N,V, ...
  • 代碼實現了使用C++進行隨機數的生成,其中NUMBER為所要生成的隨機數的數量,RANGE為生成的隨機數的範圍[0,RANGE]。 生成的隨機數會寫入同文件夾下的random_number.txt文件中,格式為每個數字占一行。 該代碼會在生成隨機數的同時對生成隨機數並完成寫入文件所消耗的時間進行計算 ...
  • 今天我們來使用JPA做分頁項目並且做講解 如果是新來的朋友請回上一篇 上一篇:微項目(一) maven整合 在pom文件的 依賴中導入以下依賴 然後重啟項目 我們可以看到項目跑起來後運行出來一個tomcat 我們可以看到這裡出現了404錯誤。雖然是錯誤但是出來這個就對了。 下麵我們來配置對項目的增和 ...
  • 1.創建app python manage.py startapp 名字 Migrations 資料庫同步目錄,記錄資料庫同步的記錄 __init__ 包文件 Admin.py django自帶的後臺管理文件 Apps app管理文件 Models.py 資料庫建模文件,ORM文件 Tests.py ...
  • [學習筆記] 7.jdbc的transaction例子: import java.sql.*;public class MySQlTransaction1 { public static void main(String[] args) throws SQLException {/*in my sq ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...