SpringMVC筆記

假大神_阿諾發表於2020-10-12

SpringMVC

MVC三層架構

JavaSE:認真學習,老師帶,入門快

JavaWeb:認真學習,老師帶,入門快

框架:研究官方文件,鍛鍊自學能力,鍛鍊筆記能力,鍛鍊專案能力

Spring: IOC 和 AOP

SpringMVC:SpringMVC的執行流程

1. 什麼是MVC?

模型(Model):dao,service

檢視(View):jsp

控制器(Controller):Servlet

  • 擴充的一個思想:

實體類:pojo 例如User類有20個欄位(使用者名稱、密碼、生日。。。)

當前端所需要的實體類欄位沒有那麼多時,可能還會在pojo的基礎上拆分出vo等

vo:意思為檢視層中的實體類

pojo中的實體類可以寫上所有欄位,vo中的實體類就寫需要在前端顯示的欄位

2. Maven建立web專案

1. 建立一個web專案,採用不勾選的方式:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-TecNF9Zw-1602517447290)(G:\學習筆記\SpringMVC學習筆記\image\1.PNG)]

2. 右鍵專案,選擇Add Frameworks Support,新增框架支援

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-37xI41pI-1602517447293)(G:\學習筆記\SpringMVC學習筆記\image\2.PNG)]

3. 右鍵專案,選擇Add Frameworks Support,新增框架支援

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-0VmZVtnn-1602517447295)(G:\學習筆記\SpringMVC學習筆記\image\3.PNG)]

這樣原來的預設專案就成為了web專案:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-XeWnNv0A-1602517447298)(G:\學習筆記\SpringMVC學習筆記\image\4.PNG)]

這種不勾選的方式存在一個弊端:

就是我們的匯入的依賴jar包,無法匯出到war包中,需要我們手動建立lib資料夾並匯入:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-aIadeWrq-1602517447301)(G:\學習筆記\SpringMVC學習筆記\image\5.PNG)]

要想不用手動匯入依賴Jar包,還是要選擇Maven骨架中的webapp進行建立web專案

3. MVC框架要做的事情

  1. 將url對映到java類或者java類的方法
  2. 封裝使用者提交的資料
  3. 處理請求–呼叫相關的業務處理–封裝相應資料
  4. 將響應的資料進行渲染 jsp/html等檢視層
  • 擴充套件

    MVVM:M , V , VM → ViewModel:雙向繫結 (在Vue中有體現)

4. 為什麼學習SpringMVC

  • SpringMVC的特點

    1. 輕量級,簡單易學

    2. 高效,基於請求響應的MVC框架

    3. 與Spring相容性好,無縫結合

      Spring:大雜燴,我們可以將SpringMVC中所有要用到的bean,註冊到Spring中

    4. 約定優於配置

    5. 功能強大:RESTful、資料驗證、格式化、本地化、主題等

    6. 簡潔靈活

  • 最重要的一點還是用的人多,使用的公司多

5. SpringMVC開發步驟

  1. 在pom.xml中匯入相關依賴

  2. 在web.xml中配置DispatcherServlet(前端控制器)

  3. 編寫springmvc的配置檔案:

    掃描註解、檢視解析器、不處理靜態資源、介面卡和對映器的註冊

  4. 編寫Controller類,@Controller註解 或者 @RestController註解

    接收前端資料 + 封裝資料 + 跳轉檢視 或者 接收前端資料 + 返回Json字串

  5. 編寫檢視層,資料渲染

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-3nIoyWlE-1602517447303)(G:\學習筆記\SpringMVC學習筆記\image\6.png)]

6. SpringMVC的執行原理

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-LgCxzI3l-1602517447305)(G:\學習筆記\SpringMVC學習筆記\image\7.png)]

  1. 使用者傳送請求至前端控制器DispatcherServlet。

  2. DispatcherServlet收到請求呼叫HandlerMapping處理器對映器。

  3. 處理器對映器找到具體的處理器(可以根據xml配置、註解進行查詢),生成處理器物件及處理器攔截器(如果有則生成)一併返回給DispatcherServlet。

  4. DispatcherServlet呼叫HandlerAdapter處理器介面卡。

  5. HandlerAdapter經過適配呼叫具體的處理器(Controller,也叫後端控制器)。

  6. Controller執行完成返回ModelAndView。

  7. HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet。

  8. DispatcherServlet將ModelAndView傳給ViewReslover檢視解析器。

  9. ViewReslover解析後返回具體View。

  10. DispatcherServlet根據View進行渲染檢視(即將模型資料填充至檢視中)。

  11. DispatcherServlet響應使用者。

7. SpringMVC元件解析

1. 前端控制器

Spring的web框架圍繞DispatcherServlet設計。

DispatcherServlet的作用是攔截請求,並將請求分發到不同的處理器。

從Spring 2.5開始,使用Java 5或者以上版本的使用者可以採用基於註解的controller宣告方式。

DispatcherServlet是一個實際的Servlet,它繼承了HttpServlet。

DispatcherServlet 的存在降低了元件之間的耦合性

我們需要在web.xml中註冊DispatcherServlet:

<?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">
    <!-- 註冊DispatcherServlet:這個是SpringMVC的核心(請求分發器,或者叫前端控制器) -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--
            DispatcherServlet要繫結Spring的配置檔案
            注意:在ssm框架整合後,這裡繫結的Spring配置檔案必須為三層配置檔案的集合:
								 在applicationContext.xml中對三層配置檔案進行import,
								 然後在下方param-value中繫結applicationContext.xml即可。
         -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <!-- 啟動級別設定為1:隨著伺服器啟動而啟動 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--
        在SpringMVC中,/ 和 /* 的區別:
        /: 只匹配所有的請求,不會去匹配jsp頁面。例如:/a.jsp
        /*: 匹配所有的請求,包括jsp頁面,這樣會導致我們轉發到jsp頁面後,又被DispatcherServlet攔截給處理器
        所以往往不需要匹配jsp頁面,一般只寫一個/即可。
     -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

2. 處理器對映器

HandlerMapping

負責根據使用者的請求找到Handler(即處理器)

SpringMVC提供了不同的對映器實現不同的對映方式。

例如:配置檔案方式、實現介面方式、註解方式等

3. 處理器介面卡

HandlerAdapter

通過HandlerAdapter對處理器進行執行,這是介面卡模式的的應用,通過擴充套件介面卡可以對更多型別的處理器進行執行

  • 處理器對映器 和 處理器介面卡 需要在springmvc配置檔案中註冊:

    方式一:【不推薦】

    <!-- 處理器對映 -->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!-- 處理器介面卡 -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    

    方式二:【推薦】

    <!--
       支援mvc註解驅動
       在spring中一般採用@RequestMapping註解來完成對映關係
       要想使@RequestMapping註解生效
       必須向上下文中註冊DefaultAnnotationHandlerMapping
       和一個AnnotationMethodHandlerAdapter例項
       這兩個例項分別在類級別和方法級別處理。
       而annotation-driven配置幫助我們自動完成上述兩個例項的注入。
    	 而且底層封裝了Jackson:
    	 由介面卡自動地將處理方法返回的Java物件轉換為Json字串
    -->
    <mvc:annotation-driven />
    

    使用<mvc:annotation-driven /> 自動載入處理器對映器和處理器對映器,替代處理器對映器和處理器介面卡的註冊。
    同時預設底層就會整合jackson進行物件或集合的json格式字串的轉換

4. 處理器

Handler

它就是我們開發中要編寫的具體業務控制器。

由 DispatcherServlet 把使用者請求轉發到 Handler。

由Handler 對具體的使用者請求進行處理。

  • 以註解方式對映的處理器(控制器),需要在springmvc配置檔案中註冊

    <!-- Handler -->
    <bean id="/hello" class="com.anuo.controller.HelloController"/>
    

5. 檢視解析器

View Resolver

負責將處理結果(ModelAndView)生成View檢視物件返回給前端控制器

View Resolver根據邏輯檢視名解析成物理檢視名,即具體的頁面地址,再生成View檢視物件。

View檢視物件包含 具體的頁面地址 和 model模型資料

  • 預設的檢視解析器:

SpringMVC有預設元件配置,預設元件都是DispatcherServlet.properties配置檔案中配置的,該配置檔案地址org/springframework/web/servlet/DispatcherServlet.properties,該檔案中配置了預設的檢視解析器,如下:

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

翻看該解析器原始碼,可以看到該解析器的預設設定,如下:

REDIRECT_URL_PREFIX = "redirect:"  --重定向字首
FORWARD_URL_PREFIX = "forward:"    --轉發字首
prefix = "";     --檢視名稱字首
suffix = "";     --檢視名稱字尾

我們可以通過屬性注入的方式修改檢視的的前字尾:

<!--配置內部資源檢視解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/WEB-INF/jsp/"></property>
  <property name="suffix" value=".jsp"></property>
</bean>

當使用了 重定向字首 或者 轉發字首,將不進行檢視名稱的拼接

6. 檢視:View

SpringMVC 框架提供了很多的 View 檢視型別的支援,包括:jstlView、freemarkerView、pdfView等。最常用的檢視就是 jsp。

一般情況下需要通過頁面標籤或頁面模版技術將模型資料通過頁面展示給使用者,需要由程式設計師根據業務需求開發具體的頁面

8. SpringMVC基本配置整合

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 自動掃描包,讓指定包下的註解生效,由IOC容器統一管理 -->
    <context:component-scan base-package="com.anuo.controller"/>
    <!-- 讓Spring MVC不處理靜態資源 例如:.css .js .html .mp3 .mp4等-->
    <mvc:default-servlet-handler/>
    <!--
        支援mvc註解驅動
        在spring中一般採用@RequestMapping註解來完成對映關係
        要想使@RequestMapping註解生效
        必須向上下文中註冊DefaultAnnotationHandlerMapping
        和一個AnnotationMethodHandlerAdapter例項
        這兩個例項分別在類級別和方法級別處理。
        而annotation-driven配置幫助我們自動完成上述兩個例項的注入。
			  而且底層封裝了Jackson:
	 			由介面卡自動地將處理方法返回的Java物件轉換為Json字串
      -->
    <mvc:annotation-driven />

    <!-- 檢視解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!-- 字首 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 字尾 -->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

9. SpringMVC入門

9.1 配置版

配置版一個類只能寫一個處理方法(類似於servlet的service方法)

  1. 寫一個類實現Controller介面,重寫handleRequest(..)方法

    public class HelloController implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
            //ModelAndView 模型和檢視
            ModelAndView mv = new ModelAndView();
            //封裝物件,放在ModelAndView中。Model
            mv.addObject("msg","HelloSpringMVC!");
            //封裝要跳轉的檢視,放在ModelAndView中
            mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
            return mv;
        }
    }
    
  2. 在springmvc配置檔案中進行bean註冊(前提是準備工作要配置好)

    <!-- Handler -->
    <bean id="/hello" class="com.anuo.controller.HelloController"/>
    

    其中id就是該處理器的路由。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

配置版的程式碼便於理解SpringMVC的原理,但是實際開發中並不會這麼寫!

9.2 註解版【重點】

註解版的實現,才是SpringMVC的精髓所在!

  • 實現的步驟:
  1. 建立一個web專案

  2. 匯入相關jar包依賴

  3. 編寫web.xml配置,註冊DispatcherServlet

  4. 編寫springmvc配置檔案

  5. 建立一個Controller類

    @Controller用於表明這個類是一個控制器類,被spring容器接管

    @Requestmapping用於指定處理器的路由

    返回ModelAndView的寫法:

    寫法一:返回String ,引數使用Model封裝資料

    @Controller
    public class HelloController {
    
        @RequestMapping("/h1")
        public String hello(Model model) {
            // 1.封裝資料
            model.addAttribute("msg", "hello,SpringMVCAnnotation!");
            // 2.檢視跳轉,現在return即可
            return "hello"; // 會被檢視解析器處理
        }
    }
    

    寫法二:返回ModelAndView物件

    @Controller
    public class HelloController {
        @RequestMapping("/h1")
        public ModelAndView hello() {
            ModelAndView mv = new ModelAndView();
          	// 1.封裝資料
          	mv.addObject("msg", "hello,SpringMVCAnnotation!");
            // 2.設定跳轉檢視的邏輯名
            mv.setViewName("hello");
            // 3.返回ModelAndView物件,會被檢視解析器處理
            return mv;
        }
    }
    

    兩種寫法的本質都是一樣的,經常用的是第一種寫法

  6. 在SpringMVC配置檔案中掃描註解(前提是準備工作要配置好)

    <!-- 自動掃描包,讓指定包下的Controller註解生效,由IOC容器統一管理 -->
    <context:component-scan base-package="com.anuo.controller"/>
    
  7. 檢視頁面hello.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>註解版springmvc</title>
    </head>
    <body>
        ${msg}
    </body>
    </html>
    
  8. 執行專案,瀏覽器訪問測試

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-tkko5ggc-1602517447307)(G:\學習筆記\SpringMVC學習筆記\image\8.PNG)]

10. 控制器Controller

  • 控制器負責提供訪問應用程式的行為,通常通過介面定義或者註解定義兩種方法實現
  • 控制器負責解析使用者的請求並將其轉換為一個模型

10.1 實現Controller介面

需要在配置檔案中註冊bean

  • 總結

    1. 實現介面Controller定義控制器是較老的辦法

    2. 缺點:

      一個控制器中只有一個辦法,如果要多個辦法則需要定義多個Controller。

      定義的方式比較麻煩!

10.2 使用註解@Controller

  • 回顧Spring中的註解

    @Component  // 元件
    @Service    // service層
    @Controller // controller層
    @Repository // dao層
    
  • 在類的上方使用註解@Controller:

    代表這個類是一個控制器,會被Spring容器接管

  • 需要在springmvc配置檔案中進行 名稱空間引入 和 元件掃描

    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
      
    2. 元件掃描

      SpringMVC基於Spring容器,所以在進行SpringMVC操作時,需要將Controller儲存到Spring容器中。

      如果使用@Controller註解標註的話,就需要元件掃描:

      <!-- 自動掃描包,讓指定包下的Controller註解生效,由IOC容器統一管理 -->
      <context:component-scan base-package="com.anuo.controller"/>
      

10.3 SpringMVC註解解析

@RequestMapping

  • 作用

    @RequestMapping註解用於對映url到控制器類或一個特定的處理程式方法

  • 使用位置

    可用於類或者方法上:

    用於類上,請求URL 的第一級訪問目錄。此處不寫的話,就相當於應用的根目錄

    用於方法上,則表示請求 URL 的第二級訪問目錄

    類與方法上的使用@ReqquestMapping標註的一級目錄一起組成訪問的虛擬路徑

    一般都需要在類上寫@ReqquestMapping的:

    作為對該Controller類和其他Controller類的一個區分,

    並且日後更好地完成許可權的控制。

  • 屬性

    1. value:用於指定請求的URL。它和path屬性的作用是一樣的

    2. method:用於指定請求的方式

      方法級別的註解變體有如下幾個:組合註解

      @GetMapping

      @PostMapping

      @PutMapping

      @DeleteMapping

      @PatchMapping

      例如:@GetMapping 等於 @RequestMapping(method=RequestMethod.GET)

    3. params:用於指定限制請求引數的條件。它支援簡單的表示式。

      ​ 要求請求引數中的key和value必須和配置的一模一樣

      例如: params = {“accountName”},表示請求引數必須有accountName

      ​ params = {“moeny!100”},表示請求引數中money不能是100

@Controller

  • 作用

    表示這個類是一個控制器元件,被spring容器接管

  • 使用位置

    類上

@ResponseBody

  • 作用

    告知SpringMVC框架,不進行檢視跳轉,直接進行資料響應。

  • 使用位置

    用在類或者方法上

    用在類上:表示該控制器類中的所有處理方法都不進行檢視跳轉

    用在方法上:表示該處理方法不進行檢視跳轉,直接響應資料

@RestController

  • 作用

    @RestController = @Controller + @ResponseBody

  • 使用位置

    類上

@RequestParam

  • 作用

    與請求引數名進行匹配

  • 使用位置

    controller處理方法的引數上

  • 使用場景

    1. 當方法的引數是普通型別時(String、Integer…等等),

      方法引數名與想要匹配的請求引數名不一致時必須使用

    2. 當方法的引數是Map<String, String>型別的時候,在引數前直接加上@RequestParam,否則無法接收請求引數。

@PathVariable

  • 作用

    用來匹配請求url的佔位符

  • 使用位置

    controller處理方法的引數上

  • 使用場景

    常用於restful風格,當方法需要接收的值在url地址中時,例如"/user/1/2",

    而並不是在請求引數中的。

@RequestBody

  • 作用

    json型別請求體中(body)的資訊裝配到方法的pojo型別的引數中

    如果是get請求方式,請求引數在url中的,可以不加這個註解,自動會裝配到方法的pojo型別的引數中。

  • 使用位置

    controller處理方法的引數上

  • 使用條件

    1. 請求引數在方法體中(常見的:post請求和put請求)

    2. 資訊傳輸的格式為json時(Content-Type為application/json

  • 使用場景

    常用於pojo型別的引數以及List集合型別(泛型為pojo型別)的引數

11. SpringMVC的資料響應

11.1 ModelAndView

封裝了 資料模型(Model) 和 檢視邏輯名(未經過拼接的檢視名) 的物件

其中Model作為域物件,它類似於我們的request物件,生命週期就是僅一次的請求相應

  • 方法:

    ModelAndView mv = new ModelAndView();
    mv.addObject("key", Object value)
    mv.setViewName("檢視邏輯名")  
    
  • 單獨使用Model物件時,它的方法:

    Model model = new Model();
    model.addAttribute("key", Object value)
    

11.2 資料響應的方式

  1. 頁面跳轉

    不攜帶資料,直接返回字串

    攜帶資料,通過ModelAndView物件返回

  2. 回顯資料

    直接返回字串

    返回物件或者集合

11.3 頁面跳轉1-不攜帶資料

  1. 不帶字首:經過檢視解析器,並進行拼接

    頁面實體地址 : {prefix} + viewName +{suffix}

  2. 帶字首:經過檢視解析器,但不進行拼接

    "redirect:" 或者 "forward:"

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-XpyjCM4J-1602517447308)(G:\學習筆記\SpringMVC學習筆記\image\9.jpg)]

// 經過檢視解析器拼接
@RequestMapping("/m1")
public String test01(Model model) {
  model.addAttribute("msg", "轉發方式跳轉過來了");
  return "test";
}
// 重定向到新的頁面
@RequestMapping("/m2")
public String test02() {
    return "redirect:/restfulTest.jsp";
}

// 轉發到新的頁面 或者 新的處理方法
@RequestMapping("/m3")
public String test03(Model model) {
    model.addAttribute("msg", "轉發方式跳轉過來了");
    return "forward:/m1";
}

注意事項:

  1. 使用"redirect:" 或者 "forward:"後面跟的路徑開頭一定不能加空格

    不要寫貫了yaml格式,在:後面就喜歡加空格

  2. 重定向到新的頁面,該頁面不能在WEB-INF下,且無法使用Model攜帶資料

  3. 請求轉發的新的處理方法,還是比較常用的。

    比如,當我們更新好資料,往往轉發到查詢顯示的處理方法,達到重新整理的效果

11.4 頁面跳轉2-攜帶資料

有三種形式,最常用的是形式二

  • 返回ModelAndView形式一:

    在Controller中方法返回ModelAndView物件,並且設定檢視名稱

    @RequestMapping("/quick2")
    public ModelAndView save2(){
        /*
          Model:模型 作用封裝資料
          View:檢視 作用展示資料
        */
        ModelAndView modelAndView = new ModelAndView();
        // 設定模型資料
        modelAndView.addObject("username","itcast");
        // 設定檢視名稱
        modelAndView.setViewName("success");
        return modelAndView;
    }
    

    也可以在Controller中方法形參上直接宣告ModelAndView,無需在方法中自己建立,在方法中直接使用該物件設定檢視,同樣可以跳轉頁面

    @RequestMapping("/quick3")
    public ModelAndView save3(ModelAndView modelAndView){
        modelAndView.addObject("username","itheima");
        modelAndView.setViewName("success");
        return modelAndView;
    }
    
  • 返回ModelAndView形式二:

    使用Model物件封裝資料,檢視邏輯名直接作為返回值

    // 單獨
    @RequestMapping("/quick4")
    public String save4(Model model){
        model.addAttribute("username","博學谷");
        return "success";
    }
    
  • 返回ModelAndView形式三:

    在Controller方法的形參上可以直接使用原生的HttpServeltRequest物件,進行資料封裝

    @RequestMapping("/quick5")
    public String save5(HttpServletRequest request){
        request.setAttribute("username","酷丁魚");
        return "success";
    }
    

11.5 資料回顯1-文字字串

  1. 將需要回顯的字串直接返回,但此時需要通過@ResponseBody註解告知SpringMVC框架,方法返回的字串不是跳轉是直接在http響應體中返回:

    @RequestMapping("/quick6")
    @ResponseBody //告知SpringMVC框架 不進行檢視跳轉 直接進行資料響應
    public String save7(){
        return "hello itheima";
    }
    
  2. 通過SpringMVC框架注入的response物件,使用response回顯資料,此時不需要檢視跳轉,業務方法返回值為void:【不常用】

    @RequestMapping("/quick7")
    public void save6(HttpServletResponse response){
        response.getWriter().print("hello itcast");
    }
    

11.6 資料回顯2-Json字串

直接以String作為方法返回值

@RequestMapping(value="/quick8")
@ResponseBody
public String save8(){
    return "{\"username\":\"zhangsan\",\"age\":18}";
}

手動拼接Json格式的字串太麻煩,我們往往需要使用JSON轉換工具,將Java物件轉換成Json字串:Jackson | Fastjson

@RequestMapping(value="/quick9")
@ResponseBody
public String save9() throws IOException {
    User user = new User();
    user.setUsername("lisi");
    user.setAge(30);
    //使用json的轉換工具將物件轉換成json格式字串在返回
    ObjectMapper objectMapper = new ObjectMapper();
    String json = objectMapper.writeValueAsString(user);
    return json;
}

為什麼我要強調以String作為返回值呢?

因為以物件或集合作為返回值的話,SpringMVC會自動幫我們將Java物件轉換為Json字串進行資料回顯。其實也是內部封裝了Jackson去完成的【需要配置】

但是可以想想,返回String也有它的好處,我們可以返回任意的Java物件的Json字串格式,只需要自己手動加上轉換的過程

11.7 資料回顯3-物件或集合

我曾經有這樣一個困惑,當我們直接以Java物件作為返回值時,最後SpringMVC會幫助我們將Java物件以Json字串的格式進行回顯,那麼我們還需要Jackson等Json轉換工具嗎?

其實呀,是我們在配置的時候,將SpringMVC底層整合了Jackson來幫我們完成這件事

怎麼配置的?,SpringMVC自動幫助我們將物件或集合進行json字串的轉換並回顯,是==在處理器介面卡中完成的==,所以我們要為處理器介面卡配置訊息轉換引數,指定使用jackson進行物件或集合的轉換,因此需要在spring-mvc.xml中進行如下配置:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
  <property name="messageConverters">
    <list>
      <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
    </list>
  </property>
</bean>

這樣配置比較麻煩,配置的程式碼比較多。
因此,我們可以使用mvc的註解驅動代替上述配置:

<mvc:annotation-driven/>

在 SpringMVC 的各個元件中,處理器對映器、處理器介面卡、檢視解析器稱為 SpringMVC 的三大元件。
使用<mvc:annotation-driven /> 自動載入處理器對映器和處理器對映器,替代處理器對映器和處理器介面卡的註冊。
同時預設底層就會整合jackson進行物件或集合的json格式字串的轉換

@RequestMapping(value="/quick10")
@ResponseBody
//期望SpringMVC自動將User轉換成json格式的字串
public User save10(){
    User user = new User();
    user.setUsername("lisi2");
    user.setAge(32);
    return user;
}

12. SpringMVC的請求接收

12.1 請求引數型別

客戶端請求引數的格式是:name=value&name=value……

伺服器端要獲得請求的引數,有時還需要進行資料的封裝。

SpringMVC可以接收如下型別的引數:

  1. 基本型別引數

  2. POJO型別引數

  3. 陣列型別引數

  4. 集合型別引數

12.2 獲得基本型別引數

Controller中的業務方法的引數名稱要與請求引數的name一致。

  • 如果不一致,我們需要在處理方法引數中使用**@RequestParam(“請求引數名”)**註解

引數值會自動對映匹配,並且能自動做型別轉換

自動的型別轉換是指從String向其他型別的轉換

例如:

請求URL:http://localhost:8080/user?username=zhangsan&age=12

處理方法:

@RequestMapping("/user")
@ResponseBody
public void save11(@RequestParam("username") String name,int age){
    System.out.println(username);
    System.out.println(age);
}

12.3 獲得POJO型別引數

Controller中的業務方法的POJO引數的屬性名與請求引數的name一致,引數值會自動對映匹配。

屬性名與請求引數的name不一致,是不會進行封裝的,也無法使用@RequestParam(),那怎麼解決這個問題呢?

在實體類相應的屬性中使用jackson中的**@JsonAlias** 或者 @JsonProperty註解

有以下兩種情況:

  1. 當請求引數在url中時(get請求),不加註解也會自動對映匹配

    public class User {
        private String username;
        private int age;
      	// ...以下省略getter和setter
    }
    

    請求URL:http://localhost:8080/user?username=zhangsan&age=12

    @RequestMapping("/user")
    @ResponseBody
    public void save11(User user){
        System.out.println(user);
    }
    
  2. 當請求引數在請求體body中時,需要加@RequestBody註解,才能自動匹配

    並且Content-Type需要設定為application/json

    public class User {
        private String username;
        private int age;
      	// ...以下省略getter和setter
    }
    

    請求URL:http://localhost:8080/user

    請求體:{“username”: “zhangsan”, “age”: “12” }

    @RequestMapping("/user")
    @ResponseBody
    public void save11(@RequestBody User user){
        System.out.println(user);
    }
    

12.4 獲得陣列型別引數

Controller中的業務方法陣列名稱與請求引數的name一致,引數值會自動對映匹配。

當我們的請求引數name都是一致的,但是value不同時,使用陣列進行接收。

例如:

請求URL:http://localhost:8080/user?strs=111&strs=222

@RequestMapping("/user")
@ResponseBody
public void save11(String[] strs){
    System.out.println(Arrays.asList(strs));
}

12.5 獲取Map型別的引數

當我們進行條件查詢的時候,條件有很多並且不確定傳過來的是哪個條件

比如可能是name=”zhangsan“,也可能是age=”12“,所以我們統一用**Map<String, String>**型別去接收。

但是我們需要對引數使用**@RequestParam**註解,否則接收不到

例如:

請求url: http://localhost:8080/user?name=zhangsan&age=12

controller:

@RequestMapping(value="/quick13")
@ResponseBody
public void save14(@Requestparam Map<String, String> map) throws IOException {
    System.out.println(nap);
}

12.5 獲得List型別的引數I

當前端傳過來的集合並不是Ajax的Json字串格式時:

獲得集合引數時,要將集合引數包裝到一個VO中才可以。

例如:

前端表單:

<form action="${pageContext.request.contextPath}/user/quick14" method="post">
    <%--表明是第一個User物件的username age--%>
    <input type="text" name="userList[0].username"><br/>
    <input type="text" name="userList[0].age"><br/>
    <%--表明是第二個User物件的username age--%>  
    <input type="text" name="userList[1].username"><br/>
    <input type="text" name="userList[1].age"><br/>
    <input type="submit" value="提交">
</form>

VO物件:

public class VO {
		private List<User> userList;
  	// 以下省略getter、setter和toString方法
}

Controller:

@RequestMapping(value="/quick14")
@ResponseBody
public void save14(VO vo) throws IOException {
    System.out.println(vo);
}

12.6 獲得List型別的引數II

在我們的開發中,經常使用到ajax實現的非同步請求。

那麼,當使用ajax提交時,可以指定contentType為json形式,

那麼在方法引數位置使用**@RequestBody**可以直接接收集合資料而無需使用VO進行包裝

例如:

前端:

<script>
    var userList = new Array();
    userList.push({username:"zhangsan",age:18});
    userList.push({username:"lisi",age:28});
  
    $.ajax({
        type:"POST",
        url:"${pageContext.request.contextPath}/user/quick15",
        data:JSON.stringify(userList),
        contentType:"application/json;charset=utf-8"
    });
</script>

ajax的屬性:

contentType:傳送給伺服器的資料型別

​ 當傳送的資料格式為json時,設定編碼型別為:“application/json; charset=utf-8”

dataType:預期伺服器返回的資料型別

​ 例如:dataType: “json”

Controller:

@RequestMapping(value="/quick15")
@ResponseBody
public void save15(@RequestBody List<User> userList) throws IOException {
    System.out.println(userList);
}

12.7 靜態資源訪問的開啟

當有靜態資源需要被載入時,比如JS、CSS、Image、html、mp3、mp4等,你會發現載入不了。

  • 原因:

    SpringMVC的前端控制器DispatcherServlet的url-pattern配置的是/,代表對所有的資源都進行過濾操作,除了JSP頁面以外

  • 解決方案:

    我們可以通過以下兩種方式指定放行靜態資源:

    <!--放行靜態資源方式1-->
    <mvc:resources mapping="/js/**" location="/js/"/>
    <mvc:resources mapping="/img/**" location="/img/"/>
    <!--放行靜態資源方式2 推薦-->
    <mvc:default-servlet-handler/>
    

12.8 解決請求亂碼問題

當post請求時,中文資料會出現亂碼,我們可以設定一個過濾器來進行編碼的過濾:

在web.xml中配置:

<!-- 2.註冊過濾器 -->
<filter>
  <filter-name>encodingFilter</filter-name>
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  <!-- 設定字符集引數,引數名必須用encoding -->
  <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
</filter>
<!-- 攔截對映配置,一定要用/*,過濾所有請求,包括.jsp檔案 -->
<filter-mapping>
  <filter-name>encodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Tomcat8 以後tomcat的預設編碼已經不是ISO-8859-1,而是改成了UTF-8,我們不需要再對get請求進行轉碼了。

12.9 引數繫結註解

@RequestParam

當請求的引數名稱與Controller的處理方法引數名稱不一致時,就需要通過@RequestParam註解顯示的繫結。

  • 屬性:

    value 與請求引數匹配

    required 此在指定的請求引數是否必須包括,預設是true,提交時如果沒有此引數則報錯

    defaultValue 指定預設值。當沒有指定請求引數時,則使用指定的預設值賦值

例如:

<form action="${pageContext.request.contextPath}/quick16" method="post">
    <input type="text" name="name"><br>
    <input type="submit" value="提交"><br>
</form>
@RequestMapping(value="/quick16")
@ResponseBody
public void save16(@RequestParam(value="name",required = false,defaultValue = "itcast") String username){
    System.out.println(username);
}

12.10 RestFul風格引數

Restful是一種軟體架構風格、設計風格,而不是標準,只是提供了一組設計原則和約束條件。主要用於客戶端和伺服器互動類的軟體

基於這個風格設計的軟體可以更簡潔,更有層次,更易於實現快取機制等。

通過不同的請求方式,使同一個url,實現不同的功能

Restful風格的請求是使用“url+請求方式”表示一次請求目的的,HTTP 協議裡面四個表示操作方式的動詞如下:(常用的四種)

  • GET:用於獲取資源
  • POST:用於新建資源
  • PUT:用於更新資源
  • DELETE:用於刪除資源

注意:對於資料庫的操作,不要使用@RequestMapping,因為這樣表示所有型別的請求都能訪問到該處理方法。這樣不安全,所以Restful風格的註解要求:

查詢操作使用:@GetMapping

新增操作使用:@PostMapping

更新操作使用:@PutMapping

刪除操作使用:@DeleteMapping

例如:

  • /user/1 以GET方式請求 : 得到 id = 1 的 user
  • /user/1 以DELETE方式請求: 刪除 id = 1 的 user
  • /user/1 以PUT方式請求: 更新 id = 1 的 user
  • /user 以POST方式請求: 新增 user

上述url地址/user/1中的1就是要獲得的請求引數值,在SpringMVC中可以使用佔位符進行引數繫結,並且我們可以為Controller處理方法設定請求方式,前端不同的請求方式會去找對應於該請求方式的處理方法(@GetMapping、@PostMapping等等…)

地址/user/1可以寫成/user/{id},佔位符{id}對應的就是1的值。在業務方法中我們可以使用==@PathVariable==註解進行佔位符的匹配獲取工作:

例如:

get請求url:http://localhost:8080/itheima_springmvc1/quick17/zhangsan

@GetMapping(value="/quick17/{name}")
@ResponseBody
public void save17(@PathVariable("name") String username){
    System.out.println(username);
}

注意:所有的位址列請求預設都是GET方式請求的

@PathVariable屬性:

value 與請求引數匹配

required 此在指定的請求引數是否必須包括,預設是true,提交時如果沒有此引數則報錯

技巧:如何以一個controller處理方法,對映不同的url地址?

現在有如下頁面需要跳轉:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-DnZo3A8w-1602517447310)(G:\學習筆記\SpringMVC學習筆記\image\12.PNG)]

我們怎麼樣只寫一個controller處理方法,能夠跳轉到/level1/1 /level1/2 /level1/3?

答案是:使用@PathVariable註解,進行請求引數匹配

@RequestMapping("/level1/{id}")
public String toLevel1(@PathVariable("id") String id) {
    return "views/level1/" + id;
}

12.11 自定義型別轉換器

SpringMVC 預設已經提供了一些常用的型別轉換器,例如客戶端提交的字串轉換成int型進行引數設定。
但是不是所有的資料型別都提供了轉換器,沒有提供的就需要自定義轉換器.

  • 例如:日期型別的資料:

    在springmvc中預設只能對"yyyy/MM/dd"格式字串進行轉換成Data型別

    但我們最常用的還是"yyyy-MM-dd" 格式字串,就需要自定義轉換器。

    否則,會報出400錯誤。

  • 自定義型別轉換器的開發步驟

    1. 定義轉換器類實現Converter介面

      // 實現Converter<String, 要轉換成的型別>介面
      public class DateConverter implements Converter<String, Date> {
          // 重寫convert方法
        	public Date convert(String dateStr) {
              //將日期字串轉換成日期物件 返回
              SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
              Date date = null;
              try {
                  date = format.parse(dateStr);
              } catch (ParseException e) {
                  e.printStackTrace();
              }
              return date;
          }
      }
      
    2. 在配置檔案中宣告轉換器,轉換器工廠中可以宣告多個轉換器

      <!-- 宣告轉換器 -->
      <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
      		<property name="converters">
        			<list>
            		<bean class="com.anuo.converter.DateConverter"/>
              </list>
        	</property>
      </bean>
      
    3. <annotation-driven>中引用轉換器

      <!-- mvc的註解驅動 -->
      <mvc: annotation-driven conversion-service="conversionService"/>
      
  • 轉換器定義好之後,進行測試

    請求URL:http://localhost:8080/itheima_springmvc1/quick18

    Controller方法:

    @RequestMapping("/quick18")
    @ResponseBody
    public void save18(Date date) {
       System.out.println(date);
    }
    

    發現已經不會出現400錯誤了。

  • 總結:

    其實在工作中不常用到自定義型別轉換器,SpringMVC內建的型別轉換器往往夠用。

    你想想Date型別的資料我們往往是實體類的屬性,

    那麼我們可以在實體類中Date型別的屬性中使用:

    1. 入參格式化,將前端的"yyyy-MM-dd HH:mm:ss"格式字串轉換為Date型別封裝到屬性中:

      @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
      private Date date;
      
    2. 出參格式化,將Date型別轉換為"yyyy-MM-dd HH:mm:ss"格式字串返回前端

      @JsonFormat(
          pattern = "yyyy-MM-dd HH:mm:ss",
          timezone = "GMT+8"
      )
      private Date date;
      

      為什麼需要timezone=“GMT+8”?

      因為,@JsonFormat是Jackson所帶的註解。

      Jackson在序列化時間時是按照國際標準時間GMT進行格式化的,而在國內預設時區使用的是CST時區,兩者相差8小時。

      如果不設定timezone="GMT+8"的話,在Jackson進行格式化的時候,會將CST時區的時間早8個小時。

      @JsonFormat 註解不是 Spring 自帶的註解,所以使用該註解前需要新增 jackson 相關的依賴包。

      當然,如果是 SpringBoot 專案就不需要自己手動新增依賴了,因為在 spring-boot-start-web 下已經包含了 jackson 相關依賴

12.12 獲取Servlet相關API

SpringMVC支援使用原始ServletAPI物件作為控制器方法的引數進行注入,常用的物件如下:

HttpServletRequest

HttpServletResponse

HttpSession

@RequestMapping(value="/quick19")
@ResponseBody
public void save19(HttpServletRequest request, HttpServletResponse response, HttpSession session){
		System.out.println(request);
		System.out.println(response);
		System.out.println(session);
}

12.13 獲取請求頭資訊

使用==@RequestHeader可以獲得請求頭資訊==

相當於web階段學習的request.getHeader(name)

  • @RequestHeader註解的屬性如下:

    value:請求頭的名稱

    required:是否必須攜帶此請求頭,預設為true

@RequestMapping(value="/quick20")
@ResponseBody
public void save20(@RequestHeader(value = "User-Agent",required = false) String user_agent){
		System.out.println(user_agent);
}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

使用@CookieValue可以獲得指定Cookie的值

  • @CookieValue註解的屬性如下:

    value:指定cookie的名稱

    required:是否必須攜帶此cookie

@RequestMapping(value="/quick21")
@ResponseBody
public void save21(@CookieValue(value = "JSESSIONID") String jsessionId){
		System.out.println(jsessionId);
}

12.14 檔案上傳

1. 檔案上傳客戶端三要素

  • 表單項type=“file”

  • 表單的提交方式是post

  • 表單的enctype屬性是多部分表單形式:enctype=“multipart/form-data”

<form action="${pageContext.request.contextPath}/user/quick22" method="post"
enctype="multipart/form-data">
    名稱<input type="text" name="username"><br/>
    檔案1<input type="file" name="uploadFile"><br/>
    <input type="submit" value="提交">
</form>

2. 檔案上傳的原理

  • 當form表單修改為多部分表單時,request.getParameter()將失效

  • enctype="application/x-www-form-urlencoded"時,form表單的正文內容格式是:

    key=value&key=value&key=value 【這是預設的,不需要設定enctype屬性值】

  • 當form表單的enctype取值為multipart/form-data時,請求正文內容就變成多部分形式:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-EJ7xsTZK-1602517447312)(G:\學習筆記\SpringMVC學習筆記\image\10.PNG)]

3. 單檔案上傳步驟

  1. 匯入fileupload和io的依賴

    <!-- 檔案上傳 -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.3</version>
    </dependency>
    
  2. 在spring-mvc.xml配置檔案上傳解析器

    <!--配置檔案上傳解析器,注意id必須為multipartResolver,否則報錯-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    		<!-- 上傳檔案的編碼型別 -->
      	<property name="defaultEncoding" value="UTF-8"/>
      	<!-- 上傳單個檔案的大小 -->
    		<property name="maxUploadSize" value="5242800"/>
      	<!-- 上傳檔案總大小 -->
      	<property name="maxUploadSizePerFile" value="5242800"/>
    </bean>
    
  3. 編寫檔案上傳程式碼

    前端表單:

    <form action="${pageContext.request.contextPath}/user/quick22" method="post"
    enctype="multipart/form-data">
        名稱<input type="text" name="username"><br/>
        檔案1<input type="file" name="uploadFile"><br/>
        <input type="submit" value="提交">
    </form>
    

    controller:檔案資料在處理方法中需要用MutipartFile型別引數去接收

    @RequestMapping(value="/quick22")
    @ResponseBody
    public void save22(String username, MultipartFile uploadFile) throws IOException {
        System.out.println(username);
      	// 獲得上傳檔案原本的名稱
      	String originalFilename = uploadFile.getOriginalFilename();
      	// 儲存檔案
      	uploadFile.transferTo(new File("C:\\upload\\" + originalFilename));
    }
    

4. 多檔案上傳

和單檔案上傳的步驟基本一致:

  1. 只需要將頁面修改為多個檔案上傳項

    上傳項的name相同,後端就用陣列引數接收

    上傳項的name不同,後端就用多個MultipartFile型別引數接收

  2. 我們演示上傳項的name相同時,將方法引數MultipartFile型別修改為MultipartFile[]即可

前端表單:

<form action="${pageContext.request.contextPath}/user/quick23" method="post"
enctype="multipart/form-data">
    名稱<input type="text" name="username"><br/>
    檔案1<input type="file" name="uploadFile"><br/>
    檔案2<input type="file" name="uploadFile"><br/>
    <input type="submit" value="提交">
</form>

controller:

@RequestMapping(value="/quick23")
@ResponseBody
public void save23(String username, MultipartFile[] uploadFile) throws IOException {
    System.out.println(username);
    for (MultipartFile multipartFile : uploadFile) {
    	String originalFilename = multipartFile.getOriginalFilename();
    	multipartFile.transferTo(new File("C:\\upload\\"+originalFilename));
    }
}

12.15 知識點總結

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-YX8I0bQ5-1602517447313)(G:\學習筆記\SpringMVC學習筆記\image\11.PNG)]

11. 接收請求引數和資料回顯

11.1 接收請求引數

  • 提交的域名稱和處理方法的引數名一致的情況

  • 提交的域名稱和處理方法的引數名不一致的情況

    @RequestParam(“username”)

規範:無論兩名稱是否一致都使用@RequestParam("請求引數名稱"),這樣能夠清晰的告訴閱讀者這是前端傳過來的引數

規範:無論兩名稱是否一致都使用@RequestParam(“請求引數名稱”),這樣能夠清晰的告訴閱讀者這是前端傳過來的引數

13. JSON

前後端分離時代:不再使用jsp

後端部署後端,提供介面:@GetMapping("/hello")

​ | JSON

前端獨立部署,負責渲染後端的資料

13.1 Controller返回JSON資料

Jackson

  • Jackson是目前比較好的json解析工具,我們之前學習的是阿里巴巴的Fastjson

這裡我們使用Jackson,使用步驟:前提先搭建好springmvc的環境

  1. pom.xml中需要匯入Jar包依賴:
<!-- Jackson -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.11.1</version>
</dependency>
  1. 在spring配置檔案中JSON亂碼問題配置:springmvc-servlet.xml

    <!-- JSON亂碼問題配置    -->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </bean>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="failOnEmptyBeans" value="false"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    

    當然,上面這種解決JSON亂碼問題的方式比較簡便,屬於全域性配置。

    還有一種瞭解即可:在@RequestMapping註解的produces屬性中設定:

    @RequestMapping(value="/j1", produces="application/json;charset=utf-8")

    類似於早期servlet中的:

    response.setContentType("application/json;charset=utf-8");

  2. 實體類:User

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private int id;
        private String name;
        private int age;
    }
    
  3. 控制器:UserController

    @Controller
    public class UserController {
    
        @RequestMapping(value = "/j1", produces = "application/json;charset=utf-8")
        @ResponseBody // 它就不會走檢視解析器,會直接返回一個json字串
        public String json1() throws JsonProcessingException {
            // jackson, objectMapper
            ObjectMapper mapper = new ObjectMapper();
    
            // 建立一個物件
            User user = new User(1, "陳健", 23);
            String str = mapper.writeValueAsString(user);
            return str;
        }
    }
    

不經過檢視解析器跳轉的兩種方法:

  1. 在控制器類上用@Controller註解的情況下:

    ​ 在對應處理方法上新增註解@ResponseBody

  2. 在控制器類上用@RestController註解:

    ​ 類中的所有處理方法的返回值都不經過檢視解析器,直接返回字串顯示

Fastjson

  1. 匯入Jar包依賴:

    <!-- FastJson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.72</version>
    </dependency>
    
  2. 序列化:Java物件轉換為JSON字串

    JSON.toJSONString(Java物件或陣列或集合) // 返回String
    
  3. 反序列化:JSON字串轉換為Java物件

    JSON.parseObject(json, Employee.class); // 返回指定的類物件
    
    JSON.parseArray(json, Employee.class); // 返回指定類物件的集合
    

14 SSM框架整合

建立資料庫ssmbuild和表books

CREATE DATABASE ssmbuild;
USE ssmbuild;
CREATE TABLE `books`(
`bookID` INT NOT NULL AUTO_INCREMENT COMMENT '書id',
`bookName` VARCHAR(100) NOT NULL COMMENT '書名',
`bookCounts` INT NOT NULL COMMENT '數量',
`detail` VARCHAR(200) NOT NULL COMMENT '描述',
KEY `bookID`(`bookID`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES
(1,'Java',1,'從入門到放棄'),
(2,'MySQL',10,'從刪庫到跑路'),
(3,'Linux',5,'從進門到進牢');

14.1 基本環境搭建

  1. 第一步:匯入jar包依賴、解決靜態資源匯出問題

    <!-- 依賴:junit、資料庫驅動、連線池、servlet、jsp、mybatis-spring、spring -->
    <dependencies>
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- 資料庫驅動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <!-- 資料庫連線池:c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.5</version>
        </dependency>
        <!-- Servlet - Jsp -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
    
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
        </dependency>
    
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!-- Mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>
        <!-- Mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.5</version>
        </dependency>
        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>
    </dependencies>
    
    <!-- 靜態資源匯出問題 -->
    <build>
      <!-- 防止Maven資源過濾的問題 -->
      <resources>
        <resource>
          <directory>src/main/java</directory>
          <includes> <include>**/*.properties</include>
            <include>**/*.xml</include>
          </includes>
          <filtering>false</filtering>
        </resource>
        <resource>
          <directory>src/main/resources</directory>
          <includes> <include>**/*.properties</include>
            <include>**/*.xml</include>
          </includes>
          <filtering>false</filtering>
        </resource>
      </resources>
    </build>
    
  2. 建立基本結構和配置框架

    database.properties

    jdbc.driver=com.mysql.jdbc.Driver
    # 如果使用的是MySQL8.0+,需要增加一個時區的配置: &serverTimezone=Asia/Shanghai
    jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useUnicode=true&characterEncoding=utf8
    jdbc.username=root
    jdbc.password=chenjian123
    

    如果使用的是MySQL8.0+,需要在url增加一個時區的配置: &serverTimezone=Asia/Shanghai

隱藏域

非表單資料Restful風格

15. Ajax

頁面非同步重新整理

ES6更安全的語法:let代替var

例如:for(var i;i<10;i++) {…}中的i在for語句結束後的程式碼中依舊可以使用

for(let i;i<10;i++) {…}中的i和Java中一樣,for語句結束後將不能使用

16. 攔截器

16.1 概述

  • SpringMVC的處理器攔截器類似於Servlet開發中的過濾器Filter,用於對處理器進行預處理和後處理。開發者可以自己定義一些攔截器來實現特定的功能。

16.2 過濾器與攔截器的區別

攔截器是AOP思想的具體應用

不同點

過濾器

  • servlet規範中的一部分,任何java web工程都可以使用

  • 在url-pattern中配置了/*之後,可以==對所有要訪問的資源進行攔截==

攔截器

  • 攔截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用

  • 攔截器==只會攔截訪問的控制器方法==, 如果訪問的是jsp/html/css/image/js是不會進行攔截的

相同點

攔截器和過濾器都可以有多個,執行順序取決於在web.xml中的配置順序

17. 檔案上傳

檔案上傳是專案開發中最常見的功能之一 ,springMVC 可以很好的支援檔案上傳,但是SpringMVC上下文中預設沒有裝配MultipartResolver,因此預設情況下其不能處理檔案上傳工作。如果想使用Spring的檔案上傳功能,則需要在上下文中配置MultipartResolver。

前端表單要求:為了能上傳檔案,必須將表單的method設定為POST,並將enctype設定為

multipart/form-data。只有在這樣的情況下,瀏覽器才會把使用者選擇的檔案以二進位制資料傳送給伺服器;

對錶單中的 enctype 屬性做個詳細的說明:

application/x-www=form-urlencoded:預設方式,只處理表單域中的 value 屬性值,採用這種編碼方式的表單會將表單域中的值處理成 URL 編碼方式。

multipart/form-data:這種編碼方式會以二進位制流的方式來處理表單資料,這種編碼方式會把檔案域指定檔案的內容也封裝到請求引數中,不會對字元編碼。

text/plain:除了把空格轉換為 “+” 號外,其他字元都不做編碼處理,這種方式適用直接通過表單傳送郵件。

  1. 匯入jar包依賴

    <!-- 檔案上傳 -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.4</version>
    </dependency>
    <!-- 匯入高版本的servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
    
  2. spring配置檔案中配置

    <!-- 檔案上傳配置,id必須為multipartResolver,否則會404錯誤 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 請求的編碼格式,必須和jSP的pageEncoding屬性一致,以便正確讀取表單的內容,預設為ISO-8859-1 -->
        <property name="defaultEncoding" value="utf-8"/>
        <!-- 上傳檔案大小上限,單位為位元組(10485760=10M) -->
        <property name="maxUploadSize" value="10485760"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>
    

相關文章