徹徹底底給你講明白啥是SpringMvc!

一豹休、SpringMVC簡(jiǎn)介

1.1炊昆、SpringMVC引言

為了使Spring有可插入的MVC架構(gòu),SpringFrameWork在Spring基礎(chǔ)上開發(fā)SpringMVC框架,從而在使用Spring進(jìn)行WEB開發(fā)時(shí)可以選擇使用Spring的SpringMVC框架作為web開發(fā)的控制器框架

1.2威根、SpringMVC的優(yōu)勢(shì)

image

SpringMVC是一個(gè)典型的輕量級(jí)MVC框架凤巨,在整個(gè)MVC架構(gòu)中充當(dāng)控制器框架,相對(duì)于之前的struts2框架,SpringMVC運(yùn)行更快,其注解式開發(fā)更高效靈活

  1. 可以和Spring框架無縫整合医窿。
  2. 運(yùn)行效率遠(yuǎn)遠(yuǎn)高于struts2框架磅甩。
  3. 注解式開發(fā)更高效。

二姥卢、SpringMVC入門

2.1卷要、環(huán)境搭建

2.1.1、引入依賴

依賴就忽略了独榴,我放在了評(píng)論區(qū)僧叉!

2.1.2、編寫配置文件

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

<!--  1. 開啟注解掃描-->
  <context:component-scan base-package="com.lin.controller"/>
<!--  2. 配置處理器映射器-->
<!--  <bean  />-->
<!--  3. 開啟處理器適配器-->
<!--  <bean  />-->
<!--  上面兩段配置被下面的一句話所替代(封裝)-->
  <mvc:annotation-driven />
  <!--  4. 開啟視圖解析器-->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
</beans>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.

2.1.3棺榔、配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

<!--  配置springmvc的核心servlet-->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
<!--      告訴springmvc配置文件的位置-->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
<!--    攔截所有請(qǐng)求-->
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.

2.1.4瓶堕、編寫控制器

package com.lin.controller;

import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author XiaoLin
 * @date 2021/2/17 17:09
 */
@Controller
public class HellowController {

  /**
      * @Description:第一個(gè)springmvc測(cè)試類
      * @author XiaoLin
      * @date 2021/2/17
      * @Param: [username, password]
      * @return java.lang.String
      */
     /*
      RequestMapping的修飾范圍:可以用在類上和方法上,他的作用如下:
      1. 用在方法上可以給當(dāng)前方法加入指定的請(qǐng)求路徑
      2. 用在類上可以給類中的所有方法都加入一個(gè)統(tǒng)一的請(qǐng)求路徑症歇,在這個(gè)方法訪問之前都必須加上
      */
  @RequestMapping("/hello")
  public String hello(String username,String password){
    System.out.println("hello");
    return "index";
  }
}
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.

2.2郎笆、注解詳解

2.2.1、@Controller

該注解用來類上標(biāo)識(shí)這是一個(gè)控制器組件類并創(chuàng)建這個(gè)類實(shí)例忘晤,告訴spring我是一個(gè)控制器宛蚓。

2.2.2、@RequestMapping

這個(gè)注解可以作用在方法上或者是類上设塔,用來指定請(qǐng)求路徑凄吏。

2.3、SpringMVC的跳轉(zhuǎn)方式

傳統(tǒng)的Servlet開發(fā)跳轉(zhuǎn)方式有兩種:

  1. forward:forward跳轉(zhuǎn)闰蛔,是在服務(wù)器內(nèi)部跳轉(zhuǎn)痕钢,所以是一次請(qǐng)求,地址欄不變序六。跳轉(zhuǎn)時(shí)可以攜帶數(shù)據(jù)進(jìn)行傳遞(使用request作用域進(jìn)行傳遞)任连。
  2. redirect:redirect跳轉(zhuǎn)是客戶端跳轉(zhuǎn),所以是多次請(qǐng)求,地址欄會(huì)改變难咕,跳轉(zhuǎn)時(shí)不可以攜帶數(shù)據(jù)傳遞课梳。

2.3.1距辆、Controller ——>前臺(tái)頁面

2.3.1.1、forward

通過測(cè)試我們可以發(fā)現(xiàn)暮刃,SpringMVC默認(rèn)的就是使用請(qǐng)求轉(zhuǎn)發(fā)的方式來進(jìn)行跳轉(zhuǎn)到前臺(tái)頁面的;

@Controller
@RequestMapping("forwoartAndRedirect")
public class TestForwoartAndRedirect {

  @RequestMapping("test")
  public String test(){
    System.out.println("test");
    return"index";
  }
}1.2.3.4.5.6.7.8.9.10.
2.3.1.2跨算、redirect

如果我們想使用重定向的方式來進(jìn)行跳轉(zhuǎn)的話,需要使用SpringMVC提供給我們的關(guān)鍵字——redirect:來完成椭懊。

語法:return "redirect:/視圖全路徑名";

**注意:**在redirect:后接頁面的不是邏輯名诸蚕,而是全路徑名。因?yàn)閞edirect跳轉(zhuǎn)不會(huì)經(jīng)過視圖解析器氧猬。

2.3.1Controller ——>Controller

2.3.1.1背犯、forward

如果我們想使用請(qǐng)求轉(zhuǎn)發(fā)的方式跳轉(zhuǎn)到相同(不同)Controller的不同方法的時(shí)候,我們也需要使用SpringMVC提供的關(guān)鍵字:forward:盅抚。

語法:return:"forward: /需要跳轉(zhuǎn)的類上的@RequestMapping的值/需要跳轉(zhuǎn)的方法上的@RequestMapping的值;"

2.3.1.2漠魏、redirect

如果我們想使用重定向的方式跳轉(zhuǎn)到相同(不同)Controller的不同方法的時(shí)候,我們也需要使用SpringMVC提供的關(guān)鍵字:redirect:妄均。

語法:return:"redirect: /需要跳轉(zhuǎn)的類上的@RequestMapping的值/需要跳轉(zhuǎn)的方法上的@RequestMapping的值;"

2.4柱锹、SpringMVC的參數(shù)接收

2.4.1、Servlet接收參數(shù)的方式

在傳統(tǒng)的Servlet開發(fā)丰包,我們一般都是用這種方式來進(jìn)行接收請(qǐng)求參數(shù)的禁熏。

// 接收名字為name的參數(shù)
request.getParameter(name)1.2.

他有幾個(gè)需要注意的點(diǎn):

  1. 參數(shù)要求是表單域的name屬性。
  2. getParameter方法用于獲取單個(gè)值, 返回類型是String邑彪。
  3. getParameterValues方法用于獲取一組數(shù)據(jù), 返回結(jié)果是String[]瞧毙。
  4. 冗余代碼較多, 使用麻煩, 類型需要自己轉(zhuǎn)換。

2.4.2寄症、SpringMVC的參數(shù)接收

SpringMVC使用的是控制器中方法形參列表來接收客戶端的請(qǐng)求參數(shù)宙彪,他可以進(jìn)行自動(dòng)類型轉(zhuǎn)換,要求傳遞參數(shù)的key要與對(duì)應(yīng)方法的形參變量名一致才可以完成自動(dòng)賦值有巧。他的優(yōu)勢(shì)很明顯:

  1. 簡(jiǎn)化參數(shù)接收形式(不需要調(diào)用任何方法, 需要什么參數(shù), 就在控制器方法中提供什么參數(shù))您访。
  2. 參數(shù)類型不需要自己轉(zhuǎn)換了。日期時(shí)間(默認(rèn)為yyyy/MM/dd)得注意剪决,需要使用@DateTimeFormat注解聲明日期轉(zhuǎn)換時(shí)遵循的格式, 否則拋出400異常。
2.4.2.1檀训、基本數(shù)據(jù)類型

要求傳遞參數(shù)的key要與對(duì)應(yīng)方法的形參變量名一致才可以完成自動(dòng)賦值柑潦。

2.4.2.2、對(duì)象類型

如果我們需要接收對(duì)象類型的話峻凫,直接將需要接收的對(duì)象作為控制器的方法參數(shù)聲明即可渗鬼。SpringMVC會(huì)自動(dòng)封裝對(duì)象,若傳遞參數(shù)key與對(duì)象中屬性名一致荧琼,就會(huì)自動(dòng)封裝成對(duì)象譬胎。

2.4.2.3差牛、數(shù)組類型

如果我們需要接收數(shù)組類型的時(shí)候,只需將要接收的數(shù)組類型直接聲明為方法的形式參數(shù)即可堰乔。

2.4.2.4偏化、集合類型

SpringMVC不能直接通過形式參數(shù)列表的方式接收集合類型的參數(shù),如果需要接收集合類型的參數(shù)必須將集合放入一個(gè)對(duì)象中镐侯,并且提供get/set方法侦讨,才可以。推薦放入VO對(duì)象中進(jìn)行封裝苟翻,進(jìn)而使用對(duì)象類型來進(jìn)行接收韵卤。

2.5、SpringMVC接收參數(shù)中文亂碼問題

2.5.1崇猫、GET請(qǐng)求

GET請(qǐng)求方式出現(xiàn)亂碼需要分Tomcat版本進(jìn)行討論:

  1. Tomcat8.x版本之前:默認(rèn)使用server.xml中的URIEncoding="ISO-8859-1"編碼沈条,而不是"UTF-8"編碼,進(jìn)而會(huì)出現(xiàn)中文亂碼诅炉。
  2. Tomcat8.x版本之后:默認(rèn)使用server.xml中的URIEncoding="UTF-8"蜡歹,所以不會(huì)出現(xiàn)中文亂碼問題。

2.5.2汞扎、POST請(qǐng)求

SpringMVC中默認(rèn)沒有對(duì)POST請(qǐng)求進(jìn)行任何編碼處理季稳,所以無論什么版本直接接收POST請(qǐng)求都會(huì)出現(xiàn)中文亂碼。

2.5.2.1澈魄、自定義過濾器解決POST亂碼請(qǐng)求

在Servlet階段景鼠,我們學(xué)過過濾器,我們可以自定義過濾器來進(jìn)行過濾編碼痹扇。

package com.filter;

import javax.servlet.*;
import java.io.IOException;

//自定義編碼filter
public class CharacterEncodingFilter  implements Filter {

    private String encoding;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.encoding = filterConfig.getInitParameter("encoding");
        System.out.println(encoding);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.
 <!--配置post請(qǐng)求方式中文亂碼的Filter-->
  <filter>
    <filter-name>charset</filter-name>
    <filter-class>com.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>charset</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>1.2.3.4.5.6.7.8.9.10.11.12.13.14.
2.5.2.2铛漓、使用CharacterEncodingFilter解決POST亂碼請(qǐng)求
  <!--配置post請(qǐng)求方式中文亂碼的Filter-->
  <filter>
    <filter-name>charset</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>charset</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.
package com.filter;

import javax.servlet.*;
import java.io.IOException;

//自定義編碼filter
public class CharacterEncodingFilter  implements Filter {

    private String encoding;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.encoding = filterConfig.getInitParameter("encoding");
        System.out.println(encoding);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.

2.6、SpringMVC中數(shù)據(jù)傳遞機(jī)制

2.6.1鲫构、什么事數(shù)據(jù)傳遞機(jī)制

數(shù)據(jù)傳遞機(jī)制主要包含三個(gè)問題:

  1. 數(shù)據(jù)如何存儲(chǔ)浓恶?
  2. 如何在頁面中獲取數(shù)據(jù)?
  3. 在頁面中獲取的數(shù)據(jù)該如何展示结笨?

2.6.2包晰、Servlet的數(shù)據(jù)傳遞機(jī)制

在以前的Servlet開發(fā)中,我們一般是將數(shù)據(jù)放入作用域(request炕吸、session伐憾、application),如果數(shù)據(jù)是單個(gè)的直接用EL表達(dá)式在前端進(jìn)行展示赫模,如果是集合或者數(shù)組树肃,可以用EL表達(dá)式?JSTL標(biāo)簽進(jìn)行遍歷后在前端進(jìn)行展示。

三瀑罗、前端控制器

3.1胸嘴、什么是前端控制器

在 MVC 框架中都存在一個(gè)前端控制器雏掠,在 WEB 應(yīng)用的前端(Front)設(shè)置一個(gè)入口控制器(Controller),是用來提供一個(gè)集中的請(qǐng)求處理機(jī)制劣像,所有的請(qǐng)求都被發(fā)往該控制器統(tǒng)一處理乡话,然后把請(qǐng)求分發(fā)給各自相應(yīng)的處理程序。一般用來做一個(gè)共同的處理驾讲,如權(quán)限檢查蚊伞,授權(quán),日志記錄等吮铭。因?yàn)榍岸丝刂频募刑幚碚?qǐng)求的能力时迫,因此提高了可重用性和可拓展性。

在沒有前端控制器的時(shí)候谓晌,我們是這樣傳遞和處理請(qǐng)求的掠拳。

image

有了前端控制器之后,我們變成了這樣纸肉。

image

3.2溺欧、代碼實(shí)現(xiàn)

Spring MVC 已經(jīng)提供了一個(gè) DispatcherServlet 類作為前端控制器,所以要使用 Spring MVC 必須在web.xml 中配置前端控制器柏肪。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">
  <!-- Spring MVC 前端控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-
      class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 指定 Spring 容器啟動(dòng)加載的配置文件-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:mvc.xml</param-value>
    </init-param>
    <!-- Tomcat 啟動(dòng)初始化 -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.

3.3姐刁、注意

load-on-startup 元素是可選的:若值為 0 或者大于 0 時(shí),表示容器在應(yīng)用啟動(dòng)時(shí)就構(gòu)建 Servlet 并調(diào)用其 init 方法做初始化操作(非負(fù)數(shù)的值越小烦味,啟動(dòng)該 Servlet 的優(yōu)先級(jí)越高)聂使;若值為一個(gè)負(fù)數(shù)時(shí)或者沒有指定時(shí),則在第一次請(qǐng)求該 Servlet 才加載谬俄。配置的話柏靶,就可以讓 SpringMVC 初始化的工作在容器啟動(dòng)的時(shí)候完成,而不是丟給用戶請(qǐng)求去完成溃论,提高用戶訪問的體驗(yàn)性屎蜓。

3.4、映射路徑

配置前端控制器的映射路徑一般有以下的三種形式:

  1. 配置如 .do钥勋、.htm 是最傳統(tǒng)方式炬转,可以訪問靜態(tài)文件(圖片、 JS算灸、 CSS 等)返吻,但不支持 RESTful風(fēng)格。
  2. 配置成 /乎婿,可以支持流行的 RESTful 風(fēng)格,但會(huì)導(dǎo)致靜態(tài)文件(圖片街佑、 JS谢翎、 CSS 等)被攔截后不能訪問捍靠。
  3. 配置成 /*,是錯(cuò)誤的方式森逮,可以請(qǐng)求到 Controller 中榨婆,但跳轉(zhuǎn)到調(diào)轉(zhuǎn)到 JSP 時(shí)被攔截,不能渲染JSP 視圖褒侧,也會(huì)導(dǎo)致靜資源訪問不了良风。

3.4.1、訪問靜態(tài)資源和 JSP 被攔截的原因

    Tomcat 容器處理靜態(tài)資源是交由內(nèi)置 DefaultServlet 來處理的(攔截路徑是 /)闷供,處理 JSP 資源是交由內(nèi)置的 JspServlet 處理的(攔截路徑是*.jsp | *.jspx)烟央。
    啟動(dòng)項(xiàng)目時(shí),先加載容器的 web.xml歪脏,而后加載項(xiàng)目中的 web.xml疑俭。當(dāng)攔截路徑在兩者文件中配置的一樣,后面會(huì)覆蓋掉前者婿失。
    所以前端控制器配置攔截路徑是 / 的所有靜態(tài)資源都會(huì)交由前端控制器處理钞艇,而攔截路徑配置 /*,所有靜態(tài)資源和 JSP 都會(huì)交由前端控制器處理豪硅。1.2.3.

3.4.2哩照、如何解決

3.4.2.1、方式一

在 web.xml 中修改懒浮,修改前端控制器的映射路徑修改為*.do飘弧,但注意,訪問控制器里的處理方法時(shí)嵌溢,請(qǐng)求路徑須攜帶 .do眯牧。

<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>  1.2.3.4.
3.4.2.2、方式二

在 mvc.xml中加入一段配置赖草,這個(gè)配置會(huì)在 Spring MVC 上下文中創(chuàng)建存入一個(gè)
DefaultServletHttpRequestHandler 的 bean学少,它會(huì) 對(duì)進(jìn)入DispatcherServlet的請(qǐng)求進(jìn)行篩查,若不是映射的請(qǐng)求秧骑,就將該請(qǐng)求交由容器默認(rèn)的 Servlet處理版确。

<mvc:default-servlet-handler/>1.

3.5、@ModelAttribute注解

在形參中的對(duì)象(必須是自定義類型)乎折,SpringMVC會(huì)默認(rèn)將他存入Model中绒疗,名稱是參數(shù)的類名首字母小寫,有些時(shí)候骂澄,這個(gè)類會(huì)顯得格外長(zhǎng)吓蘑,但是我們又有這種需求,比方說:查詢條件的回顯。我們只需在自定義類的前面加@ModelAttribute磨镶,里面寫我們需要修改的key的名稱即可溃蔫。

package cn.wolfcode.web.controller;
    @Controller
    public class RequestController {
        @RequestMapping("/req7")
            public String resp7(@ModelAttribute("u") User user) {
            return "m";
        }
}1.2.3.4.5.6.7.8.

四、處理響應(yīng)

SpringMVC的作用是請(qǐng)求和處理響應(yīng)琳猫,響應(yīng)處理是指怎么編寫控制器里面的處理方法接受請(qǐng)求做響應(yīng)伟叛,找視圖文件和往作用域中存入數(shù)據(jù)。要處理方法要做響應(yīng)脐嫂,一般處理方法返回的類型為 ModelAndView 和 String统刮。

4.1、返回 ModelAndView

方法中返回 ModelAndView 對(duì)象账千,此對(duì)象中設(shè)置模型數(shù)據(jù)并指定視圖侥蒙。前端依舊是使用JSTL+CgLib來進(jìn)行取值。他有兩個(gè)常用方法:

  1. addObject(String key, Object value):設(shè)置共享數(shù)據(jù)的 key 和 value蕊爵。
  2. addObject(Object value):設(shè)置共享數(shù)據(jù)的 value辉哥,key 為該 value 類型首字母小寫。
package cn.linstudy.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ResponseController {
  // 提供方法處理請(qǐng)求攒射,localhost/resp1
  @RequestMapping("/resp1")
  public ModelAndView resp1() {
// 通過創(chuàng)建這個(gè)類對(duì)象醋旦,告訴 Spring MVC 找什么視圖文件, 往作用域或者說往模型中存入什么數(shù)據(jù)
    ModelAndView mv = new ModelAndView();
// 往作用域或者模型中存入數(shù)據(jù)
    mv.addObject("msg", "方法返回類型是 ModelAndView");
// 找視圖
    mv.setViewName("/WEB-INF/views/resp.jsp");
    return mv;
  }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.

4.2会放、返回String

返回 String 類型(使用廣泛)饲齐,此時(shí)如果我們需要共享數(shù)據(jù),那么就需要用到HttpServlet對(duì)象咧最,Spring幫我們封裝好了一個(gè)對(duì)象:Model 捂人。組合使用,用其往作用域或模型中存入數(shù)據(jù)矢沿。

package cn.instudy.web.controller;

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

@Controller
public class ResponseController {
  // 提供方法處理請(qǐng)求滥搭,localhost/resp2
  @RequestMapping("/resp2")
  public String resp2(Model model) {
// 往作用域或者模型中存入數(shù)據(jù)
    model.addAttribute("msg", "方法返回類型是 String");
// 返回視圖名
    return "/WEB-INF/views/resp.jsp";
  }
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.

4.3、改進(jìn)

我們會(huì)發(fā)現(xiàn)捣鲸,如果我們需要寫返回界面的話需要不斷地寫前綴和后綴瑟匆,這個(gè)時(shí)候需要進(jìn)行消除消除視圖前綴和后綴,我們只需在Spring中進(jìn)行配置視圖解析器即可栽惶。

<!--
配置視圖解析器 配置這個(gè)Spring MVC 找視圖的路徑就是:前綴 + 邏輯視圖名(處理方法設(shè)置或返回視圖名)+ 后綴名
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- 視圖前綴 -->
    <property name="prefix" value="/WEB-INF/views/"/>
    <!-- 視圖后綴 -->
    <property name="suffix" value=".jsp"/>
</bean>1.2.3.4.5.6.7.8.9.

五愁溜、請(qǐng)求轉(zhuǎn)發(fā)和重定向

5.1、請(qǐng)求轉(zhuǎn)發(fā)和重定向的區(qū)別

幾次請(qǐng)求 地址欄 WEB-INF中資源 共享請(qǐng)求數(shù)據(jù) 有無表單重復(fù)提交
請(qǐng)求轉(zhuǎn)發(fā) 1次 不改變 可以訪問 可以共享
重定向 多次 改變 不可訪問 不可共享

5.2外厂、請(qǐng)求轉(zhuǎn)發(fā)

加上forward 關(guān)鍵字冕象,表示請(qǐng)求轉(zhuǎn)發(fā),相當(dāng)于
request.getRequestDispatcher().forward(request,response)汁蝶,轉(zhuǎn)發(fā)后瀏覽器地址欄不變渐扮,共享之前請(qǐng)求中的數(shù)據(jù)。加了關(guān)鍵字后,配置的視圖解析器就不起作用了墓律。如果返回視圖必須寫全路徑

package cn.linstudy.web.controller;
@Controller
public class ResponseController {

    @RequestMapping("/TestForward")
    public String forward() {
        return "forward:/WEB-INF/views/welcome.jsp";
    }
}1.2.3.4.5.6.7.8.9.

5.3意荤、重定向

加上 redirect 關(guān)鍵字,表示重定向只锻,相當(dāng)于 response.sendRedirect(),重定向后瀏覽器地址欄變?yōu)橹囟ㄏ蚝蟮牡刂纷瞎龋还蚕碇罢?qǐng)求的數(shù)據(jù)齐饮。

package cn.linstudy.web.controller;
@Controller
public class ResponseController {
    // localhost/r
    @RequestMapping("/TestRedirect")
    public String redirect() {
        return "redirect:/static/demo.html";
    }
}1.2.3.4.5.6.7.8.9.

5.4、請(qǐng)求路徑

在請(qǐng)求轉(zhuǎn)發(fā)和重定向的時(shí)候笤昨,我們一般有兩種方式來寫請(qǐng)求路徑:

  1. 加/:使用是絕對(duì)路徑(推薦使用)祖驱,從項(xiàng)目根路徑找。(/response/test6 ---> "redirect:/hello.html" ---> localhost:/hello.html)
  2. 不加/:使用是相對(duì)路徑瞒窒,相對(duì)于上一次訪問上下文路徑的上一級(jí)找捺僻。(/response/test6 ---> "redirect:hello.html" ---> localhost:/response/hello.html)

六、參數(shù)處理

6.1崇裁、處理簡(jiǎn)單類型的請(qǐng)求參數(shù)

我們?cè)诳刂破鞯娜绾潍@取請(qǐng)求中的簡(jiǎn)單數(shù)據(jù)類型的參數(shù)參數(shù)匕坯?簡(jiǎn)單數(shù)據(jù)類型包含基本數(shù)據(jù)類型及其包裝類、String 和BigDecimal 等形參接收拔稳。

6.1.1葛峻、請(qǐng)求參數(shù)名和控制器方法參數(shù)列表形參同名

如果前臺(tái)傳遞過來的參數(shù)名和控制器方法中參數(shù)列表的形參參數(shù)名相同就無需做任何操作,SpringMVC會(huì)自動(dòng)幫我們進(jìn)賦值巴比。

 // 請(qǐng)求路徑為:/req1?username=zs&age=18
package cn.linstudy.web.controller;
    @Controller
    public class RequestController {
        @RequestMapping("/req1")
        public ModelAndView resp1(String username, int age) {
            System.out.println(username);
            System.out.println(age);
            return null;
        }
}1.2.3.4.5.6.7.8.9.10.11.

6.1.2术奖、請(qǐng)求參數(shù)名和控制器方法參數(shù)列表形參不同名

如果前臺(tái)傳遞過來的參數(shù)名和控制器方法中參數(shù)列表的形參參數(shù)名不相同的話,我們需要使用一個(gè)注解@RequestParam("前臺(tái)攜帶的參數(shù)名")來告訴SpringMVC我們?nèi)魏螌?duì)數(shù)據(jù)來進(jìn)行賦值轻绞。

 // 請(qǐng)求路徑為:/req1?username=zs&age=18
package cn.linstudy.web.controller;
    @Controller
    public class RequestController {
        @RequestMapping("/req1")
        public ModelAndView resp1(@RequestParam("username") String username1, @RequestParam("age") int age1) {
            System.out.println(username);
            System.out.println(age);
            return null;
        }
}1.2.3.4.5.6.7.8.9.10.11.

6.2采记、處理復(fù)雜類型的請(qǐng)求參數(shù)

6.2.1、數(shù)組類型

對(duì)于數(shù)組類型參數(shù)政勃,我們只需在方法參數(shù)的形參列表中定義一個(gè)同名的數(shù)組類型進(jìn)行接收即可唧龄。

// 請(qǐng)求路徑 /req3?ids=1&ids=2&ids=3
package cn.linstudy.web.controller;
    @Controller
    public class RequestController {
        @RequestMapping("/req3")
        public ModelAndView resp3(Long[] ids) {
            System.out.println(Arrays.toString(ids));
            return null;
        }
}1.2.3.4.5.6.7.8.9.10.

6.2.2、自定義類型

我們?cè)诤芏嗟臅r(shí)候稼病,需要接收的是一個(gè)自定義類型的對(duì)象选侨。比如說我們進(jìn)行保存用戶,需要將前臺(tái)傳遞的數(shù)據(jù)進(jìn)行封裝成一個(gè)自定義的用戶類型然走,那么這個(gè)時(shí)候援制,只需要保證自定義的類型里面的字段和前端傳過來的字段相同(注意傳遞參數(shù)名與封裝對(duì)象的屬性名一致),SpringMVC即可自動(dòng)進(jìn)行封裝芍瑞。

// /req4?username=hehe&password=666
package cn.linstudy.web.controller; 
    @Controller
    public class RequestController {
        @RequestMapping("/req4")
        public ModelAndView resp4(User user) {
            System.out.println(user);
            return null
        }
}1.2.3.4.5.6.7.8.9.10.

底層 Spring MVC 根據(jù)請(qǐng)求地址對(duì)應(yīng)調(diào)用處理方法晨仑,調(diào)用方法時(shí)發(fā)現(xiàn)要傳遞 User 類型的實(shí)參,SpringMVC 會(huì)反射創(chuàng)建 User 對(duì)象,之后通過請(qǐng)求參數(shù)名找對(duì)應(yīng)的屬性洪己,給對(duì)象的屬性設(shè)置對(duì)應(yīng)的參數(shù)值妥凳。

6.3、處理日期類型的請(qǐng)求參數(shù)

6.3.1答捕、日期在請(qǐng)求參數(shù)上

如果日期在請(qǐng)求參數(shù)上逝钥,那么我們需要在處理方法的 Date 類型的形參貼上 @DateTimeFormat注解。

package cn.linstudy.controller;
    @Controller
    public class RequestController {
        @RequestMapping("/req5")
        // 注意形參的類型為 java.util.Date
        public ModelAndView resp5(@DateTimeFormat(pattern="yyyy-MM-dd")Date date) {
            System.out.println(date.toLocaleString());
            return null;
        }
}1.2.3.4.5.6.7.8.9.10.

6.3.2拱镐、在封裝的對(duì)象上

如果日期在封裝對(duì)象的字段艘款,那么我們需要在字段的上貼@DateTimeFormat注解。

package cn.linstudy.domain;
    public class User {
    private Long id;
    private String Username;
    private String password;
    // 增加下面這個(gè)字段沃琅,并貼注解
    @DateTimeFormat(pattern="yyyy-MM-dd")
    private Date date;
    // 省略 setter getter toString
}1.2.3.4.5.6.7.8.9.10.
    package cn.linstudy.controller;
    @Controller
    public class RequestController {
        @RequestMapping("/req6")
        public ModelAndView resp6(User user) {
            System.out.println(user);
            return null;
        }
}1.2.3.4.5.6.7.8.9.

七哗咆、文件上傳與下載

7.1、文件上傳

回顧之前使用 Servlet3.0 來解決文件上傳的問題益眉,編寫上傳表單(POST晌柬、multipart/form-data),還在處理方法 doPost 中編寫解析上傳文件的代碼郭脂。但是在SpringMVC是可以幫我們簡(jiǎn)化文件上傳的步驟和代碼年碘。

7.1.1、編寫表單

注意請(qǐng)求數(shù)據(jù)類型必須是:multipart/form-data朱庆,且請(qǐng)求方式是POST盛泡。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文件上傳</title>
</head>
<body>
    <form action="/upload" method="POST" enctype="multipart/form-data">
        文件:<input type="file" name="pic"><br>
        <input type="submit" value="提交"/>
    </form>
</body>
</html>1.2.3.4.5.6.7.8.9.10.11.12.13.

7.1.2、修改web.xml

我們可以在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:mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <multipart-config>
        <max-file-size>52428800</max-file-size>
        <max-request-size>52428800</max-request-size>
    </multipart-config>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.

7.1.3傲诵、配置上傳解析器

在mvc.xml中配置上傳解析器,使用springmvc中multipartfile接收客戶端上傳的文件必須配置文件上傳解析器且解析的id必須為multipartResolver

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <!--控制文件上傳大小單位字節(jié) 默認(rèn)沒有大小限制 這里是2-->
  <property name="maxUploadSize" value="2097152"/>
</bean>1.2.3.4.

7.1.4箱硕、配置上傳控制器

package cn.linstudy.controller;
    @Controller
    public class UploadController {
    // Spring 容器存在 ServletContext 類型的對(duì)象拴竹,所以定義好 ServletContext 類型字段貼@Autowired 注解即可獲取到
    @Autowired
    private ServletContext servletContext;
    @RequestMapping("/upload")
    public ModelAndView upload(Part pic) throws Exception {
        System.out.println(pic.getContentType()); // 文件類型
        System.out.println(pic.getName()); // 文件參數(shù)名
        System.out.println(pic.getSize()); // 文件大小
        System.out.println(pic.getInputStream()); // 文件輸入流
        // FileCopyUtils.copy(in, out),一個(gè) Spring 提供的拷貝方法
        // 獲取項(xiàng)目 webapp 目錄下 uploadDir 目錄的絕對(duì)路徑
        System.out.println(servletContext.getRealPath("/uploadDir"));
        return null;
    }
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.

7.2剧罩、文件下載

文件下載:將服務(wù)器上的文件下載到當(dāng)前用戶訪問的計(jì)算機(jī)的過程稱之為文件下載

7.2.1栓拜、開發(fā)控制器

下載時(shí)必須設(shè)置響應(yīng)的頭信息,指定文件以何種方式保存,另外下載文件的控制器不能存在返回值,代表響應(yīng)只用來下載文件信息

    /**
     * 測(cè)試文件下載
     * @param fileName 要下載文件名
     * @return
     */
    @RequestMapping("download")
    public String download(String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //獲取下載服務(wù)器上文件的絕對(duì)路徑
        String realPath = request.getSession().getServletContext().getRealPath("/down");
        //根據(jù)文件名獲取服務(wù)上指定文件
        FileInputStream is = new FileInputStream(new File(realPath, fileName));
        //獲取響應(yīng)對(duì)象設(shè)置響應(yīng)頭信息
        response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));
        ServletOutputStream os = response.getOutputStream();
        IOUtils.copy(is,os);
        IOUtils.closeQuietly(is);
        IOUtils.closeQuietly(os);
        return null;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市惠昔,隨后出現(xiàn)的幾起案子幕与,更是在濱河造成了極大的恐慌,老刑警劉巖镇防,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啦鸣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡来氧,警方通過查閱死者的電腦和手機(jī)诫给,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門香拉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人中狂,你說我怎么就攤上這事凫碌。” “怎么了胃榕?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵盛险,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我勋又,道長(zhǎng)枉层,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任赐写,我火速辦了婚禮,結(jié)果婚禮上膜赃,老公的妹妹穿的比我還像新娘挺邀。我一直安慰自己,他們只是感情好跳座,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布端铛。 她就那樣靜靜地躺著,像睡著了一般疲眷。 火紅的嫁衣襯著肌膚如雪禾蚕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天狂丝,我揣著相機(jī)與錄音换淆,去河邊找鬼。 笑死几颜,一個(gè)胖子當(dāng)著我的面吹牛倍试,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蛋哭,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼县习,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了谆趾?” 一聲冷哼從身側(cè)響起躁愿,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沪蓬,沒想到半個(gè)月后彤钟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怜跑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年样勃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吠勘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡峡眶,死狀恐怖剧防,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辫樱,我是刑警寧澤峭拘,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站狮暑,受9級(jí)特大地震影響鸡挠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜搬男,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一拣展、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缔逛,春花似錦备埃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至敦冬,卻和暖如春辅搬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背脖旱。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工堪遂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人萌庆。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓蚤氏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親踊兜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子竿滨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

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

  • SSH通常指的是 Struts2 做前端控制器于游,Spring 管理各層的組件,Hibernate 負(fù)責(zé)持久化層垫言。 ...
    996小遷閱讀 444評(píng)論 0 1
  • 1贰剥、什么是MVC 2、什么是SpringMVC 3筷频、SpringMVC的特點(diǎn) 1蚌成、開發(fā)環(huán)境 2前痘、創(chuàng)建maven工程...
    小茅同學(xué)閱讀 273評(píng)論 0 0
  • 一、SpringMVC 1.1 引言1.2 MVC架構(gòu)1.2.1 概念1.2.2 好處 二担忧、開發(fā)流程 2.1 導(dǎo)入...
    dddye閱讀 241評(píng)論 0 0
  • SpringMVC 一芹缔、SpringMVC概述 1. 三層架構(gòu) 服務(wù)器端開發(fā)程序主要由兩種形式構(gòu)成。一種是基于客戶...
    青丶空閱讀 384評(píng)論 0 1
  • 1. MVC模式 使用MVC模式的目的:將M和V的實(shí)現(xiàn)代碼分離瓶盛,從而使同一個(gè)程序可以使用不同的表現(xiàn)形式最欠。C存在的目...
    皇天閱讀 170評(píng)論 0 0