SpringMVC(一):基本應(yīng)用

SpringMVC 簡(jiǎn)介

  • MVC 模式

MVC 是軟件工程中的一種軟件架構(gòu)模式乏屯,它是一種分離業(yè)務(wù)邏輯與顯示界面的開(kāi)發(fā)思想勃刨。

  • M(model)模型:處理業(yè)務(wù)邏輯叽粹,封裝實(shí)體
  • V(view) 視圖:展示內(nèi)容
  • C(controller)控制器:負(fù)責(zé)調(diào)度分發(fā)(1.接收請(qǐng)求、2.調(diào)用模型溯乒、3.轉(zhuǎn)發(fā)到視圖)
  • SpringMVC 概述

SpringMVC 是一種基于 Java 的實(shí)現(xiàn) MVC 設(shè)計(jì)模式的輕量級(jí) Web 框架杯道,屬于Spring Framework 的后續(xù)產(chǎn)品匪煌,已經(jīng)融合在 Spring Web Flow 中责蝠。

SpringMVC 已經(jīng)成為目前最主流的 MVC 框架之一,并且隨著 Spring 3.0 的發(fā)布萎庭,全面超越 Struts 2霜医,成為最優(yōu)秀的 MVC 框架。它通過(guò)一套注解驳规,讓一個(gè)簡(jiǎn)單的 Java 類成為處理請(qǐng)求的控制器肴敛,而無(wú)須實(shí)現(xiàn)任何接口。同時(shí)它還支持 RESTful 編程風(fēng)格的請(qǐng)求吗购。

SpringMVC 的框架就是封裝了原來(lái) Servlet 中的共有行為医男;例如:參數(shù)封裝,視圖轉(zhuǎn)發(fā)等捻勉。

  • SpringMVC 快速入門(mén)

需求:客戶端發(fā)起請(qǐng)求镀梭,服務(wù)器接收請(qǐng)求,執(zhí)行邏輯并進(jìn)行視圖跳轉(zhuǎn)踱启。

步驟分析:

  1. 創(chuàng)建web項(xiàng)目报账,導(dǎo)入 SpringMVC 相關(guān)坐標(biāo)
  2. 配置 SpringMVC 前端控制器 DispatcherServlet
  3. 編寫(xiě) Controller 類和視圖頁(yè)面
  4. 使用注解配置 Controller 類中業(yè)務(wù)方法的映射地址
  5. 配置 SpringMVC 核心文件 spring-mvc.xml

1. 創(chuàng)建 web 項(xiàng)目,導(dǎo)入 SpringMVC 相關(guān)坐標(biāo)

<packaging>war</packaging>

<!-- 指定編碼及版本 -->
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
    <java.version>1.11</java.version>
    <maven.compiler.source>1.11</maven.compiler.source>
    <maven.compiler.target>1.11</maven.compiler.target>
</properties>

<dependencies>
    <!-- springMVC 坐標(biāo) -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>
    <!-- servlet 坐標(biāo) -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- jsp 坐標(biāo) -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
        <scope>provided</scope>
    </dependency>

    ...

</dependencies>

2. 配置 SpringMVC 前端控制器 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">

    <!-- springMVC 的前端控制器:DispatcherServlet-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 加載 springMVC 相關(guān)的配置文件 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <!-- 
            在應(yīng)用啟動(dòng)時(shí)埠偿,就完成 servlet 的實(shí)例化及初始化操作透罢。
            數(shù)字大于等于 0 時(shí),服務(wù)器啟動(dòng)時(shí)就加載并初始化 servlet;
            數(shù)字越接近 0冠蒋,則優(yōu)先級(jí)越高
        -->
        <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <!--
            / 和 /* 的區(qū)別:
            / 會(huì)匹配到所有的訪問(wèn)路徑羽圃,除了帶有 *.jsp 這樣的后綴名的路徑;
            如可以匹配到 /login /add /update浊服,但 /a.jsp 不能匹配统屈。
        -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

3. 編寫(xiě) Controller 類和視圖頁(yè)面
UserController.java

public class UserController {
    public String quick() {
        // 業(yè)務(wù)處理
        System.out.println("SpringMVC Quick Start...");
        // 頁(yè)面跳轉(zhuǎn) 請(qǐng)求轉(zhuǎn)發(fā)
        return "/WEB-INF/pages/success.jsp";
    }
}

/WEB-INF/pages/success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>SUCCESS</title>
</head>
<body>

    <h3>success... ${username}</h3>
    <% System.out.println("Success...");%>

</body>
</html>

4. 使用注解配置 Controller 類中業(yè)務(wù)方法的映射地址

@Controller
public class UserController {
    @RequestMapping("/quick")
    public String quick() {
        System.out.println("SpringMVC Quick Start...");
        return "/WEB-INF/pages/success.jsp";
    }
}

5. 配置 SpringMVC 核心文件 spring-mvc.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- IOC 注解掃描 -->
    <context:component-scan base-package="com.zm.controller"/>

</beans>
  • web 工程執(zhí)行流程

客戶端(瀏覽器)發(fā)送請(qǐng)求到 Tomcat 服務(wù)器胚吁,Tomcat 服務(wù)器發(fā)送響應(yīng)到客戶端牙躺。

服務(wù)器的 Tomcat 引擎:

  1. 接受客戶端請(qǐng)求,解析請(qǐng)求資源地址
  2. 創(chuàng)建代表請(qǐng)求的 request 對(duì)象
  3. 創(chuàng)建代表響應(yīng) response 對(duì)象
  4. 調(diào)用目標(biāo)資源
  5. 獲得 response 中的內(nèi)容腕扶,組裝成 HTTP 響應(yīng)返回客戶端

服務(wù)器的 Web 應(yīng)用:

  1. 獲得請(qǐng)求資源地址
  2. 解析映射地址孽拷,找到對(duì)應(yīng)的處理器(Controller)
  3. 處理器執(zhí)行對(duì)應(yīng)的方法(進(jìn)行業(yè)務(wù)邏輯以及視圖跳轉(zhuǎn)操作),獲取被訪問(wèn)的真實(shí)資源

小結(jié)

  • SpringMVC 是對(duì) MVC 設(shè)計(jì)模式的一種實(shí)現(xiàn)半抱,屬于輕量級(jí)的 WEB 框架脓恕。
  • SpringMVC 的開(kāi)發(fā)步驟:
    1. 創(chuàng)建 web 項(xiàng)目,導(dǎo)入 SpringMVC 相關(guān)坐標(biāo)
    2. 配置 SpringMVC 前端控制器 DispatcherServlet
    3. 編寫(xiě) Controller 類和視圖頁(yè)面
    4. 使用注解配置 Controller 類中業(yè)務(wù)方法的映射地址
    5. 配置 SpringMVC 核心文件 spring-mvc.xml

SpringMVC 組件概述

  • SpringMVC 的執(zhí)行流程

  1. 用戶發(fā)送請(qǐng)求至前端控制器 DispatcherServlet窿侈。
  1. DispatcherServlet 收到請(qǐng)求調(diào)用 HandlerMapping 處理器映射器炼幔。
  1. 處理器映射器找到具體的處理器(可以根據(jù) xml 配置、注解進(jìn)行查找)史简,生成處理器對(duì)象及處理器攔截器(如果有則生成)一并返回給 DispatcherServlet乃秀。
  1. DispatcherServlet 調(diào)用 HandlerAdapter 處理器適配器。
  1. HandlerAdapter 經(jīng)過(guò)適配調(diào)用具體的處理器(Controller,也叫后端控制器)跺讯。
  1. Controller 執(zhí)行完成返回 ModelAndView枢贿。
  1. HandlerAdapter 將 controller 執(zhí)行結(jié)果 ModelAndView 返回給 DispatcherServlet。
  1. DispatcherServlet 將 ModelAndView 傳給 ViewReslover 視圖解析器刀脏。
  1. ViewReslover 解析后返回具體 View局荚。
  1. DispatcherServlet 根據(jù) View 進(jìn)行渲染視圖(即將模型數(shù)據(jù)填充至視圖中)。
  1. DispatcherServlet 將渲染后的視圖響應(yīng)響應(yīng)用戶愈污。
  • SpringMVC 組件解析

  1. 前端控制器:DispatcherServlet
    用戶請(qǐng)求到達(dá)前端控制器耀态,它就相當(dāng)于 MVC 模式中的 C;DispatcherServlet 是整個(gè)流程控制的中心钙畔,由它調(diào)用其它組件處理用戶的請(qǐng)求茫陆;DispatcherServlet 的存在降低了組件之間的耦合性。

  2. 處理器映射器:HandlerMapping
    HandlerMapping 負(fù)責(zé)根據(jù)用戶請(qǐng)求找到 Handler 即處理器擎析;SpringMVC 提供了不同的映射器實(shí)現(xiàn)不同的映射方式簿盅,例如:配置文件方式、實(shí)現(xiàn)接口方式揍魂、注解方式等桨醋。

  3. 處理器適配器:HandlerAdapter
    通過(guò) HandlerAdapter 對(duì)處理器進(jìn)行執(zhí)行,這是適配器模式的應(yīng)用现斋,通過(guò)擴(kuò)展適配器可以對(duì)更多類型的處理器進(jìn)行執(zhí)行喜最。

  4. 處理器:Handler【開(kāi)發(fā)者編寫(xiě)
    它是開(kāi)發(fā)中要編寫(xiě)的具體業(yè)務(wù)控制器;由 DispatcherServlet 把用戶請(qǐng)求轉(zhuǎn)發(fā)到 Handler庄蹋;由 Handler 對(duì)具體的用戶請(qǐng)求進(jìn)行處理瞬内。

  5. 視圖解析器:ViewResolver
    View Resolver 負(fù)責(zé)將處理結(jié)果生成 View 視圖;View Resolver 首先根據(jù)邏輯視圖名解析成物理視圖名限书,即具體的頁(yè)面地址虫蝶,再生成 View 視圖對(duì)象,最后對(duì) View 進(jìn)行渲染將處理結(jié)果通過(guò)頁(yè)面展示給用戶倦西。

  6. 視圖:View 【開(kāi)發(fā)者編寫(xiě)
    SpringMVC 框架提供了很多的 View 視圖類型的支持能真,包括:jstlView、freemarkerView扰柠、pdfView等粉铐。最常用的視圖就是 jsp。一般情況下需要通過(guò)頁(yè)面標(biāo)簽或頁(yè)面模版技術(shù)將模型數(shù)據(jù)通過(guò)頁(yè)面展示給用戶卤档,需要由程序員根據(jù)業(yè)務(wù)需求開(kāi)發(fā)具體的頁(yè)面蝙泼。

  7. SpringMVC 中的三大組件是什么?
    處理器映射器 HandlerMapping劝枣;
    處理器適配器 HandlerAdapter汤踏;
    視圖解析器 ViewResolver倡缠;
    如果是四大組件,則加上前端控制器 DispatcherServlet茎活。

spring-mvc.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- IOC 注解掃描 -->
    <context:component-scan base-package="com.zm.controller"/>

    <!-- 處理器映射器-處理器適配器昙沦。進(jìn)行了功能的增強(qiáng):支持 json 的讀寫(xiě) -->
    <mvc:annotation-driven/>

    <!-- 視圖解析器:ViewResolver -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- success :解析邏輯視圖名,解析成具體的物理文件地址 /WEB-INF/pages/success.jsp -->
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>

UserController.java

    @RequestMapping("/quick")
    public String quick() {
        System.out.println("SpringMVC Quick Start...");
        // 頁(yè)面跳轉(zhuǎn) 請(qǐng)求轉(zhuǎn)發(fā) 返回邏輯視圖名
        return "success";
    }
  • SpringMVC 注解解析

@Controller

SpringMVC 基于 Spring 容器载荔,所以在進(jìn)行 SpringMVC 操作時(shí)盾饮,需要將 Controller 存儲(chǔ)到 Spring 容器中,如果使用 @Controller 注解標(biāo)注的話懒熙,就需要使用:

<!-- 配置 IOC 注解掃描 -->
<context:component-scan base-package="com.zm.controller"/>

注意配置 SpringMVC 的 base package 只掃描 web 層的包丘损,其它包交給 Spring 容器掃描;這樣 SpringMVC 的容器就相當(dāng)于是 Spring 容器的一個(gè)子容器工扎。

@RequestMapping

* 作用:用于建立請(qǐng)求 URL 和處理請(qǐng)求方法之間的對(duì)應(yīng)關(guān)系

* 位置:
1. 類上:請(qǐng)求 URL 的第一級(jí)訪問(wèn)目錄徘钥。此處不寫(xiě)的話,就相當(dāng)于應(yīng)用的根目錄肢娘;寫(xiě)的話需要以 / 開(kāi)頭呈础。
    它出現(xiàn)的目的是為了使 URL 可以按照模塊化管理:
        用戶模塊
            /user/add
            /user/update
            /user/delete
            ...
        賬戶模塊
            /account/add
            /account/update
            /account/delete
2. 方法上:請(qǐng)求 URL 的第二級(jí)訪問(wèn)目錄,和一級(jí)目錄組成一個(gè)完整的 URL 路徑橱健。

* 屬性:
1. value:用于指定請(qǐng)求的 URL而钞;它和 path 屬性的作用是一樣的
2. method:用來(lái)限定請(qǐng)求的方式
3. params:用來(lái)限定請(qǐng)求參數(shù)的條件
    例如:
        params={"accountName"} 表示請(qǐng)求參數(shù)中必須有 accountName
        params={"money!100"} 表示請(qǐng)求參數(shù)中 money 不能是100
@Controller
@RequestMapping("/user") //一級(jí)訪問(wèn)目錄
public class UserController {

    /**
     * http://localhost:8080/springmvc_quickstart/user/quick?accountName=renda
     * 
     * path :作用等同于 value,同樣是設(shè)置方法的映射地址
     * method:用來(lái)限定請(qǐng)求的方式 RequestMethod.POST: 只能以 post 的請(qǐng)求方式訪問(wèn)該訪問(wèn)拘荡,其他請(qǐng)求方式會(huì)報(bào)錯(cuò)
     * params:用來(lái)限定請(qǐng)求參數(shù)的條件 params={"accountName"} 表示請(qǐng)求參數(shù)中必須有 accountName
     */
    @RequestMapping(
            path = "/quick", // 二級(jí)訪問(wèn)目錄
            method = {RequestMethod.POST, RequestMethod.GET},
            params = {"accountName"})
    public String quick() {
        // 業(yè)務(wù)處理
        System.out.println("SpringMVC Quick Start...");
        // 頁(yè)面跳轉(zhuǎn) 請(qǐng)求轉(zhuǎn)發(fā) 返回邏輯視圖名
        return "success";
    }

}
  • 小結(jié)

-- SpringMVC的三大組件
處理器映射器:HandlerMapping
處理器適配器:HandlerAdapter
視圖解析器:View Resolver

-- 開(kāi)發(fā)者編寫(xiě)
處理器:Handler
視圖:View


SpringMVC 的請(qǐng)求

  • 請(qǐng)求參數(shù)類型介紹

客戶端請(qǐng)求參數(shù)的格式是: name=value&name=value ...

服務(wù)器要獲取請(qǐng)求的參數(shù)的時(shí)候要進(jìn)行類型轉(zhuǎn)換臼节,有時(shí)還需要進(jìn)行數(shù)據(jù)的封裝

SpringMVC 可以接收如下類型的參數(shù):

  • 基本類型參數(shù)

  • 對(duì)象類型參數(shù)

  • 數(shù)組類型參數(shù)

  • 集合類型參數(shù)

  • 獲取基本類型參數(shù)

Controller 中的業(yè)務(wù)方法的參數(shù)名稱要與請(qǐng)求參數(shù)的 name 一致,參數(shù)值會(huì)自動(dòng)映射匹配珊皿。并且能自動(dòng)做類型轉(zhuǎn)換网缝;自動(dòng)的類型轉(zhuǎn)換是指從 String 向其他類型的轉(zhuǎn)換。

requestParam.jsp

<%-- ${pageContext.request.contextPath} 動(dòng)態(tài)的來(lái)獲取當(dāng)前的項(xiàng)目路徑 - springmvc_quickstart蟋定;a 標(biāo)簽的請(qǐng)求方式:get 請(qǐng)求 --%>
<a href="${pageContext.request.contextPath}/user/simpleParam?id=1&username=杰克">
    基本類型參數(shù)
</a>

在 UserController 中添加方法

@RequestMapping("/simpleParam")
public String simpleParam(Integer id, String username) {
    System.out.println(id);
    System.out.println(username);
    return "success";
}
  • 獲取對(duì)象類型參數(shù)

Controller 中的業(yè)務(wù)方法參數(shù)的 POJO 屬性名與請(qǐng)求參數(shù)的 name 一致粉臊,參數(shù)值會(huì)自動(dòng)映射匹配。

requestParam.jsp

<%-- form 表單溢吻;該表單提交的請(qǐng)求方式為 post 類型 --%>
<form action="${pageContext.request.contextPath}/user/pojoParam" method="post">
    編號(hào):<input type="text" name="id"><br>
    用戶名:<input type="text" name="username">
    <input type="submit" value="對(duì)象類型參數(shù)">
</form>

創(chuàng)建 User 類

public class User {
    private Integer id;
    private String username;
    // setter getter...
}

在 UserController 中添加方法

@RequestMapping("/pojoParam")
public String pojoParam(User user){
    System.out.println(user);
    return "success";
}
  • 中文亂碼過(guò)濾器

當(dāng) post 請(qǐng)求時(shí)维费,數(shù)據(jù)會(huì)出現(xiàn)亂碼果元,可以在 web.xml 設(shè)置一個(gè)過(guò)濾器來(lái)進(jìn)行編碼的過(guò)濾促王。

<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>
  • 獲取數(shù)組類型參數(shù)

Controller 中的業(yè)務(wù)方法數(shù)組名稱與請(qǐng)求參數(shù)的 name 一致,參數(shù)值會(huì)自動(dòng)映射匹配而晒。

requestParam.jsp

<form action="${pageContext.request.contextPath}/user/arrayParam" method="post">
    編號(hào):<br>
    <input type="checkbox" name="id" value="1">1<br>
    <input type="checkbox" name="ids" value="2">2<br>
    <input type="checkbox" name="ids" value="3">3<br>
    <input type="checkbox" name="ids" value="4">4<br>
    <input type="submit" value="數(shù)組類型參數(shù)">
</form>

在 UserController 中添加方法

@RequestMapping("/arrayParam")
public String arrayParam(Integer[] ids){
    System.out.println(Arrays.toString(ids));
    return "success";
}
  • 獲取集合(復(fù)雜)類型參數(shù)

獲得集合參數(shù)時(shí)蝇狼,要將集合參數(shù)包裝到一個(gè) POJO 中才可以。

requestParam.jsp

<form action="${pageContext.request.contextPath}/user/queryParam" method="post">
    搜索關(guān)鍵字:
    <input type="text" name="keyword"><br>
    user對(duì)象:
    <input type="text" name="user.id" placeholder="編號(hào)">
    <input type="text" name="user.username" placeholder="姓名"><br>
    list集合:
    元素1:
    <input type="text" name="userList[0].id" placeholder="編號(hào)">
    <input type="text" name="userList[0].username" placeholder="姓名">
    元素2:
    <input type="text" name="userList[1].id" placeholder="編號(hào)">
    <input type="text" name="userList[1].username" placeholder="姓名"><br>
    Map集合:
    元素1:
    <input type="text" name="userMap['u1'].id" placeholder="編號(hào)">
    <input type="text" name="userMap['u1'].username" placeholder="姓名">
    元素2:
    <input type="text" name="userMap['u2'].id" placeholder="編號(hào)">
    <input type="text" name="userMap['u2'].username" placeholder="姓名"><br>
    <input type="submit" value="復(fù)雜類型">
</form>

創(chuàng)建 QueryVo 類

public class QueryVo {

    private String keyword;
    private User user;
    private List<User> userList;
    private Map<String, User> userMap;
    // setter getter...
}

在 UserController 中添加方法

@RequestMapping("/queryParam")
public String queryParam(QueryVo queryVo){
    System.out.println(queryVo);
    return "success";
}
  • 自定義類型轉(zhuǎn)換器

SpringMVC 默認(rèn)已經(jīng)提供了一些常用的類型轉(zhuǎn)換器倡怎。例如:客戶端提交的字符串轉(zhuǎn)換成 INT 型進(jìn)行參數(shù)設(shè)置迅耘,日期格式類型要求為:yyyy/MM/dd 不然的話會(huì)報(bào)錯(cuò)贱枣;對(duì)于特有的行為,SpringMVC 提供了自定義類型轉(zhuǎn)換器方便開(kāi)發(fā)者自定義處理颤专。

requestParam.jsp

<form action="${pageContext.request.contextPath}/user/converterParam" method="post">
    生日:<input type="text" name="birthday">
    <input type="submit" value="自定義類型轉(zhuǎn)換器">
</form>

配置自定義日期轉(zhuǎn)換 DateConverter

public class DateConverter implements Converter<String, Date> {

    /**
     * s 就是表單傳遞過(guò)來(lái)的請(qǐng)求參數(shù)纽哥,如 2012-12-12
     */
    @Override
    public Date convert(String s) {
        // 將日期字符串轉(zhuǎn)換成日期對(duì)象,進(jìn)行返回
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = simpleDateFormat.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}

spring-mvc.xml

<!-- 自定義類型轉(zhuǎn)換器配置 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.zm.converter.DateConverter"/>
        </set>
    </property>
</bean>
<!-- 處理器映射器-處理器適配器栖秕。進(jìn)行了功能的增強(qiáng):支持 json 的讀寫(xiě) -->
<mvc:annotation-driven conversion-service="conversionService"/>

在 UserController 中添加方法

@RequestMapping("/converterParam")
public String converterParam(Date birthday){
    System.out.println(birthday);
    return "success";
}
  • 相關(guān)注解

@RequestParam
當(dāng)請(qǐng)求的參數(shù) name 名稱與 Controller 的業(yè)務(wù)方法參數(shù)名稱不一致時(shí)春塌,就需要通過(guò) @RequestParam 注解顯示的綁定

requestParam.jsp

<a href="${pageContext.request.contextPath}/user/findByPage?pageNo=2">
    分頁(yè)查詢
</a>

在 UserController 中添加方法

/**
 * name:匹配頁(yè)面?zhèn)鬟f參數(shù)的名稱
 * defaultValue:設(shè)置參數(shù)的默認(rèn)值
 * required:設(shè)置是否必須傳遞該參數(shù),默認(rèn)值為 true簇捍;如果設(shè)置了默認(rèn)值只壳,值自動(dòng)改為 false
 */
@RequestMapping("findByPage")
public String findByPage(
    @RequestParam(name = "pageNo", defaultValue = "1", required = false) Integer pageNum,
    @RequestParam(defaultValue = "5") Integer pageSize) {
    System.out.println(pageNum);
    System.out.println(pageSize);
    return "success";
}

@RequestHeader
獲取請(qǐng)求頭的數(shù)據(jù)。

在 UserController 中添加方法

@RequestMapping("/requestHeader")
public String requestHead(@RequestHeader("cookie") String cookie){
    System.out.println(cookie);
    return "success";
}

@CookieValue
獲取 cookie 中的數(shù)據(jù)暑塑。

在 UserController 中添加方法

@RequestMapping("/cookieValue")
public String cookieValue(@CookieValue("JSESSIONID") String jSessionId){
    System.out.println(jSessionId);
    return "success";
}
  • 獲取 Servlet 相關(guān) API

SpringMVC 支持使用原始 Servlet API 對(duì)象作為控制器方法的參數(shù)進(jìn)行注入吼句,常用的對(duì)象如下:

@RequestMapping("/servletAPI")
public String servletApi(HttpServletRequest request, HttpServletResponse response, HttpSession session){
    System.out.println(request);
    System.out.println(response);
    System.out.println(session);
    return "success";
}


SpringMVC 的響應(yīng)

  • SpringMVC 響應(yīng)方式介紹

頁(yè)面跳轉(zhuǎn):

  1. 返回字符串邏輯視圖
  2. void 原始 ServletAPI
  3. ModelAndView

返回?cái)?shù)據(jù):

  1. 直接返回字符串?dāng)?shù)據(jù)
  2. 將對(duì)象或集合轉(zhuǎn)為 json 返回
返回字符串邏輯視圖

直接返回字符串:此種方式會(huì)將返回的字符串與視圖解析器的前后綴拼接后跳轉(zhuǎn)到指定頁(yè)面

@RequestMapping("/returnString")
public String returnString() {
    return "success";
}
void 原始 ServletAPI

可以通過(guò) request、response 對(duì)象實(shí)現(xiàn)響應(yīng)

index.jsp

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

在 UserController 中添加方法

@RequestMapping("/returnVoid")
public void returnVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    /* 直接返回?cái)?shù)據(jù) */
    response.setContentType("text/html;charset=utf-8");
    response.getWriter().write("張三 ");
    request.setAttribute("username", "zhangsan");

    // 借助 request 對(duì)象完成請(qǐng)求轉(zhuǎn)發(fā)事格,一次請(qǐng)求
    // request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);
    // request.getRequestDispatcher("/index.jsp").forward(request, response);

    // 借助 response 對(duì)象完成重定向惕艳,兩次請(qǐng)求。WEB-INF - 安全目錄:不允許外部請(qǐng)求直接訪問(wèn)該目錄資源驹愚,只可以進(jìn)行服務(wù)器內(nèi)部轉(zhuǎn)發(fā)
    // response.sendRedirect(request.getContextPath() + "/index.jsp");
}
轉(zhuǎn)發(fā)和重定向

企業(yè)開(kāi)發(fā)一般使用返回字符串邏輯視圖實(shí)現(xiàn)頁(yè)面的跳轉(zhuǎn)尔艇,這種方式其實(shí)就是請(qǐng)求轉(zhuǎn)發(fā);也可以寫(xiě)成:forward 轉(zhuǎn)發(fā)么鹤。如果用了 forward终娃,則路徑必須寫(xiě)成實(shí)際視圖 URL,不能寫(xiě)邏輯視圖蒸甜。它相當(dāng)于:

request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response)

使用請(qǐng)求轉(zhuǎn)發(fā)棠耕,既可以轉(zhuǎn)發(fā)到 JSP,也可以轉(zhuǎn)發(fā)到其他的控制器方法柠新。

@RequestMapping("/forward")
public String forward(Model model){
    // 在模型中設(shè)置一些值
    model.addAttribute("username","zhangsan");
    // 使用請(qǐng)求轉(zhuǎn)發(fā)窍荧,既可以轉(zhuǎn)發(fā)到 jsp,也可以轉(zhuǎn)發(fā)到其他的控制器方法
    // return "forward:/product/findAll";
    return "forward:/WEB-INF/pages/success.jsp";
}

Redirect 重定向:可以不寫(xiě)虛擬目錄,SpringMVC 框架會(huì)自動(dòng)拼接恨憎,并且將 Model 中的數(shù)據(jù)拼接到 URL 地址上蕊退;重定向的目標(biāo) JSP 頁(yè)面不能寫(xiě)在 WEB-INF 目錄中,否則無(wú)法找到憔恳。

@RequestMapping("/redirect")
public String redirect(Model model) {
    // 底層使用的還是 request.setAttribute("username","lucky")瓤荔,
    // 域范圍是一次請(qǐng)求,所以重定向后钥组,請(qǐng)求發(fā)生了變化输硝,請(qǐng)求域的值無(wú)法獲取
    model.addAttribute("username", "lucky");
    return "redirect:/index.jsp";
}
ModelAndView

方式一
在 Controller 中方法創(chuàng)建并返回 ModelAndView 對(duì)象,并且設(shè)置視圖名稱

/**
 * model:模型:作用封裝存放數(shù)據(jù)
 * View :視圖:用來(lái)展示數(shù)據(jù)
 */
@RequestMapping("/returnModelAndView")
public ModelAndView returnModelAndView(){
    ModelAndView modelAndView = new ModelAndView();
    // 設(shè)置模型數(shù)據(jù)
    modelAndView.addObject("username","modelAndView 方式一");
    // 設(shè)置視圖名稱程梦。視圖解析器解析 modelAndView 拼接前綴和后后綴
    modelAndView.setViewName("success");
    return modelAndView;
}

方式二
在 Controller 中方法形參上直接聲明 ModelAndView点把,無(wú)需在方法中自己創(chuàng)建橘荠,在方法中直接使用該對(duì)象設(shè)置視圖,同樣可以跳轉(zhuǎn)頁(yè)面

@RequestMapping("/returnModelAndView2")
public ModelAndView returnModelAndView2(ModelAndView modelAndView){
    // 設(shè)置模型數(shù)據(jù)
    modelAndView.addObject("username","modelAndView 方式二");
    // 設(shè)置視圖名稱郎逃。視圖解析器解析 modelAndView 拼接前綴和后后綴
    modelAndView.setViewName("success");
    return modelAndView;
}
@SessionAttributes

如果在多個(gè)請(qǐng)求之間共用數(shù)據(jù)哥童,則可以在控制器類上標(biāo)注一個(gè) @SessionAttributes,配置需要在 session 中存放的數(shù)據(jù)范圍褒翰,SpringMVC 將存放在 model 中對(duì)應(yīng)的數(shù)據(jù)暫存到 HttpSession 中如蚜。

注意:@SessionAttributes 只能定義在類上

@Controller
@RequestMapping("/user") //一級(jí)訪問(wèn)目錄
@SessionAttributes("username") // 向 request 域中(model)中存入 key 為 username 時(shí),會(huì)同步到 session 域中
public class UserController {

    ...

    @RequestMapping("/forward")
    public String forward(Model model) {
        // 在模型中設(shè)置一些值
        model.addAttribute("username", "zhangsan");
        // 使用請(qǐng)求轉(zhuǎn)發(fā)影暴,既可以轉(zhuǎn)發(fā)到 jsp,也可以轉(zhuǎn)發(fā)到其他的控制器方法
        // return "forward:/product/findAll";
        return "forward:/WEB-INF/pages/success.jsp";
    }

    ...

    @RequestMapping("/returnString")
    public String returnString(){
        return "success";
    }
}
  • 小結(jié)

  • 頁(yè)面跳轉(zhuǎn)采用返回字符串邏輯視圖
    forward 轉(zhuǎn)發(fā)
    可以通過(guò)Model向request域中設(shè)置數(shù)據(jù)
    redirect 重定向
    直接寫(xiě)資源路徑即可错邦,虛擬目錄springMVC框架自動(dòng)完成拼接

  • 數(shù)據(jù)存儲(chǔ)到 request 域中
    Model model
    model.addAttribute("username", "子慕");


靜態(tài)資源訪問(wèn)的開(kāi)啟

requestParam.jsp

...
<%-- 引入 jquery.js --%>
<script src="${pageContext.request.contextPath}/js/jquery-3.5.1.js"></script>
...

當(dāng)有靜態(tài)資源需要加載時(shí),比如 jQuery 文件型宙,通過(guò)谷歌開(kāi)發(fā)者工具抓包發(fā)現(xiàn)撬呢,沒(méi)有加載到 jQuery 文件,原因是 SpringMVC 的前端控制器 DispatcherServlet 的 url-pattern 配置的是 /(默認(rèn)配置)妆兑,代表對(duì)所有的靜態(tài)資源都進(jìn)行處理操作魂拦,這樣就不會(huì)執(zhí)行 Tomcat 內(nèi)置的 DefaultServlet 處理,可以通過(guò)以下兩種方式在 spring-mvc.xml 指定放行靜態(tài)資源搁嗓。

方式一:放行指定的靜態(tài)資源

<!-- mapping:放行的映射路徑芯勘,location:靜態(tài)資源所在的目錄 -->
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/img/**" location="/img/"/>

方式二:放行全部的靜態(tài)資源

<!-- 在 springmvc 配置文件中開(kāi)啟 DefaultServlet 處理靜態(tài)資源 -->
<mvc:default-servlet-handler/>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市腺逛,隨后出現(xiàn)的幾起案子荷愕,更是在濱河造成了極大的恐慌,老刑警劉巖棍矛,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件安疗,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡够委,警方通過(guò)查閱死者的電腦和手機(jī)荐类,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)茁帽,“玉大人玉罐,你說(shuō)我怎么就攤上這事∨瞬Γ” “怎么了吊输?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)战秋。 經(jīng)常有香客問(wèn)我璧亚,道長(zhǎng)讨韭,這世上最難降的妖魔是什么脂信? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任癣蟋,我火速辦了婚禮,結(jié)果婚禮上狰闪,老公的妹妹穿的比我還像新娘疯搅。我一直安慰自己,他們只是感情好埋泵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布幔欧。 她就那樣靜靜地躺著,像睡著了一般丽声。 火紅的嫁衣襯著肌膚如雪礁蔗。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天雁社,我揣著相機(jī)與錄音浴井,去河邊找鬼。 笑死霉撵,一個(gè)胖子當(dāng)著我的面吹牛磺浙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播徒坡,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼撕氧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了喇完?” 一聲冷哼從身側(cè)響起伦泥,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锦溪,沒(méi)想到半個(gè)月后奄喂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡海洼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年跨新,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坏逢。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡域帐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出是整,到底是詐尸還是另有隱情肖揣,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布浮入,位于F島的核電站龙优,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏事秀。R本人自食惡果不足惜彤断,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一野舶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宰衙,春花似錦平道、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至袋哼,卻和暖如春冀墨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背涛贯。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工轧苫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人疫蔓。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓含懊,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親衅胀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子岔乔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容