天天看點

SpringMVC基礎第一部分

今日内容

  • SpringMVC認識
  • SpringMVC原理
  • 接收請求參數
  • 參數處理
  • 接收請求頭

第一章 SpringMVC

1. MVC模式(了解)

MVC是一種用于設計建立 Web 應用程式表現層的模式,使用它可以将業務邏輯、資料、界面顯示代碼分離開來.

  • Model(模型): 指的就是資料模型,用于封裝資料
  • View(視圖): 用于資料展示
  • Controller(控制器): 用于程式處理邏輯
web層職責
  1. 接收請求
  2. 調用service
  3. 傳回頁面
  4. 傳回資料
  5. 全局異常處理

2. SpringMVC介紹(了解)

SpringMVC是Spring産品對MVC模式的一種具體實作,它可以通過一套注解,讓一個簡單Java類成為控制器。

SpringMVC将Servlet分離為兩個部分,分别是負責請求轉發的DispatcherServlet和負責調用的JavaBean

第二章 SpringMVC入門案例(重點)

開發一個請求頁面, 向背景發送一個請求, 背景需要在控制台列印一句話, 然後跳轉到一個新的傳回頁面

1. 建立一個新工程, 導入坐标

<dependencies>
  <!--springMVC-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.1.6.RELEASE</version>
  </dependency>
  <!--servlet-->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
  </dependency>
  <!--jsp-->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
  </dependency>
</dependencies>
           

2.提供一個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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--元件掃描-->
    <context:component-scan base-package="cn.com.mryhl.controller"></context:component-scan>
    <!--三大元件-->
    <!--注解驅動:相當于增強版的處理器擴充卡和處理器映射器-->
    <mvc:annotation-driven />
    <!--視圖解析器-->
    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean>
</beans>
           

3. 在web.xml中配置前端控制器

<!--前端控制器-->
<servlet>
   <servlet-name>dispatcherServlet</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
   <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
   </init-param>
</servlet>
<servlet-mapping>
   <servlet-name>dispatcherServlet</servlet-name>
   <!--/ 預設配置,攔截的是除了.jsp之外的所有路徑-->
   <url-pattern>/</url-pattern>
</servlet-mapping>
           

4. 開發請求頁面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--
  User: mr_yhl
  Date: 2020/9/26
  Time: 9:48  
--%>
<html>
    <head>
        <title>SpringMVC請求頁面</title>
    </head>
    <body>
        <a href="${pageContext.request.contextPath}/demoController/demo1" target="_blank" rel="external nofollow" >demo1入門案例</a>
    </body>
</html>
           

5. 開發一個控制器

/**
 * @Controller将目前類放入SpringMVC容器中
 */
@Controller
public class DemoController {
    /**
     * 編寫控制器
     * @RequestMapping:用于為目前方法綁定一個URL位址,作用就是為了前端請求的比對
     */
    @RequestMapping("/demoController/demo1")
    public String demo01(){
        System.out.println("背景執行了...");
        // 傳回值就是下一步要轉發的頁面
        return "/WEB-INF/success.jsp";
    }
}
           

6.開發響應頁面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--
  User: mr_yhl
  Date: 2020/9/26
  Time: 11:58  
--%>
<html>
    <head>
        <title>成功</title>
    </head>
    <body>
        跳轉成功...
    </body>
</html>
           

7. 部署測試

頁面正常跳轉到指定頁面,控制台列印出指定内容

8. 常用的注解

@RequestMapping:用于為目前方法綁定一個URL位址,作用就是為了前端請求的比對

@Controller将目前類放入SpringMVC容器中

第三章 SpringMVC原理(面試必問)

1. SpringMVC的工作流程(手畫)

SpringMVC基礎第一部分
  1. 使用者通過浏覽器發送請求至DispatcherServlet
  2. DispatcherServlet收到請求調用HandlerMapping
  3. HandlerMapping找到具體的處理器鍊傳回給DispatcherServlet
  4. DispatcherServlet會根據傳回的處理器鍊調用HandlerAdapter
  5. HandlerAdapter經過适配調用具體的Handler(controller)
  6. Controller執行完成傳回一個執行結果
  7. HandlerAdapter将Handler的結果ModelAndView對象傳回給DispatcherServlet
  8. DispatcherServlet将ModelAndView對象傳給ViewReslover
  9. ViewReslover解析後得到具體View,并傳回給DispatcherServlet
  10. DispatcherServlet根據View進行視圖渲染(即将模型資料填充至視圖中)
  11. DispatcherServlet會将渲染後的視圖響應給浏覽器

2. SpringMVC的三大元件

處理器映射器 負責根據URL尋找對應的處理器方法

處理器擴充卡 負責真正的去調用某個處理器方法

視圖解析器 負責将邏輯視圖轉換成實體視圖

SpringMVC自帶三大元件,如果不進行配置也能正常使用.配置的相當于增強版
<!--視圖解析器-->
<bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--SpringMVC的前端控制器允許我們以配置的形式傳入字首和字尾,他會在跳轉視圖的時候自動拼接-->
    <property name="prefix" value="/WEB-INF/"></property>
    <property name="suffix" value=".jsp"></property>
</bean>
           

3.RequestMapping(會用)

RequestMapping用于建立請求URL和處理方法之間的對應關系,也可以通過它的屬性對請求做出各種限制

  • value: 用于限制請求URL(和path作用一樣)
  • method:用于限制請求類型
  • params:用于限制請求參數的條件

此注解可以标注在方法上,也可以标注在類上,标注在類上代表類中的所有方法都可以共用一段URL

@Controller
@RequestMapping("/demoController")
public class DemoController {
    /**
     * 編寫控制器
     * @RequestMapping:用于為目前方法綁定一個URL位址,作用就是為了前端請求的比對
     */
    @RequestMapping("/demo1")
    public String demo01(){
        System.out.println("背景執行了...");
        // 傳回值就是下一步要轉發的頁面
        return "success";
    }
}
           

4. 限制請求路徑

4.1 頁面

<a href="${pageContext.request.contextPath}/demoController/demo2" target="_blank" rel="external nofollow" >[email protected]</a>
<a href="${pageContext.request.contextPath}/demoController/demo3" target="_blank" rel="external nofollow" >[email protected]</a>
           

4.2 背景

@RequestMapping(path = {"/demo2","/demo3"})
public String demo02(){
    System.out.println("背景執行了...");
    // 傳回值就是下一步要轉發的頁面
    return "success";
}
           

5. 限制請求類型

method,作用就是用于限定目前方法的送出方式,支援數組寫法(同時多個)

如果不寫method,代表所有請求方式都能運作

5.1 頁面

<form action="${pageContext.request.contextPath}/demoController/demo4" method="post">
    <input type="submit" value="[email protected]">
</form>
           

5.2 背景

/**
 * 編寫控制器
 * @RequestMapping:用于為目前方法綁定一個URL位址,作用就是為了前端請求的比對
 * method,作用就是用于限定目前方法的送出方式,支援數組寫法(同時多個)
 * 如果不寫method,代表所有請求方式都能運作
 */
@RequestMapping(value = "/demo4",method = RequestMethod.POST)
public String demo04(){
    System.out.println("value = \"/demo3\",method = RequestMethod.POST");
    // 傳回值就是下一步要轉發的頁面
    return "success";
}
           

6. 限制請求參數

params用于限定請求參數的必傳,不寫代表不限制

6.1 頁面

<a href="${pageContext.request.contextPath}/demoController/demo5?username=11" target="_blank" rel="external nofollow" >[email protected]</a><br>
           

6.2 背景

/**
 * 編寫控制器
 * @RequestMapping:用于為目前方法綁定一個URL位址,作用就是為了前端請求的比對
 * params用于限定請求參數的必傳,不寫代表不限制
 */
@RequestMapping(value = "/demo5",params = "username")
public String demo05(){
    System.out.println("username");
    // 傳回值就是下一步要轉發的頁面
    return "success";
}
           

第四章 接收請求參數(重點)

在SpringMVC中可以使用多種類型來接收前端傳入的參數(字元串)

1. 簡單類型

隻需要保證前端傳遞的參數名稱跟方法的形參名稱一緻就好

1.1頁面

<a href="${pageContext.request.contextPath}/demoController/demo6?username=張三&age=11" target="_blank" rel="external nofollow" >demo6接收參數--簡單類型</a><br>
           

1.2背景

/**
 * 編寫控制器,接收簡單參數
 * 簡單類型參數接收:需要保證前端傳遞的參數名稱跟方法的形參名稱一緻就好
 * 對于簡單類型的資料,SpringMVC底層内置了類型轉換器
 */
@RequestMapping(value = "/demo6")
public String demo06(String username,Integer age){
    System.out.println("username = "+username+", age = " + age);
    // 傳回值就是下一步要轉發的頁面
    return "success";
}
// username = 張三, age = 11
           

2. 對象類型

隻需要保證前端傳遞的參數名稱跟pojo的屬性名稱(set方法)一緻就好

2.1 頁面

<a href="${pageContext.request.contextPath}/demoController/demo7?username=張三&age=11" target="_blank" rel="external nofollow" >demo7接收參數--對象類型</a><br>
           

2.2 封裝一個實體

public class User {
    private String username;
    private Integer age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                '}';
    }
}
           

2.3 背景

/**
 * 編寫控制器,接收對象類型
 * 接收對象類型:需要保證前端傳遞的參數名稱跟pojo的屬性名稱(set方法)一緻就好
 */
@RequestMapping(value = "/demo7")
public String demo07(User user){
    System.out.println(user);
    // 傳回值就是下一步要轉發的頁面
    return "success";
}
           

3.數組類型

隻需要保證前端傳遞的參數名稱跟方法中的數組形參名稱一緻就好

3.1 頁面

<a href="${pageContext.request.contextPath}/demoController/demo8?students=張三&students=李四" target="_blank" rel="external nofollow" >demo8接收參數--數組類型</a><br>
           

3.2背景

/**
 * 如果前端傳入的是數組,但是背景以字元串接收, Spring會将參數以,分隔拼接成一個串傳進來[ public String demo8(String students)]
 * 如果前端傳入的是數組,背景也是以數組接收, 隻需要保證前端傳遞的參數名稱跟方法中的數組形參名稱一緻就好
 */
@RequestMapping(value = "/demo8")
public String demo08(String[] students){
    for (String student : students) {
        System.out.println(student);
    }
    // 傳回值就是下一步要轉發的頁面
    return "success";
}
           

4. 集合類型

擷取集合參數時,要将集合參數包裝到一個pojo中才可以

4.1頁面

<form action="${pageContext.request.contextPath}/demoController/demo9" method="post">
    第1個User的username:<input type="text" name="users[0].username" value="張三"><br>
    第1個User的age:<input type="text" name="users[0].age" value="16"><br>
    第2個User的username:<input type="text" name="users[1].username" value="李四"><br>
    第2個User的age:<input type="text" name="users[1].age" value="15"><br>

    map的第一個元素:<input type="text" name="map['1001']" value="zs">          

    map的第二個元素:<input type="text" name="map['1002']" value="ls">           

    <input type="submit" value="接收參數--集合類型"><br>           


</form>
           

4.2封裝一個Vo對象

public class Vo {
    private List<User> users = new ArrayList<User>();
    private Map<String,String> map = new HashMap<String, String>();

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }

    public Map<String, String> getMap() {
        return map;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    @Override
    public String toString() {
        return "Vo{" +
                "users=" + users +
                ", map=" + map +
                '}';
    }
}
           

4.3 背景

/**
 *擷取集合參數時,要将集合參數包裝到一個pojo中才可以
 */
@RequestMapping(value = "/demo9")
public String demo09(Vo vo){
    System.out.println(vo);
    // 傳回值就是下一步要轉發的頁面
    return "success";
}
           

5.日期類型(面試)

對于一些常見的類型, SpringMVC是内置了類型轉換器的, 但是對于一些格式比較靈活的參數(日期 時間), SpringMVC無法完成類型轉換

這時候就必須自定義類型轉換器

其實SpringMVC也内置日期類型的轉換器, 格式: yyyy/MM/dd

5.1 頁面

<a href="${pageContext.request.contextPath}/demoController/demo10?myDate=2020-09-26" target="_blank" rel="external nofollow" >demo10接收參數--日期類型</a><br>
           

5.2 自定義時間類型轉換器

1) 自定義一個類型轉換器類,實作類型轉換的方法

/**
 * 自定義一個類型轉換器,實作類型轉換方法(必須實作Converter<原始類型,目标類型>接口)
 */
public class DateConverter implements Converter<String,Date> {

    public Date convert(String s){
        Date date = null;
        try{
           date= new SimpleDateFormat("yyyy-MM-dd").parse(s);
        }catch (ParseException e){
            e.printStackTrace();
        }
        return date;

    }


}
           

2) 将轉換器的類注冊到轉換服務,并且将轉換服務注冊到Springmvc的注冊驅動中

<!--注解驅動:相當于增強版的處理器擴充卡和處理器映射器-->
<mvc:annotation-driven conversion-service="conversionService2" />
<bean id="conversionService2" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="cn.com.mryhl.converters.DateConverter"></bean>
        </set>
    </property>
</bean>
           

5.3 背景

/**
 *擷取日期類型參數
 */
@RequestMapping(value = "/demo10")
public String demo10(Date myDate){
    System.out.println(myDate);
    // 傳回值就是下一步要轉發的頁面
    return "success";
}
           

6. 檔案類型(檔案上傳)

6.1 加入檔案上傳的包

<!--檔案上傳-->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.4</version>
</dependency>
           

6.2配置檔案上傳解析器

<!--
檔案上傳解析器
注意:此處的id是固定值
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--限制每此上傳檔案的大小,機關是B-->
    <property name="maxUploadSize" value="5242880"></property>
</bean>
           

6.3 單檔案上傳

6.3.1 頁面

<%--
檔案上傳三要素:
1) method = "post"
2) enctype = "multipart/form-date"
3) 必須有一個type = file的input域
--%>
<form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/demoController/demo11">
    <input type="file" name="uploadFile">
    <input type="submit" value="單檔案上傳">
</form>
           

6.3.2背景

/**
 *檔案上傳
 * 參數類型必須是MultipartFile,參數名必須域前台一緻
 */
@RequestMapping(value = "/demo11")
public String demo11(MultipartFile uploadFile) throws IOException {
    // 生産新的檔案名
    String newFileName = UUID.randomUUID().toString() + uploadFile.getOriginalFilename();
    // 定義一個本地目錄
    File newFile = new File(new File("F:\\code\\spring\\day04_MVC"), newFileName);

    uploadFile.transferTo(newFile);

    return "success";
}
           

6.4 多檔案上傳

6.4.1頁面

<form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/demoController/demo12">
    <input type="file" name="uploadFiles" multiple>
    <input type="submit" value="多檔案上傳">
</form>
           

6.4.2 背景

/**
 *檔案上傳
 * 參數類型必須是MultipartFile,參數名必須域前台一緻
 */
@RequestMapping(value = "/demo12")
public String demo12(MultipartFile[] uploadFiles) throws IOException {
    for (MultipartFile uploadFile : uploadFiles) {
        // 生産新的檔案名
        String newFileName = UUID.randomUUID().toString() + uploadFile.getOriginalFilename();
        // 定義一個本地目錄
        File newFile = new File(new File("F:\\code\\spring\\day04_MVC"), newFileName);

        uploadFile.transferTo(newFile);
    }

    return "success";
}
           

第五章 接收參數的處理

5.1 中文亂碼

SpringMVC在使用post送出請求時, 對于中文參數是有亂碼問題的, 針對這種情況它提供了一個中文亂碼過濾器, 我們隻需要進行配置一下就可以了.
<!--中文亂碼過濾器-->
   <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>
   </filter>
   <filter-mapping>
       <filter-name>characterEncodingFilter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>
           

5.2 @RequestParam

@RequestParam标注在方法參數之前,用于對傳入的參數做一些限制,支援三個屬性:

  • value:預設屬性,用于指定前端傳入的參數名稱
  • required:用于指定此參數是否必傳
  • defaultValue:當參數為非必傳參數且前端沒有傳入參數時,指定一個預設值

5.2.1 前端

<a href="${pageContext.request.contextPath}/demoController/demo13?students=張三&students=李四" target="_blank" rel="external nofollow" >demo13接收參數[email protected]</a><br>
           

5.2.2背景

/**
 * @RequestParam 标注在方法參數之前, 用于表示目前參數是擷取的前端傳遞過來的哪個參數的值
 * @RequestParam 标注在方法參數之前, 此參數就是必傳選項,不傳就會報錯 , 但是可以使用required=false來取消這個限制
 * defaultValue  可以為目前參數設定一個預設值, 目前端不再傳遞此參數的時候,就使用預設值
 * @RequestParam(value = "students")  可以接收一個集合參數,直接封裝到一個集合對象中去
 */
@RequestMapping(value = "/demo13")
public String demo13(
        @RequestParam(value = "page_size", required = false, defaultValue = "20") String pageSize,
        @RequestParam(value = "students") List<String> students
) {
    System.out.println(pageSize);
    for (String student : students) {
        System.out.println(student);

    }

    return "success";
}
           

第六章 接收請求頭資訊(了解)

1. 前端

<a href="${pageContext.request.contextPath}/demoController/demo14" target="_blank" rel="external nofollow" >demo14接收請求頭參數</a><br>
           

2. 背景

/**
 * 接收請求頭
 * @RequestHeader  用于接收請求頭中的所有資訊, 會封裝到一個Map結構中去
 * @RequestHeader(key)  用于接收請求頭中的某一項資訊
 * @CookieValue(key)  用于接收cookie中的某一項資訊
 */
@RequestMapping(value = "/demo14")
public String demo14(
        @RequestHeader Map map,
        @RequestHeader("cookie") String cookie,
        @CookieValue("JSESSIONID") String jsessionid
) {
    System.out.println(map);
    System.out.println(cookie);
    System.out.println(jsessionid);
    return "success";
}
           

運作結果

{host=localhost:8080, connection=keep-alive, upgrade-insecure-requests=1, user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36, accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9, sec-fetch-site=same-origin, sec-fetch-mode=navigate, sec-fetch-user=?1, sec-fetch-dest=document, referer=http://localhost:8080/, accept-encoding=gzip, deflate, br, accept-language=zh-CN,zh;q=0.9, cookie=Idea-affb8a85=347d378c-a966-4e19-a8bb-71aac3e665bb; JSESSIONID=372DA54978F9BF7DC7ED8CF9DD78F197}

Idea-affb8a85=347d378c-a966-4e19-a8bb-71aac3e665bb; JSESSIONID=372DA54978F9BF7DC7ED8CF9DD78F197

372DA54978F9BF7DC7ED8CF9DD78F197

@RequestParam

@RequestParam标注在方法參數之前,用于對傳入的參數做一些限制,支援三個屬性:

  • value:預設屬性,用于指定前端傳入的參數名稱
  • required:用于指定此參數是否必傳
  • defaultValue:當參數為非必傳參數且前端沒有傳入參數時,指定一個預設值