day01-SpringMVC基本介紹-01

2023-02-04 06:00:30

SpringMVC介紹-01

1.離線檔案

解壓 spring-5.3.8-dist.zip檔案。

位置:spring-framework-5.3.8/docs/reference/html/web.html#spring-web

image-20230202181914295

2.SpringMVC基本介紹

2.1SpringMVC特點&概述

  1. SpringMVC 從易用性,效率上都比曾經流行的 Struts2 更好

  2. SpringMVC 是 WEB 層框架:SpringMVC接管了 web層元件,比如控制器,檢視,檢視解析,返回給使用者的資料格式,同時支援 MVC 的開發模式/開發架構

  3. SpringMVC 通過註解,讓 POJO 成為控制器,不需要繼承類或者實現介面

  4. SpringMVC 採用低耦合的元件設計方式,具有更好的拓展和靈活性

  5. 支援 REST 格式的 URL 請求

  6. SpringMVC 是基於 Spring 的,它的核心包為 spring-webmvc-xxx.jar 和 spring-web-xxx.jar

2.2Spring SpringMVC SpringBoot的關係

  1. SpringMVC 只是 Spring 處理 WEB 層的一個模組/元件,SpringMVC 的基石是 Servlet
  2. SpringBoot 是為了簡化開發者的使用而推出的一個框架(約定優於設定,簡化了Spring的設定流程),它包含很多元件/框架,Spring 就是最核心的內容之一,也包含了 SpringMVC
  3. 三者之間的關係是:Spring Boot > Spring > SpringMVC

3.SpringMVC的快速入門

3.1需求說明

需求說明:使用SpringMVC,完成一個最基本的測試案例——登入案例

image-20230202185633326

3.2SpringMVC登入流程分析

3.3程式碼實現

  1. 建立Java專案,新增 web支援並設定 tomcat

    image-20230202193635101
  2. 匯入SpringMVC 開發需要的jar包

    image-20230202194018945
  3. src目錄下建立spring的容器檔案applicationContext-mvc.xml(名稱隨意)

    image-20230202204606328
  4. 在WEB-INF/web.xml檔案中設定前端控制器(中央控制器)

    <!--設定前端控制器/中央控制器/分發控制器,負責處理所有的應用請求-->
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <!--設定屬性 contextConfigLocation,指定 DispatcherServlet 去操作的 spring容器組態檔-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext-mvc.xml</param-value>
        </init-param>
        <!--在web專案啟動時,就自動的載入 DispatcherServlet範例,1表示載入的順序號-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <!--1.設定的url-pattern為 /,表示使用者的請求都經過 DispatcherServlet
            2.這樣設定也支援 rest 風格的url請求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
  5. web目錄下建立login.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>登入</title>
    </head>
    <body>
    <h3>登入頁面</h3>
    <%--
        action="login": 這樣寫實際上是相對路徑,而相對路徑是以當前的瀏覽器位址列而言。
        因此實際上這裡表示的 url 是 http://localhost:8080/web工程路徑/login
    --%>
    <form action="login">
        u:<input name="username" type="text"/> <br/>
        p:<input name="password" type="password"/> <br/>
        <input type="submit" value="登入"/>
    </form>
    </body>
    </html>
    

    關於web工程路徑,詳見 Javaweb--day18-web工程路徑

  6. 建立 src/com/li/web/UserServlet.java

    package com.li.web;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    /**
     * @author 李
     * @version 1.0
     * 1.如果我們使用了SpringMVC,在一個類上標識 @Controller
     * 2.表示將該類視為一個控制器,注入到容器
     * 3.比原生的 servlet方便很多
     */
    @Controller
    public class UserServlet {
        /**
         * 編寫login方法,響應使用者請求
         * 1.login()方法用於響應使用者的登入請求
         * 2.@RequestMapping(value = "/login")
         *    類似於我們原生的Servlet設定的url-pattern,不同的是這裡是給方法設定url對映
         * 3.當用戶在瀏覽器位址列輸入 http://localhost:8080/web工程路徑/login
         *    就能夠存取當到 login()方法
         * 4.return "login_ok"; 表示返回結果給檢視解析器(InternalResourceViewResolver),
         *    檢視解析器會根據設定,來決定提交到哪一個頁面,如:
         * <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
         *    <property name="prefix" value="/WEB-INF/pages/"/>
         *    <property name="suffix" value=".jsp"/>
         * </bean>
         * 根據上面的設定,return "login_ok"; 就是轉發到 /WEB-INF/pages/login_ok.jsp
         *
         * @return
         */
        @RequestMapping(value = "/login")
        public String login() {
            System.out.println("login ok...");
            return "login_ok";
        }
    }
    
  7. 建立web/WEB-INF/pages/login_ok.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>登入成功</title>
    </head>
    <body>
    <h1>恭喜,登入成功!</h1>
    </body>
    </html>
    
  8. 設定容器檔案applicationContext-mvc.xml

    <!--指定掃描的包-->
    <context:component-scan base-package="com.li.web"/>
    
    <!--設定檢視解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--設定屬性 suffix(字尾) 和 prefix(字首)-->
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    
  9. 整體的檔案位置如下:

    image-20230202212119630
  10. 啟動tomcat,存取 http://localhost:8080/springmvc/login.jsp,存取成功:

    image-20230202211845571
  11. 點選登入,成功存取到login_ok.jsp

    image-20230202212014130

3.4注意事項和細節說明

  1. 這裡的UserServlet 需要註解成一個@Controller,我們稱之為一個Handler處理器

  2. 在UserServlet 指定 url 時,value 可以省略(注意是省略「value」字元,不是省略值)

    image-20230202212828452
  3. 關於SpringMVC 的 DispatcherServlet 的組態檔,如果不在web.xml中指定spring組態檔,則預設在/WEB-INF/目錄下找名為 springDispatcherServlet-servlet.xml 的spring組態檔。

    image-20230202215055842

    因此,我們將之前的spring容器檔案移動到/web-INF/目錄下,並註釋掉web.xml設定的<init-param>,然後將容器檔案重新命名為 springDispatcherServlet-servlet.xml,重啟tomcat,依然可以成功執行。

4.SpringMVC執行流程

5.@RequestMapping

5.1基本使用

@RequestMapping註解可以指定 控制器(處理器) 的某個方法的請求url

image-20230202212828452

5.2@RequestMapping其他使用方式

5.2.1修飾方法和類

@RequestMapping註解可以修飾方法,還可以修飾類。

當同時修飾類和方法時,請求的url就是組合形式:/類請求值/方法請求值

例子

(1)UserHandler.java:

package com.li.web;

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

/**
 * @author 李
 * @version 1.0
 */
@RequestMapping(value = "/user")
@Controller  //UserHandler就是一個處理器/控制器,注入到spring容器
public class UserHandler {
    /**
     * 1.method = RequestMethod.POST 表示請求buy方法必須是post請求
     * 2.RequestMethod 四個常用的選項 :GET, POST, PUT, DELETE
     * 3.如果沒有設定 RequestMethod,SpringMVC控制器預設支援 get和 post兩種方式
     * 4.buy()方法對應的完整請求url = http://ip:port/web工程路徑/user/buy
     * @return
     */
    @RequestMapping(value = "/buy", method = RequestMethod.POST)
    public String buy() {
        System.out.println("購買商品");
        return "success";
    }
}

(2)request.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>購買商品</title>
</head>
<body>
<h1>購買商品</h1>
<%--
buy()方法對應的完整請求 url = http://ip:port/web工程路徑/user/buy
--%>
<form action="user/buy" method="post">
    購買人:<input type="text" name="username"/><br/>
    購買量:<input type="text" name="nums"/><br/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

(3)success.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>操作成功</title>
</head>
<body>
<h1>恭喜,操作成功!</h1>
</body>
</html>

在瀏覽器中存取 http://localhost:8080/springmvc/request.jsp,點選提交按鈕,結果如下:

image-20230203191741074 image-20230203191828499

5.2.2指定請求方式

  1. @RequestMapping 可以指定請求的方式(post/get/put/delete...),請求方式要和指定方式一致,否則報錯:

    image-20230203192822882
  2. SpringMVC 控制器預設支援get 和 post兩種請求方式,即如果沒有指定 method,可以接收 get 和 post請求

5.2.3指定params和headers,支援簡單表示式

  1. param1:表示請求必須包含名為 param1 的請求引數
  2. !param1:表示請求不能包含名為 param1 的請求引數
  3. param1 != value1:表示請求包含名為 param1 的請求引數,但其值不能為 value1
  4. {"param1 = value1", "param2"}:請求必須包含名為 param1 和 param2 的兩個請求引數,且 param1的值必須為 value1

應用範例

(1)修改UserHandler.java,增加方法

//...
@RequestMapping(value = "/user")
@Controller  
public class UserHandler {
    //...

    /**
     * 1.params = "bookId" 表示請求該方式時,必須給一個名為 bookId的引數
     * 2.search(String bookId){} 表示請求目標方法時,
     *  攜帶的 bookId引數的值會被填充到目標方法的同名形參中
     * @param bookId
     * @return
     */
    @RequestMapping(value = "/find", params = "bookId", method = RequestMethod.GET)
    public String search(String bookId) {
        System.out.println("查詢書籍 bookId=" + bookId);
        return "success";
    }
}

(2)request.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>購買商品</title>
</head>
<body>
<h1>演示params的使用</h1>
<a href="user/find?bookId=100">查詢書籍</a>
</body>
</html>

(3) success.jsp 不變。

(4)redeployTomcat,在瀏覽器位址列存取:http://localhost:8080/springmvc/request.jsp,點選查詢書籍超連結,結果如下:

image-20230203203244672 image-20230203203931702

(5)修改UserHandler.java,指定引數的值=100。

image-20230203204158727

(6)修改request.jsp,修改傳送的值為200.

(7)redeployTomcat,重新範文request.jsp,點選超連結,這裡可以看到出現異常,因為傳送的值和方法指定的值不一樣。

image-20230203204520955

5.2.4支援Ant 風格資源地址

  1. ?:匹配檔名中的一個字元
  2. *:匹配檔名中的任意字元,長度任意
  3. **:匹配多層路徑
  4. Ant 風格的 url 地址舉例:
    • /user/*/createUser:匹配 /user/aaa/createUser、/user/bbb/createUser 等 URL
    • /user/**/createUser:匹配 /user/createUser、/user/aaa/bbb/createUser 等 URL
    • /user/createUser??: 匹配 /user/createUserab、/user/createUsercd 等 URL

應用範例

(1)修改UserHandler.java,增加方法:

//...
@RequestMapping(value = "/user")
@Controller  
public class UserHandler {
    //...
    
    /**
     * 要求:可以匹配 /user/message/aa, /user/message/aa/bb/cc
     *  @RequestMapping(value = "/message/**")
     *  表示可以匹配多層的路徑
     * @return
     */
    @RequestMapping(value = "/message/**")
    public String im(){
        System.out.println("傳送訊息");
        return "success";
    }
}

(2)修改request.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>購買商品</title>
</head>
<body>
<h1>演示 Ant 風格的請求資源方式</h1>
<a href="user/message/aa">傳送訊息 1</a><br>
<a href="user/message/aa/bb/cc">傳送訊息 2</a><br>
</body>
</html>

(3) success.jsp 不變。

(4)redeployTomcat,在瀏覽器位址列存取:http://localhost:8080/springmvc/request.jsp,分別點選兩個超連結,都能成功存取方法,並跳轉到success.jsp

image-20230203211052829 image-20230203211132423 image-20230203211202176

5.2.5可配合@PathVariable對映URL繫結的預留位置

  1. @RequestMapping 還可以配合 @PathVariable(路徑變數) 對映 URL 繫結的預留位置
  2. 這樣就不需要在url位址列上帶引數名了,更加簡潔明瞭

例子

request.jsp頁面如下,其中 kristina 和 300 皆為引數值

<h1>預留位置的演示</h1>
<a href="user/reg/kristina/300">預留位置的演示</a>

(1)修改UserHandler.java,增加方法,注意@PathVariable("username") 不能少

//...
@RequestMapping(value = "/user")
@Controller 
public class UserHandler {
    /**
     * 我們希望目標方法獲取到username和 userid
     * 前端頁面為:<a href="user/reg/kristina/300">預留位置的演示</a>
     * 1. value = "/reg/{username}/{userid}"
     *    表示 kristina=>{username} ,300=>{userid}
     * 2.通過 @PathVariable 將變數賦給對應的形參
     */
    @RequestMapping(value = "/reg/{username}/{userid}")
    public String register(@PathVariable("username") String name,
                           @PathVariable("userid") int id) {
        System.out.println("接收到的引數--username=" + name + "--userid=" + id);
        return "success";
    }
}

(2)success.jsp不變

(3)redeployTomcat,存取 http://localhost:8080/springmvc/request.jsp,點選超連結,成功存取到success.jsp,後臺輸出如下:

image-20230203213818006

5.2.6注意事項和使用細節

  1. 對映的URL不能重複,否則報錯:

    Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'userHandler' method 
    com.li.web.UserHandler#buy()
    to {POST [/user/buy]}: There is already 'userHandler' bean method
    
  2. 各種請求的簡寫形式

    @RequestMapping(value="/buy",method=RequestMethod.POST) 等價於 @PostMapping(value="buy")

    以此類推,還有 @GetMapping@PostMapping@PutMapping@DeleteMapping

  3. 如果我們確定表單或者超連結會提交某個欄位資料,比如email,要求提交的引數名和目標方法的引數名保持一致。

    例如:

    /**
     * hello3(String email){} 如果請求引數有email=xx,就會將傳遞的引數值賦給String email
     * 但是要求名稱保持一致!如果不一致,那麼接收不到資料,而是null
     * @param email
     * @return
     */
    @GetMapping(value = "/hello3")
    public String hello3(String email) {
        System.out.println("hello3= " + email);
        return "success";
    }
    
    image-20230203220142357

5.2.7練習

編寫一個表單,以Post方式提交表單資訊,後端編寫ComputerHandler,可以接收到表單資訊

image-20230203220422270

computer.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>hw-電腦資訊</title>
</head>
<body>
<h1>電腦資訊</h1>
<form action="computer/info" method="post">
    品牌:<input type="text" name="brand"/><br/>
    價格:<input type="text" name="price"/><br/>
    數量:<input type="text" name="nums"/><br/>
    <input type="submit" value="提交">
</form>
</body>
</html>

ComputerHandler:

package com.li.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author 李
 * @version 1.0
 */
@RequestMapping("/computer")
@Controller
public class ComputerHandler {
    //注意接收的引數名要和info方法的形參名一致
    @PostMapping("/info")
    public String info(String brand, String price, String nums) {
        System.out.println("brand=" + brand +
                " price=" + price + " nums=" + nums);
        return "success";
    }
}

redeployTomcat,存取:http://localhost:8080/springmvc/computer.jsp,輸入資訊,點選提交表單。

image-20230203221946716

後臺輸出:

image-20230203222022381

5.3Postman介面測試工具