一豹休、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ì)
SpringMVC是一個(gè)典型的輕量級(jí)MVC框架凤巨,在整個(gè)MVC架構(gòu)中充當(dāng)控制器框架,相對(duì)于之前的struts2框架,SpringMVC運(yùn)行更快,其注解式開發(fā)更高效靈活。
- 可以和Spring框架無縫整合医窿。
- 運(yùn)行效率遠(yuǎn)遠(yuǎn)高于struts2框架磅甩。
- 注解式開發(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)方式有兩種:
- forward:forward跳轉(zhuǎn)闰蛔,是在服務(wù)器內(nèi)部跳轉(zhuǎn)痕钢,所以是一次請(qǐng)求,地址欄不變序六。跳轉(zhuǎn)時(shí)可以攜帶數(shù)據(jù)進(jìn)行傳遞(使用request作用域進(jìn)行傳遞)任连。
- 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):
- 參數(shù)要求是表單域的name屬性。
- getParameter方法用于獲取單個(gè)值, 返回類型是String邑彪。
- getParameterValues方法用于獲取一組數(shù)據(jù), 返回結(jié)果是String[]瞧毙。
- 冗余代碼較多, 使用麻煩, 類型需要自己轉(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ì)很明顯:
- 簡(jiǎn)化參數(shù)接收形式(不需要調(diào)用任何方法, 需要什么參數(shù), 就在控制器方法中提供什么參數(shù))您访。
- 參數(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)行討論:
- Tomcat8.x版本之前:默認(rèn)使用server.xml中的URIEncoding="ISO-8859-1"編碼沈条,而不是"UTF-8"編碼,進(jìn)而會(huì)出現(xiàn)中文亂碼诅炉。
- 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è)問題:
- 數(shù)據(jù)如何存儲(chǔ)浓恶?
- 如何在頁面中獲取數(shù)據(jù)?
- 在頁面中獲取的數(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)求的掠拳。
有了前端控制器之后,我們變成了這樣纸肉。
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、映射路徑
配置前端控制器的映射路徑一般有以下的三種形式:
- 配置如 .do钥勋、.htm 是最傳統(tǒng)方式炬转,可以訪問靜態(tài)文件(圖片、 JS算灸、 CSS 等)返吻,但不支持 RESTful風(fēng)格。
- 配置成 /乎婿,可以支持流行的 RESTful 風(fēng)格,但會(huì)導(dǎo)致靜態(tài)文件(圖片街佑、 JS谢翎、 CSS 等)被攔截后不能訪問捍靠。
- 配置成 /*,是錯(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è)常用方法:
- addObject(String key, Object value):設(shè)置共享數(shù)據(jù)的 key 和 value蕊爵。
- 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)求路徑:
- 加/:使用是絕對(duì)路徑(推薦使用)祖驱,從項(xiàng)目根路徑找。(/response/test6 ---> "redirect:/hello.html" ---> localhost:/hello.html)
- 不加/:使用是相對(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;