1. 程式人生 > 其它 >SpringMVC基礎知識

SpringMVC基礎知識

1、SpringMVC的介紹

  Spring Web MVC是構建在Servlet API上的原始Web框架,從一開始就包含在Spring Framework中。 正式名稱 “Spring Web MVC,” 來自其源模組(spring-webmvc)的名稱,但它通常被稱為“Spring MVC”。

  SpringMVC是Spring框架的一部分,是基於java實現的一個輕量級web框架。

  學習SpringMVC框架最核心的就是DispatcherServlet的設計,掌握好DispatcherServlet是掌握SpringMVC的核心關鍵。

2、SpringMVC的優點

  1)清晰的角色劃分:控制器(controller)、驗證器(validator)、命令物件(command obect)、表單物件(form object)、模型物件(model object)、Servlet分發器(DispatcherServlet)、

    處理器對映(handler mapping)、試圖解析器(view resoler)等等。每一個角色都可以由一個專門的物件來實現。

  2)強大而直接的配置方式:將框架類和應用程式類都能作為JavaBean配置,支援跨多個context的引用,例如,在web控制器中對業務物件和驗證器validator的引用。

  3)可適配、非侵入:可以根據不同的應用場景,選擇合適的控制器子類(simple型、command型、from型、wizard型、multi-action型或者自定義),而不是一個單一控制器(比如Action/ActionForm)繼承。

  4)可重用的業務程式碼:可以使用現有的業務物件作為命令或表單物件,而不需要去擴充套件某個特定框架的基類。

  5)可定製的繫結(binding)和驗證(validation):比如將型別不匹配作為應用級的驗證錯誤,這可以保證錯誤的值。再比如本地化的日期和數字繫結等等。在其他某些框架中,你只能使用字串表單物件,

    需要手動解析它並轉換到業務物件。

  6)可定製的handler mapping和view resolution:Spring提供從最簡單的URL對映,到複雜的、專用的定製策略。與某些web MVC框架強制開發人員使用單一特定技術相比,Spring顯得更加靈活。

  7)靈活的model轉換:在Springweb框架中,使用基於Map的鍵/值對來達到輕易的與各種檢視技術整合。

  8)可定製的本地化和主題(theme)解析:支援在JSP中可選擇地使用Spring標籤庫、支援JSTL、支援Velocity(不需要額外的中間層)等等。

  9)簡單而強大的JSP標籤庫(Spring Tag Library):支援包括諸如資料繫結和主題(theme)之類的許多功能。他提供在標記方面的最大靈活性。

  10)JSP表單標籤庫:在Spring2.0中引入的表單標籤庫,使用在JSP編寫表單更加容易。

  11)Spring Bean的生命週期:可以被限制在當前的HTTP Request或者HTTP Session。準確的說,這並非Spring MVC框架本身特性,而應歸屬於Spring MVC使用的WebApplicationContext容器。

3、SpringMVC的實現原理

  SpringMVC的MVC模式:

  

  SpringMVC的具體執行流程:

  當發起請求時被前置的控制器攔截到請求,根據請求引數生成代理請求,找到請求對應的實際控制器,控制器處理請求,建立資料模型,

  訪問資料庫,將模型響應給中心控制器,控制器使用模型與檢視渲染檢視結果,將結果返回給中心控制器,再將結果返回給請求者。

  

  1、DispatcherServlet表示前置控制器,是整個SpringMVC的控制中心。使用者發出請求,DispatcherServlet接收請求並攔截請求。
  2、HandlerMapping為處理器對映。DispatcherServlet呼叫HandlerMapping,HandlerMapping根據請求url查詢Handler。
  3、返回處理器執行鏈,根據url查詢控制器,並且將解析後的資訊傳遞給DispatcherServlet
  4、HandlerAdapter表示處理器介面卡,其按照特定的規則去執行Handler。
  5、執行handler找到具體的處理器
  6、Controller將具體的執行資訊返回給HandlerAdapter,如ModelAndView。
  7、HandlerAdapter將檢視邏輯名或模型傳遞給DispatcherServlet。
  8、DispatcherServlet呼叫檢視解析器(ViewResolver)來解析HandlerAdapter傳遞的邏輯檢視名。
  9、檢視解析器將解析的邏輯檢視名傳給DispatcherServlet。
  10、DispatcherServlet根據檢視解析器解析的檢視結果,呼叫具體的檢視,進行試圖渲染
  11、將響應資料返回給客戶端

4、基於XML的Hello_SpringMVC

  1)新增pom依賴

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
    </dependencies>

  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">
    <!--配置DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

      <!--
        關聯springmvc的配置檔案
        此配置檔案的屬性可以不新增,但是需要在WEB-INF的目錄下建立 前端控制器名稱-servlet.xml檔案
      -->

        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
    </servlet>

    <!--匹配servlet的請求,
      /:標識匹配所有請求,但是不會jsp頁面
      /*:攔截所有請求,攔截jsp頁面

    但是需要注意的是,當配置成index.html的時候,會發現請求不到
    原因在於,tomcat下也有一個web.xml檔案,所有的專案下web.xml檔案都需要繼承此web.xml
    在伺服器的web.xml檔案中有一個DefaultServlet用來處理靜態資源,但是url-pattern是/
    而我們在自己的配置檔案中如果添加了url-pattern=/會覆蓋父類中的url-pattern,此時在請求的時候
    DispatcherServlet會去controller中做匹配,找不到則直接報404
    而在伺服器的web.xml檔案中包含了一個JspServlet的處理,所以不過攔截jsp請求
    -->

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--/*和/都是攔截所有請求,/會攔截的請求不包含*.jsp,而/*的範圍更大,還會攔截*.jsp這些請求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

  3)編寫springmvc需要的spring配置檔案,applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

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

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

    <bean id="/hello" class="com.llxazy.controller.HelloController"></bean>
</beans>

  4)HelloController.java

package com.llxazy.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //建立模型和檢視物件
        ModelAndView mv = new ModelAndView();
        //將需要的值傳遞到model中
        mv.addObject("msg","helloSpringMVC");
        //設定要跳轉的檢視,
        mv.setViewName("hello");
        return mv;
    }
}

  5)建立hello.jsp頁面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
  ${msg}
</body>
</html>

  6)配置tomcat,傳送請求

http://localhost:8080/hello

5、基於註解的Hello_SpringMVC

  1)新增pom依賴

  2)編寫web.xml檔案

  3)編寫applicationContext.xml檔案

<?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.llxazy"></context:component-scan>
    <!-- 檢視解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          id="internalResourceViewResolver">
        <!-- 字首 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 字尾 -->
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

  4)編寫HelloController.java

package com.llxazy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController{
    /*
    * @RequestMapping就是用來標識此方法用來處理什麼請求,其中的/可以取消
    * 取消後預設也是從當前專案的根目錄開始查詢,一般在編寫的時候看個人習慣
    * 同時,@RequestMapping也可以用來加在類上,
    * */
    @RequestMapping("/hello")
    public String hello(Model model){
        model.addAttribute("msg","hello,SpringMVC");
        return "hello";
    }
}

  5)編寫hello.jsp

  6)配置tomcat,傳送請求

http://localhost:8080/hello

6、springmvc_helloworld執行流程: 

  1)客戶端傳送請求http://localhost:8080/hello

  2)由tomcat接受到對應的請求

  3)SpringMVC的前端控制器DispatcherServlet接收到所有的請求

  4)檢視請求地址和@RequestMapping註解的哪個匹配,來找到具體的類的處理方法

  5)前端控制器找到目標處理類和方法之後,執行目標方法

  6)方法執行完成之後會有一個返回值,SpringMVC會將這個返回值用檢視解析器進行解析拼接成完整的頁面地址

  7)DispatcherServlet拿到頁面地址之後,轉發到具體的頁面

7、@RequestMapping

  @RequestMapping用來匹配客戶端傳送的請求,可以在方法上使用,也可以在類上使用。

  方法:表示用來匹配要處理的請求

  類上:表示為當前類的所有方法的請求地址新增一個前置路徑,訪問的時候必須要新增此路徑

  在整個專案的不同方法上不能包含相同的@RequestMapping值

  @RequestMapping註解還可以新增很多額外的屬性值,用來精確匹配請求

  @RequestMapping還包含了很多複雜的匹配功能,提供了萬用字元的支援

package com.llxazy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/llxazy")
public class HelloController{

    /*
    * @RequestMapping就是用來標識此方法用來處理什麼請求,其中的/可以取消
    * 取消後預設也是從當前專案的根目錄開始查詢,一般在編寫的時候看個人習慣
    * 同時,@RequestMapping也可以用來加在類上,
    * */
    @RequestMapping("/hello")
    public String hello(Model model){
        model.addAttribute("msg","hello,SpringMVC");
        return "hello";
    }

    /**
     * Request的其他屬性值
     *  value:要匹配的請求
     *  method:限制傳送請求的方式: POST GET
     *  params:表示請求要接受的引數,如果定義了這個屬性,那麼傳送的時候必須要新增引數
     *         params有幾種匹配規則
     *          1、直接寫引數的名稱,param1,param2
     *              params = {"username"}
     *          2、表示請求不能包含的引數,!param1
     *              params = {"!username"}
     *          3、表示請求中需要要包含的引數但是可以限制值 param1=values  param1!=value
     *              params = {"username=123","age"}
     *              params = {"username!=123","age"}
     *  headers:填寫請求頭資訊
     *          chrome:User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36
     *          firefox:User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0
     *
     *  consumers:只接受內容型別是哪種的請求,相當於指定Content-Type
     *  produces:返回的內容型別 Content-Type:text/html;charset=utf-8
     *
     * @return
     */
    @RequestMapping(value = "/hello2",method = RequestMethod.POST)
    public String hello2(){
        return "hello";
    }

    @RequestMapping(value = "/hello3",params = {"username!=123","age"})
    public String hello3(String username){
        System.out.println(username);
        return "hello";
    }

    @RequestMapping(value = "/hello4",headers = {"User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0"})
    public String hello4(){
        return "hello";
    }

    /**
     * @Request包含三種模糊匹配的方式,分別是:
     *  ?:能替代任意一個字元
     *  *: 能替代任意多個字元和一層路徑
     *  **:能代替多層路徑
     * @return
     */
    @RequestMapping(value = "/**/h*llo?")
    public String hello5(){
        System.out.println("hello5");
        return "hello";
    }
}

8、@PathVariable

  @PathVariable註解,此註解就是提供了對佔位符URL的支援,就是將URL中佔位符引數繫結到控制器處理方法的引數中。

package com.llxazy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/llxazy")
public class HelloController{

    @RequestMapping(value = "/pathVariable/{name}")
    public String pathVariable(@PathVariable("name") String name){
        System.out.println(name);
        return "hello";
    }
}