Spring MVC
是當(dāng)前最優(yōu)秀的MVC框架坐漏,自從Spring 2.5版本發(fā)布后充岛,由于支持注解配置盹憎,易
用性有了大幅度的提高敦姻。Spring 3.0更加完善瘾境,實現(xiàn)了對老牌的MVC框架Struts 2的超越。
現(xiàn)在版本已經(jīng)到了Spring5.x了镰惦,我們這門課程是基于Spring5.0.6的SpringMVC框架來寫案
例〖娜福現(xiàn)在越來越多的開發(fā)團(tuán)隊選擇了Spring MVC。
springmvc開發(fā)大概步驟:maven web 工程名: springmvcdemo
-
springmvc需要的包:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
-
在web.xml中配置DispatcherServlet.
注意:打開web.xml 按ctrl+shift+f 格式一下文檔陨献,再 <web-app xxxxxxxxxxxxx/>中盒犹,去掉 /,再加 </web-app>
在<web-app>中:按alt+/,找到--如圖所示:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1" >
<!-- 使用spring mvc ,springmvc的核心的調(diào)度器眨业,servlet中配置來 -->
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--指定springmvc的配置文件的所在的位置 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 指定url地址 -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern> <!--根目錄下的所有地址急膀,包括靜態(tài)資源,jsp等龄捡,但不包括卓嫂,其它servlet
強(qiáng)調(diào)一點:不要配成/* , /*一般情況下配在過濾器中 -->
</servlet-mapping>
</web-app>
-
加入SpringMVC的spring配置文件
配置文件,配置注解所在的包聘殖,為mvc指定視圖解析器晨雳。
<?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-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">
<!-- 指定注解所在的基本包 -->
<context:component-scan base-package="cn.ybzy.springmvcdemo"></context:component-scan>
<!-- 為springmvc指定視較長解析器 -->
<bean id ="" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property> <!-- 文件前綴 -->
<property name="suffix" value=".jsp"></property> <!-- 文件后綴 -->
</bean>
</beans>
-
搭好架子,建好所有要的包奸腺,和jsp文件(該類文件一般放在/WEB-INF/jsp中---安全餐禁,直接訪問不到)
- 建好控制類,做好顯示頁(jsp或html)突照,該類控制類不去執(zhí)行HttpServlet類來做控制邏輯帮非,已經(jīng)可以用注解@Controller方式注解成sevlet.可以跳轉(zhuǎn)。如下代碼:它可以返回index.jsp頁。
index.jsp
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class IndexController {
@RequestMapping("/index") //映射index.jsp頁面
public String index() {
return "index"; //返回對應(yīng)的視圖(jsp頁面)的名字末盔,不寫前后綴
}
}
測試:
啟動TOMCAT,瀏覽器地址欄中輸入:http://localhost:8081/springmvcdemo/index 回車筑舅,注意不要輸后綴,后綴由spring xml文件配置好了陨舱。
這個例子的大致流程分析:
一些注解說明
1@Controller
注解該類為一個Servlet 對象放到IOC容器中翠拣,也就是如同HttpServlet類對象。
2 @RequestMapping
是 Spring Web 應(yīng)用程序中最常被用到的注解之一游盲。這個注解會將HTTP 請求映射到控制器(controller類)的處理方法上误墓。
Request Mapping 基礎(chǔ)用法
在 Spring MVC 應(yīng)用程序中, RequestDispatcher ( 在 Front Controller 之下 ) 這個 servlet 負(fù)責(zé)將進(jìn)入的 HTTP 請求路由到控制器的處理方法背桐。在對 Spring MVC 進(jìn)行的配置的時候 , 需要我們指定請求與處理方法之間的映射關(guān)系优烧。
指定映射關(guān)系,就需要我們用上 @RequestMapping 注解链峭。
@RequestMapping 注解在前面的例子中是在方法的級別上使用畦娄。除此外,這個注解還可使用在類級別的:
在類的級別上的注解會將一個特定請求或者請求模式映射到一個控制器之上弊仪。之后才是另外添加在方法級別的注解來進(jìn)一步指定到處理方法的映射關(guān)系熙卡。
下面是一個同時在類和方法上應(yīng)用了 @RequestMapping 注解的示例:
說白了,體現(xiàn)在瀏覽器上訪問地址上励饵,就是父目錄:/index/index
RequestMapping里面的注解包含的參數(shù):
- value 驳癌, method(path等于value,要是見到有寫path代就理解為value)
value( 別名path) : :指定請求的實際地址,指定的地址可以是URI Template 模式役听;
多個地址可以寫成一個數(shù)組形形:value={"/index","/",""}颓鲜,即運行時,只需輸入項目名也可進(jìn)入到頁面典予。
value的uri值為以下三類:
B類通配符:
RequestMapping注解中的映射請求可以支持3中通配符:
1甜滨、?:匹配文件中的一個字符
2瘤袖、* :匹配任意字符
3衣摩、** :匹配多層路徑
B類示例:在地址欄中輸入: http://localhost:8080/springmvcdemo/index/10 回車,控制臺會輸出:ids===10
http://localhost:8080/springmvcdemo/index/a/10 回車捂敌,控制臺會輸出:ids===10
http://localhost:8080/springmvcdemo/index/aa/10 回車艾扮,控制臺會輸出:ids===10
三種代碼如下:
@Controller
public class IndexController {
@RequestMapping("/index/{id}")
public String index(@PathVariable(value="id") int ids) {
System.out.println("ids===="+ids);
return "index"; //返回對應(yīng)的視圖(jsp頁面文件名字)的名字,不寫前后綴
}
}
@Controller
public class IndexController {
@RequestMapping("/index/*/{id}")
public String index(@PathVariable(value="id") int ids) {
System.out.println("ids===="+ids);
return "index"; //返回對應(yīng)的視圖(jsp頁面文件名字)的名字占婉,不寫前后綴
}
}
@Controller
public class IndexController {
@RequestMapping("/index/**/{id}")
public String index(@PathVariable(value="id") int ids) {
System.out.println("ids===="+ids);
return "index"; //返回對應(yīng)的視圖(jsp頁面文件名字)的名字泡嘴,不寫前后綴
}
}
method: 默認(rèn)會自動匹配GET或POST請求,可以指定請求的method類型 取值可以是GET锐涯、POST磕诊、PUT、DELETE等纹腌;舉例說明一下method霎终,看 JSP 頁面:http://localhost:8080/springmvcdemo/index/10 回車后,會出現(xiàn)HTTP狀態(tài) 405 - 方法不允許錯誤升薯,因為它指定POST,而我們這樣的請求是GET.
@Controller
public class IndexController {
@RequestMapping(value="/index/{id}",method=RequestMethod.POST)
public String index(@PathVariable(value="id") int ids) {
System.out.println("ids===="+ids);
return "index"; //返回對應(yīng)的視圖(jsp頁面文件名字)的名字莱褒,不寫前后綴
}
}
- consumes,produces涎劈;
consumes: 指定處理請求的提交內(nèi)容類型( Content-Type ) 例如 application/json, text/html;
TOMCAT 服務(wù)支持的類型可以到其根目錄下/conf/web.xml中查看广凸,如:
<!-- ===================== Default MIME Type Mappings =================== -->
<!-- When serving static resources, Tomcat will automatically generate -->
<!-- a "Content-Type" header based on the resource's filename extension, -->
<!-- based on these mappings. Additional mappings can be added here (to -->
<!-- apply to all web applications), or in your own application's web.xml -->
<!-- deployment descriptor. -->
<!-- Note: Extensions are always matched in a case-insensitive manner. -->
<mime-mapping>
<extension>123</extension>
<mime-type>application/vnd.lotus-1-2-3</mime-type>
</mime-mapping>
舉例:
上述代碼中加一個WEB-INF/jsp/success.jsp頁面。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>測試@RequestMapping的參數(shù)Consumes</title>
</head>
<body>
<h4>提交成功</h4>
</body>
</html>
index.jsp: 加一個表單蛛枚,表單跳轉(zhuǎn)到映射類方法中
<title>Insert title here</title>
</head>
<body>
<h4>這是index首頁</h4>
<form action="${pageContext.request.contextPath}/testConsumes" method="POST">
<input type="text" value="aaa" /> <input type="submit" value="提交" />
</form>
</body>
</html>
映射頁面控制類中IndexController.java中代碼如下:
@Controller
public class IndexController {
@RequestMapping(value="/index/{id}")// ,method=RequestMethod.POST)
public String index(@PathVariable(value="id") int ids) {
System.out.println("ids===="+ids);
return "index"; //返回對應(yīng)的視圖(jsp頁面文件名字)的名字谅海,不寫前后綴 ,跳到index.jsp中。
//測試:http://localhost:8080/springmvcdemo/index/10 回車蹦浦,控制臺可以看到 ids====10
}
@RequestMapping(value="/testConsumes",method=RequestMethod.POST,consumes="application/json")
public String testConsumes() {
System.out.println("進(jìn)來的comsumes方法");
return "success"; //跳轉(zhuǎn)到success.jsp
}
}
測試:
http://localhost/springmvcdemo/index/10 回車扭吁,跳 轉(zhuǎn)到index.jsp
從首頁index.jsp進(jìn)入頁,提交請求給success.jsp頁面盲镶,頁控制類中又設(shè)定的映射請求類型 application/json侥袜,若表單設(shè)置類型,會報
produces: 指定返回的內(nèi)容類型溉贿,僅當(dāng) request 請求頭中的 (Accept) 類型中包含該指定類型才返回枫吧;
這不用但心,絕大我數(shù)瀏覽器都能解術(shù)json格式數(shù)據(jù)宇色。
瀏覽器請求頭
該項表明可以接收任何類型的九杂,權(quán)重系數(shù)0.8表明如果前面幾種類型不能正常接收。則使用該項進(jìn)行自動分析宣蠕。 application/json 幾種主流瀏覽器都可以自動解析例隆。
- params,headers植影;
params : 指定 request 中必須包含某些參數(shù)值裳擎,才讓該方法處理。
參數(shù) username=tom思币;age = 10鹿响;
后臺代碼:設(shè)定必須包含username 和age兩個參數(shù),且age參數(shù)不為10 (可以有多個參數(shù))谷饿。
首頁提交age=10惶我,會產(chǎn)生錯誤。
狀態(tài)碼400表示:服務(wù)器未能理解請求博投。將age 改為其他值绸贡,正常跳轉(zhuǎn)。
headers: 指定 request 中必須包含某些指定的 header 值,才能讓該方法處理請求听怕。
查看請求頭的方法捧挺,進(jìn)入瀏覽器后,按F12,打開控制臺尿瞭,網(wǎng)絡(luò)闽烙,---》運行提交網(wǎng)頁,后声搁,可看到如下:
對照上圖的請求頭黑竞,我們測試一下,在上例的控制類中疏旨,提交請求映射方法中指定請求頭(瀏覽器中已存的)很魂,運行http://localhost:8080/springmvcdemo/index/10 回車進(jìn)入提交頁‘提交‘,會成功,若我們改一些內(nèi)容檐涝,可能不成功提交了遏匆。
@RequestMapping(value="/testConsumes",method=RequestMethod.POST,headers= {"Accept-Language=zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2"}/*consumes="application/json"*/)
public String testConsumes() {
System.out.println("進(jìn)來的comsumes方法");
return "success";
}
-
name
基于name值來構(gòu)建訪問的url,需要通過配置
spring xml中:
jsp頁面上:
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
請求動作發(fā)生時:
一般我們請求url這樣寫
<form action="${pageContext.request.contextPath}/testConsumes" method="POST">
配了name參功能的bean和jsp頁面的 taglib后骤铃,我們可以寫成
<form action="${s:mvcUrl('IC#testConsumes').build()}" method="POST">
這里要加IC#似乎不習(xí)慣拉岁,也不好看飒货,我們在相應(yīng)映射方法中加上name的屬性值-即方法名丹允『盎可以這樣寫:
@RequestMapping(value="/testConsumes",name="testConsumes")
public String testConsumes() {
System.out.println("進(jìn)來的comsumes方法");
return "success";
}
------------------------------------------------------------------------------------------------------------
<form action="${s:mvcUrl('testConsumes').build()}" method="POST">
3 @RequestParam
@RequestParam注解是在SpringMvc后臺進(jìn)行獲取參數(shù)數(shù)據(jù)的注解:
springmvc會自動根據(jù)參數(shù)名字來注入玫坛,所以要名字一致肆氓,不然不會注入
參數(shù)名字不一致的話于样,需要在@RequestParam后面指定參數(shù)名字媳友,才能為后面的參數(shù)進(jìn)行賦
值肥缔。
設(shè)置默認(rèn)值
如果要@RequestParam為一個int型的數(shù)據(jù)傳值丛版,假如前端并未輸入巩掺,那么將會為int型的數(shù)據(jù)賦值為null。顯然页畦,這是不允許的胖替,直接報錯。 可以設(shè)置默認(rèn)值為0來解決這種報錯情況豫缨!
可以通過required=false或者true來要求@RequestParam配置的前端參數(shù)是否一定要傳
4 注解@RequestHeader和@CookieValue
@RequestHeader和@CookieValue也是在SpringMvc后臺進(jìn)行獲取數(shù)據(jù)的注解独令,只不過不是前端傳來的參數(shù),而是前端請求的頭部信息和Cookie信息:
@RequestHeader 注解:可以把Request請求header部分的值綁定到方法的參數(shù)上好芭。
示例代碼:
這是一個Request 的header部分
后臺代碼
上面的代碼燃箭,把request header部分的 Accept-Encoding的值,綁定到參數(shù)encoding上了舍败, Keep-Alive header的值綁定到參數(shù)keepAlive上招狸。
@CookieValue
可以把Request header中關(guān)于cookie的值綁定到方法的參數(shù)上敬拓。
例如有如下Cookie值:
參數(shù)綁定的代碼:
即把JSESSIONID的值綁定到參數(shù)cookie上。
從JSP頁面里傳數(shù)據(jù)到SpringMVC中的Controller處理
-
直接讀取表單的數(shù)據(jù)裙戏。在控制器里的方法里乘凸,按照這種格式寫。
-
SpringMVC的參數(shù)映射問題:(JSP頁面或者說url路徑的參數(shù)同控制器里的方法的參數(shù)的對應(yīng))
1)第一種映射方式:
表單里的表單元素的name名字和控制器里的方法的形參名一致挽懦。
比如界面中的數(shù)據(jù):
在控制器里方法的定義:
2)采取普通的java對象(POJO)傳值的方式:
jsp頁面里的表單元素的name名字為java對象的字段名翰意。
比如:用戶的注冊頁面:
在控制器里的方法的定義:
3)通過url參數(shù)傳遞木人。將url的參數(shù)和形參進(jìn)行一個匹配:
Spring MVC中的模型數(shù)據(jù)處理(Controller響應(yīng)jsp)
Spring MVC 提供了以下途徑來輸出模型數(shù)據(jù):
1信柿、ModelAndView
當(dāng)處理方法返回值類型為 ModelAndView時, 方法體即可通過該對象添加模型數(shù)據(jù)到請求域。
2醒第、Map 及 Model和ModelMap
輸入?yún)?shù)為org.springframework.ui.Model渔嚷、org.springframework.ui.ModelMap 或java.uti.Map 時,處理方法返回時稠曼,Map中的數(shù)據(jù)會自動添加到模型中形病。
3、@SessionAttributes
該注解將模型中的某個屬性暫存到HttpSession 中霞幅,以便多個請求之間可以共享這個屬性漠吻。
4、@ModelAttribute: 方法輸入?yún)?shù)標(biāo)注該注解后, 入?yún)⒌膶ο缶蜁诺綌?shù)據(jù)模型中司恳。
ModelAndView和Map&Model&ModelMap
ModelAndView對象中包含了一個model屬性和一個view屬性途乃。
model:是一個ModelMap的類型。而ModelMap又是一個LinkedHashMap的子類扔傅。
view:包含了一些視圖信息耍共。
實現(xiàn)原理:
當(dāng)視圖解釋器解析ModelAndVIew類型的參數(shù)時,其中model是一個Map的實現(xiàn)類的子類猎塞,視圖解析器將model中的每個元素都通過request.setAttribute(name, value)方法试读,添加request請求域中。這樣就可以在JSP頁面中通過EL表達(dá)式來獲取對應(yīng)的值
操作方法:
添加模型數(shù)據(jù):
addObject(String attributeName, Object attributeValue)
設(shè)置視圖:
setViewName(String viewName)
11.ModelAndView方式荠耽,實際上就是map集合封裝
@RequestMapping("/testMV")
public ModelAndView MV() {
ModelAndView mView = new ModelAndView();
//注入字符串
mView.addObject("name","xiongshaowen");
//注一一個對象
User user =new User();
User user2= new User();
user.setId(1);
user.setAge(20);
user.setUsername("熊少文");
user2.setId(2);
user2.setAge(20);
user2.setUsername("徐會鳳");
mView.addObject("user",user);
mView.setViewName("success");
List<User> users = new ArrayList<User>();
users.add(user);
users.add(user2);
mView.addObject("users",users);
return mView;
}
success.jsp 視圖頁面
<%@ taglib prefix="s" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>測試@RequestMapping的參數(shù)Consumes</title>
</head>
<body>
<h4>提交成功</h4>
name: ${requestScope.name}
<h4>對象user</h4>
${requestScope.user}
<br><br>
<c:forEach var="user" items="${users }">
${user.username }
${user}
</c:forEach>
</body>
</html>
測試運行:
http://localhost:8080/springmvcdemo/testMV
- Map方式
@RequestMapping("/testMV")
public String test2MV(Map<String,Object> map) {
//注入字符串
map.put("name", "xiongsahwowen");
User user =new User();
User user2= new User();
user.setId(1);
user.setAge(20);
user.setUsername("熊少文");
user2.setId(2);
user2.setAge(20);
user2.setUsername("徐會鳳");
List<User> users = new ArrayList<User>();
users.add(user);
users.add(user2);
map.put("users", users);
return "success";
}
測試運行:
http://localhost:8080/springmvcdemo/testMV
13.Model方式
@RequestMapping("/testMV")
public String testMV3(Model model) {
//注入字符串
model.addAttribute("name","xiongshaowen");
User user =new User();
User user2= new User();
user.setId(1);
user.setAge(20);
user.setUsername("熊少文");
user2.setId(2);
user2.setAge(20);
user2.setUsername("徐會鳳");
List<User> users = new ArrayList<User>();
users.add(user);
users.add(user2);
model.addAttribute("users", users);
return "success";
}
測試運行:
http://localhost:8080/springmvcdemo/testMV
以上三種方式效果一樣:
. @SessionAttributes
如果我們希望在多個請求之間共用某個模型屬性數(shù)據(jù)钩骇,則可以在控制器類上標(biāo)注一個@SessionAttributes, Spring MVC 將把模型中對應(yīng)的屬性暫存到 HttpSession 的域中。
使用方法:
@SessionAttributes(value={"xxx铝量,xxx,xxxx"}/("xxxx"), types={xxxx.class}) 小括號表示一個對象鍵
@SessionAttributes(types=User.class)
value:是通過鍵來指定放入HttpSession 的域中的值倘屹;
types:是通過類型指定放入HttpSession 的域中的值;
該注解只能放在類的上面. 而不能修飾放方法款违。
這個注解會將類中所有放入Request域中的User對象同時放進(jìn)HttpSession的域空間中唐瀑。
@SessionAttributes(value= {"name","user"}) //name,user要與下面響應(yīng)方法中注入的字符串,對象的(鍵)名字一致插爹,這里不是鍵值對哄辣,兩個都是鍵请梢,表兩個注入。
@Controller
public class IndexController {
//3.Model方式注入
@RequestMapping("/testMV3")
public String testMV3(Model model) {
//注入字符串
model.addAttribute("name","xiongshaowen");
User user =new User();
User user2= new User();
user.setId(1);
user.setAge(20);
user.setUsername("熊少文");
user2.setId(2);
user2.setAge(20);
user2.setUsername("徐會鳳");
List<User> users = new ArrayList<User>();
users.add(user);
users.add(user2);
model.addAttribute("user",user); //該對象會注入到HttpSession域空間中
model.addAttribute("users", users);
return "success"; //跳轉(zhuǎn)到success.jsp中
}
}
success.jsp:
<%@ taglib prefix="s" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-----------------------------
<body>
<h4>提交成功</h4>
requestScope.name::::${requestScope.name} <br/><br/>
sessionScope.name::::${sessionScope.name}<br/><br/>
sessionScope.user::::${sessionScope.user}<br/>
-----------------
</body>
</html>
測試:http://localhost:8080/springmvcdemo/testMV3
結(jié)果:
若沒有加 @SessionAttributes(value= {"name","user"}) 在
public class IndexController{}
上的話力穗,結(jié)果:
如果是打開另一個瀏覽器的話毅弧,sessionScopne.name::: 也是空的,只是這里沒有另打開
21.@SessionAttributes(types=User.class)/ /@SessionAttributes(types= {User.class,String.class})
這個注解會將類中所有(多個對象)放入Request域中的User對象和String對象同時放進(jìn)HttpSession的域空間中当窗。
這樣name,name2,user,user2,user3...都可sessionScope中獲取了够坐。
sessionScope.name::::${sessionScope.name}<br/><br/>
sessionScope.user::::${sessionScope.user}<br/>
sessionScope.user2::::${sessionScope.user2}<br/>
22.可以混合使用
@SessionAttributes(value={“user1”, “user2”},types={Dept.class})
@ModelAttribute
使用方式:
1、在 方法 定義上使用 @ModelAttribute 注解崖面,Spring MVC在調(diào)用目標(biāo)處理方法前元咙,會先逐個調(diào)用在方法級上標(biāo)注了@ModelAttribute 的方法。
2巫员、在方法的 參數(shù) 前使用 @ModelAttribute 注解庶香,主要用做和使用 @ModelAttribute注解的方法中Map的Key匹配!
3简识、當(dāng)同一個controller中有任意一個方法被@ModelAttribute注解標(biāo)記赶掖,頁面請求只要進(jìn)入這個控制器,不管請求那個方法七扰,均會先執(zhí)行被@ModelAttribute標(biāo)記的方法奢赂,所以我們可以用@ModelAttribute注解的方法做一些初始化操作。當(dāng)同一個controller中有多個方法被@ModelAttribute注解標(biāo)記颈走,所有被@ModelAttribute標(biāo)記的方法均會被執(zhí)行膳灶,按先后順序執(zhí)行,然后再進(jìn)入請求的方法疫鹊。
應(yīng)用中使用示例:
//@ModelAttribute測試袖瞻,配合testModelAttribute2()測試,該方法注解為@RequestMapping進(jìn)入頁http://localhost/springmvcdemo/testMA拆吆,再看看誰先執(zhí)行
//當(dāng)同一個controller中有任意一個方法被@ModelAttribute注解標(biāo)記聋迎,頁面請求只要進(jìn)入這
//個控制器,不管請求那個方法枣耀,均會先執(zhí)行被@ModelAttribute標(biāo)記的方法霉晕,所以我們可以用@ModelAttribute注解的方法做一些初始化操作
@ModelAttribute
private void testModelAttribute() {
System.out.println("@ModelAttribute這個注解標(biāo)注的方法執(zhí)行了");
}
@RequestMapping("/testMA")
public String testModelAttribute2() {
System.out.println("進(jìn)入方法被執(zhí)行了,testModelAttribute2()");
return "test";
//@ModelAttribute這個注解標(biāo)注的方法最先執(zhí)行了
//進(jìn)入方法被執(zhí)行了捞奕,testModelAttribute2()
}
使用@ModelAttribute的一個場景
應(yīng)用中牺堰,用戶名不允許修改,在修改用戶信息頁面中颅围,我們不提供輸入用戶名的字段伟葫,但當(dāng)我們提交后,springmvc中封裝對象時院促,把username設(shè)為null了筏养,這不好斧抱,怎么辦呢。
例: User ---id,username,age
@RequestMapping("/updateUser")
public String updateUser(User user) {
System.out.println("要修改的用戶信息:"+user);
return "test"; //test.jsp
}
test.jsp
body>
<form action="${pageContext.request.contextPath}/updateUser" method="post" >
<input type="hidden" name="id" value="1">
修改用戶年紀(jì)age:<input type="text" value="" name="age">
<input type="submit" value="提交">
</form>
</body>
http://localhost:8080/springmvcdemo/updateUser 回車
控制臺結(jié)果:
@ModelAttribute這個注解標(biāo)注的方法執(zhí)行了
要修改的用戶信息:User [id=1,username=null, age=22]
解決方法見下面代碼中的說明:
spring中的處理方法,用@ModelAttribute標(biāo)注的方法做初始化操作渐溶,產(chǎn)生對象屬性值只覆蓋提交給過來的對象屬性的null值辉浦,其它字段值不作處理。
@Controller
public class IndexController {
//@ModelAttribure測試茎辐,配合testModelAttribute2()測試宪郊,該方法注解為@RequestMapping進(jìn)入頁http://localhost/springmvcdemo/testMA,再看看誰先執(zhí)行
//當(dāng)同一個controller中有任意一個方法被@ModelAttribute注解標(biāo)記拖陆,頁面請求只要進(jìn)入這
//個控制器弛槐,不管請求那個方法,均會先執(zhí)行被@ModelAttribute標(biāo)記的方法慕蔚,所以我們可以用@ModelAttribute注解的方法做一些初始化操作
@ModelAttribute
private void testModelAttribute(@RequestParam(value="id",required=false) Integer id,Model model) { //required=false防止空異常
System.out.println("id==="+id);
System.out.println("@ModelAttribute這個注解標(biāo)注的方法執(zhí)行了");
if(id!=null) {
User user =new User();
user.setId(1); //設(shè)置屬性值丐黄,若是從數(shù)據(jù)庫獲取的對象,不用這樣設(shè)置孔飒,直接加入model
user.setUsername("admin");
user.setAge(40);
model.addAttribute("user",user); //user
}
}
@RequestMapping("/updateUser")
public String updateUser(User user) {
System.out.println("要修改的用戶信息:"+user);
//傳統(tǒng)做法
//1. 通過傳過來的id值,在數(shù)據(jù)庫中找到對應(yīng)的對象艰争,返回一個User對象
/*User usery=userService.get(user.getId());
//2.將傳過來的user對象的屬性覆蓋數(shù)據(jù)庫中查出來的user對象坏瞄。
user2.setAge(user.getAge());
//3. 調(diào)用服條層你的update方法
userService.update(user2) */
//spring中的處理方法,用@ModelAttribute標(biāo)注的方法做初始化操作,產(chǎn)生對象屬性值只覆蓋提交給過來的對象屬性的null值甩卓,其它字段值不作處理鸠匀。
return "test"; //進(jìn)入test.jsp頁
}
}
test.jsp
<body>
<form action="${pageContext.request.contextPath}/updateUser" method="post" >
<input type="hidden" name="id" value="1">
修改用戶年紀(jì)age:<input type="text" value="" name="age">
<input type="submit" value="提交">
</form>
</body>
測試: http:localhost/springmvcdemo/updateUser 回車 輸入age:33
結(jié)果:
id===1
@ModelAttribute這個注解標(biāo)注的方法執(zhí)行了
要修改的用戶信息:User [id=1,username=admin, age=33]
運行流程簡單示意
1)執(zhí)行目標(biāo)方法之前先執(zhí)行 @ModelAttribute 注解修飾的方法: 從數(shù)據(jù)庫中取出對象,把對象放入到了 Map 中。鍵為: user逾柿。
2)SpringMVC 從 Map 中取出 User 對象,合并Jsp頁面中表單傳過來的 User 對象的對應(yīng)屬性缀棍。
3) SpringMVC 把上述修改后的對象傳入目標(biāo)方法的參數(shù).
注意:在 @ModelAttribute 修飾的方法時, 放入到 Map 時的鍵(user)需要和目標(biāo)方法入?yún)㈩愋停║ser)的第一個字母小寫的字符串一致!
真正的內(nèi)部執(zhí)行過程復(fù)雜的多
1 ) 確定一個 key,若目標(biāo)方法的 POJO 類型的參數(shù)沒有使用 @ModelAttribute 作為修飾, 則 key 為 POJO 類名的第一個字母改小寫后的名字机错,這個名字就是Key爬范。 若目標(biāo)方法中的參數(shù)使用了 @ModelAttribute 來修飾,則 key 為 @ModelAttribute 注解的 value屬性值弱匪。
2)SpringMVC 從 Map 中取出 User 對象, 合并Jsp頁面中表單傳過來的 User 對象的對應(yīng)屬性的內(nèi)部細(xì)節(jié):實際上第一步是將User對象(就是從數(shù)據(jù)庫中取出的)放到了一個叫implicitModel 的Map中青瀑,所以它里頭有Key (前面1來確定)和Value值(User對象)。第二步:SpringMVC執(zhí)行目標(biāo)方法之前會在implicitModel找Key萧诫,在若存在匹配的, 則取出來合并表單傳過來的對象的相應(yīng)屬性后傳入目標(biāo)方法斥难。如果在implicitModel 中不存在匹配的Key 對應(yīng), 則檢查當(dāng)前的Controller類上是否使用 @SessionAttributes 注解修飾。若使用了該注解, 且 @SessionAttributes 注解的HttpSession 域空間中找匹配的Key, 找到了則會從 HttpSession 的域中來獲取 key 所對應(yīng)的 value 值帘饶,在合并表單傳過來的對象的相應(yīng)屬性后傳入到目標(biāo)方法的參數(shù)中哑诊,若Controller類沒有識
@SessionAttributes 注解或 @SessionAttributes 注解的域空間中不包含匹配的Key, 則會通過反射來創(chuàng)建 POJO 類型的對象, 傳入為目標(biāo)方法的參數(shù)。
3)最后SpringMVC 會把 Key 和 POJO 類型的對象保存到 implicitModel 中, 進(jìn)而會保存到 request 中及刻。
SpringMVC的視圖解析過程詳解
我們前面講過這個流程示意圖:
Controller類中請求處理方法執(zhí)行完成后镀裤,最終返回一個ModelAndView對象穷当。對于那些返
回String,view或者M(jìn)odelMap等類型的處理方法淹禾,SpringMVC也會在內(nèi)部將他們裝配成一個ModelAndView對象返回馁菜。ModelAndView對象包含了邏輯名和模型對象,其中的model可能為 { }空铃岔。
首先說明springmvc.xml中視圖解析器配置注意事項:
說明一下汪疮,如果前綴為 /WEB-INF/jsp/,那么后臺return視圖名”/success” or “success”均映射到/WEB-INF/jsp/success.jsp ;
如果前綴 為 /WEB-INF/jsp毁习,那么后臺return視圖名”/success”智嚷,將會映射到/WEB-
INF/views/success.jsp;如果后臺return視圖名”success”纺且,將會報錯盏道!
視圖解析過程從幾個概念入手:
- 【視圖】
視圖的作用是渲染模型數(shù)據(jù),將模型里的數(shù)據(jù)以某種形式呈現(xiàn)給客戶载碌,其實就是html猜嘱、jsp甚至word、excel文件(模板)嫁艇;為了實現(xiàn)視圖模型和具體實現(xiàn)技術(shù)的解耦朗伶,Spring在org.springframwork.web.servlet包中定義了一個高度抽象的View接口:
(Navigate--open type--搜‘View’,ctrl+t列出View接口所有實現(xiàn)類如下圖:)
我們springmvc的配置文件xml中配的是InternalResourceView實現(xiàn)View類。
視圖對象由視圖解析器負(fù)責(zé)實例化步咪,由于他們是無狀態(tài)的论皆,所以不存在線程安全的問題。
1猾漫、有狀態(tài)就是有數(shù)據(jù)存儲功能点晴。有狀態(tài)對象(Stateful Bean),就是有實例變量的對象悯周,可以保存數(shù)據(jù)粒督,是非線程安全的,無法做分布式集群功能队橙。
2坠陈、無狀態(tài)就是一次操作,不能保存數(shù)據(jù)捐康。無狀態(tài)對象(Stateless Bean)仇矾,就是沒有實例變
量的對象.不能保存數(shù)據(jù),是不變類解总,是線程安全的贮匕。無狀態(tài)即各自維護(hù)自身的狀態(tài),如會話信息都在客戶端花枫,服務(wù)端并不保存狀態(tài)信息刻盐,那么我們可以說服務(wù)端是無狀態(tài)的掏膏,這個的好處是顯而易見的,無狀態(tài)的部分可以很方便的被替換掉(或集群敦锌、橫向擴(kuò)展)而不用狀態(tài)重建(或同步)狀態(tài)信息馒疹!
常見的視圖實現(xiàn)類: JstlView extends InternalResourceView
- 【視圖解析器】
SpringMVC為邏輯視圖名的解析提供了不同的策略,可以在Spring Web 上下文中配置一種或多種解析策略乙墙,并指定他們之間的先后順序颖变。
每一種映射策略對應(yīng)一個具體的視圖解析器實現(xiàn)類。
視圖解析器的作用比較單一:將邏輯視圖解析為一個具體的物理視圖對象听想。所有的視圖解析器都必須實現(xiàn)ViewResolver接口腥刹。
常見的視圖解析器實現(xiàn)類:
可以選擇一種或多種視圖解析器,可以通過其order屬性指定解析器的優(yōu)先順序汉买,order越小優(yōu)先級越高衔峰, InternalResourceViewResolver 中 order 屬性的默認(rèn)值:Integer.MAX_VALUE
既然SpringMVC默認(rèn)解析器就是InternalResourceViewResolver,為什么我們要在是springmvc.xml文件自己配置解析器呢蛙粘?原因是SpringMVC默認(rèn)選擇的解析器就是
InternalResourceViewResolver垫卤,但是它里邊的屬性值""(property)是空的!所以需要我們配置它里頭的屬性值组题!
具體解析過程葫男,我們跟蹤一下源碼就知道了:
1、請求會被我們web.xml文件中配置的DispatcherServlet攔截
2崔列、默認(rèn)執(zhí)行doDispatch()
3、我們在return “index”旺遮;的地方打一個斷點赵讯,開始跟蹤!
4耿眉、往回找doDispatch()
看到實例化mv边翼,就是ModelAndView對象:
往后走兩步,可以看到
進(jìn)入轉(zhuǎn)發(fā)結(jié)果處理方法(step into F5)processDispatchResult鸣剪,在該方法中進(jìn)行視圖渲染组底。
F5進(jìn)入視圖渲染方法render:
進(jìn)入視圖解析方法resolveViewName:
可以看到視圖解析器有兩個(與Springmvc.xml配置文件里的配置一致),而且下面是一個for循環(huán)遍歷筐骇,所有我們在配置文件中可以配置多個解析器债鸡!此時得到的view對象:
可以看到拿到了name和轉(zhuǎn)發(fā)的URL。
1.為何為JstlView而不是XML配置的InternalResourceViewResolver默認(rèn)對應(yīng)的InternlResourceView铛纬?
2.因為JSP頁面使用fmt等JSTL標(biāo)簽厌均!SpringMVC會自動使用InternlResourceView的子類 — JstlView !8嫠簟棺弊!
拿到了視圖之后晶密,就該進(jìn)行視圖渲染了 !跳到render方法模她,進(jìn)入:
如圖上紅線表明稻艰,先準(zhǔn)備數(shù)據(jù),再進(jìn)行數(shù)據(jù)渲染侈净。不過由于后臺方法未傳入model數(shù)據(jù)尊勿,所以此時mergedModel仍為空{(diào) }
不多說,進(jìn)入renderMergedOutputModel( )方法用狱!
最后在總結(jié)一下SpringMVC的工作原理:
1运怖、SpringMVC所有的請求都提交給DispatcherServlet,它會委托應(yīng)用系統(tǒng)的其它模塊負(fù)責(zé)
對請求進(jìn)行真正的處理工作。
2夏伊、DispatcherServlet查詢一個或多個HandleMapping,找到處理請求的Controller.
3摇展、DispatcherServlet提交到目標(biāo)Controller.
4、Controller進(jìn)行業(yè)務(wù)邏輯處理后溺忧,會返回一個ModelAndView
5咏连、Dispatcher查詢一個或多個ViewResolver視圖解析器,找到ModelAndView對象指定的視圖對象
6鲁森、視圖對象負(fù)責(zé)渲染返回給客戶端祟滴。
JstlView視圖使用fmt標(biāo)簽的方法
1上一節(jié)課中我們可以看到拿到了試圖解析器解析拿到ViewName和轉(zhuǎn)發(fā)的URL。返回的結(jié)果對象為JstlView而不是XML配置的InternalResourceViewResolver默認(rèn)對應(yīng)的InternlResourceView原因也說了:因為JSP頁面使用fmt等JSTL數(shù)據(jù)格式化標(biāo)簽歌溉!SpringMVC會自動使用InternlResourceView的子類 — JstlView B⒍!痛垛!
2項目中使用 JSTL 草慧, SpringMVC 會把視圖由 InternalView 轉(zhuǎn)換為 JstlView ,這沒問題匙头。 關(guān)鍵是這里還有一個知識點: 如果要使用 Jstl 的 fmt 標(biāo)簽支持國際化(多語言界面)漫谷,就 需要在 SpringMVC 的配置文件中配置國際化資源文件 才行。這在中國也不是必要的設(shè)置蹂析,若是在國外(美國)的話開發(fā)就要選en_US了舔示。
現(xiàn)在我們舉例來說明一下i18n的用法:
假設(shè)我們要用到兩種格式,中文电抚,英文美國(格式可以在如火狐瀏覽器-設(shè)置--語言---選擇優(yōu)先使用語言對話框中查看)惕稻,用戶請求頁(index.jsp),只有兩個框: 用戶名喻频,密碼缩宜。表單前面沒加提示符,但當(dāng)我們設(shè)置了兩個資源文件(語言格式)后,當(dāng)瀏覽器設(shè)置了語言優(yōu)級為誰锻煌,就以誰國的語言顯示提示符妓布。
-
創(chuàng)建兩個文件(英文en_US,中文zh_CN),(\u7528\u6237\u540D用戶名宋梧,\u5BC6\u7801密碼)匣沼,放的位置和內(nèi)容如下圖:
- 配springmvc xml的國際化資源對象bean,上面有圖已顯示方法捂龄。
<!-- 配置國際化資源文件 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
- index.jsp 添加 fmt 標(biāo)簽
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<body>
<h4>這是index首頁</h4>
<form action="${pageContext.request.contextPath}/jsptomvc" method="POST">
<fmt:message key="i18n.username"/>:<input type="text" value="" name="username" /> <br><br>
<input type="text" value ="age" name="age"/><br><br>
<fmt:message key="i18n.password"/>:<input type="password" name="password"/><br><br>
<input type="submit" value="提交" />
</form>
</body>
-
設(shè)置瀏覽器释涛。
要優(yōu)先的語言上移,再設(shè)設(shè)置備用語言倦沧,也是一樣優(yōu)先的上移唇撬,再重啟瀏覽器。如下圖:5張圖片合成的展融。
- 測試:http://localhost:8080/springmvcdemo 回車
配置直接轉(zhuǎn)發(fā)的頁面
前面我們已設(shè)置了一個視圖解析器
然后在配置一個控制器:
這里使用http://localhost:8080/springmvcdemo/index 可以正確得到頁面
使用<mvc:view-controller path=""/>的情況下:
在springmvc配置文件中配置
<mvc:view-controller path="/index" view-name="index" />
<mvc:annotation-driven />
然后使用http://localhost:8080/springmvcdemo/index 可以正確得到頁面窖认,不需要在Controller類里寫方法了!(這種場景也常用告希,如我們要查一個頁面扑浸,不需要任何處理的情況下)
不過:有這個配置后,正常的需要通過Controller類的方法的Url就會訪問出錯燕偶,解決方法(spring.xml)加 <mvc:annotation-driven /> 配置.
此外: <mvc:view-controller/> 除了直接轉(zhuǎn)發(fā)還可也重定向:
<mvc:view-controller path="/" view-name="redirect:/indexController"/>
即如果當(dāng)前路徑是/ 則重定向到/indexController
mvc-annotation-driven這個配置標(biāo)簽
<mvc:annotation-driven /> 其實是一種簡寫形式喝噪,完全可以手動配置替代這種簡寫形式,簡寫形式可以讓初學(xué)都快速應(yīng)用默認(rèn)配置方案指么。
<!-- 這個簡化標(biāo)簽相當(dāng)于 如下配置-->
<!-- HandlerMapping -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping ">
</bean>
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- HandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
</bean>
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter "></bean>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- HadnlerExceptionResolvers -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver "></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver"></bean>
<bean class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver"></bean>
<mvc:annotation-driven /> 會自動注冊:
- RequestMappingHandlerMapping酝惧, 實現(xiàn)這個類,它會處理@RequestMapping 注解伯诬,并將其注冊到請求映射表中系奉。
- RequestMappingHandlerAda pter, 實現(xiàn)這個類姑廉,則是處理請求的適配器,確定調(diào)用哪個類的哪個方法翁涤,并且構(gòu)造方法參數(shù)桥言,返回值。當(dāng)配置了mvc:annotation-driven后葵礼,Spring就知道了我們啟用注解驅(qū)動号阿。然后Spring通過context:component-scan標(biāo)簽的配置,會自動為我們將掃描到的@Component鸳粉,@Controller扔涧,@Service,@Repository等注解標(biāo)記的組件注冊到工廠中,來處理我們的請求枯夜。
- ExceptionHandlerExceptionResolver
- <mvc:annotation-driven /> 還將提供以下支持:
1.支持使用 ConversionService 實例對表單參數(shù)進(jìn)行類型轉(zhuǎn)換弯汰;
2.支持使用 @NumberFormat annotation、@DateTimeFormat注解完成數(shù)據(jù)類型的格式化湖雹;
3.支持使用 @Valid 注解對 JavaBean 實例進(jìn)行 JSR 303 驗證咏闪;
4.支持使用 @RequestBody 和 @ResponseBody 注解;
5.讀寫XML的支持(JAXB)摔吏,讀寫JSON的支持(Jackson)鸽嫂,后面,我們處理響應(yīng)ajax請求時征讲,就使用到了對json的支持据某。
6.當(dāng)使用mvc:view-controller標(biāo)簽時一定要加入mvc:annotation-driven,不然會使requestMapping失效诗箍。
7.后面癣籽,當(dāng)為了處理靜態(tài)資源問題而加入mvc:default-servlet-handler時,也一定要加入mvc:annotation-driven扳还,不然requestMapping同樣會失效才避。
8.后面,當(dāng)使用自定義類型轉(zhuǎn)換器的時候需要加上mvc:annotation-driven標(biāo)簽氨距。
9.后面桑逝,對action寫JUnit單元測試時,要從spring IOC容器中取DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter 兩個bean俏让,來完成測試楞遏,取的時候要知道是<mvc:annotation-driven />這一句注冊的這兩個bean進(jìn)Spring的IOC容器的。
SpringMVC自定義視圖
自定義視圖作用:
自己定義視圖首昔,視圖繼承 view 類或者 abstractExcelView 或者abstractPdfView 寡喝,將內(nèi)容以 Excel 或者 PDF 格式顯示,還可以玩表格啊什么的勒奇。
玩一下Excel的實現(xiàn):
-
創(chuàng)建 excelView 視圖预鬓,繼承 AbstractXlsxView 。
這里需要 apache 的 poi 的 jar 包:
實現(xiàn)功能:從 modelAndView 中獲取 model 數(shù)據(jù)赊颠,作為 excel 視圖顯示格二。
cn.ybzy.springmvcdemo.web
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.servlet.view.document.AbstractXlsView;
import cn.ybzy.springmvcdemo.model.User;
public class ExcelView extends AbstractXlsView{
@Override
protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request,
HttpServletResponse response) throws Exception {
String fileName="xiong.xlsx";
response.setCharacterEncoding("utf-8");
response.setContentType("application/ms-excel"); //ms是微軟的
response.setHeader("Content-Disposition","inline;filename="+new String(fileName.getBytes(),"UTF-8")); //設(shè)置頁為在線下載頁
List<User> users =(List<User>) model.get("users"); //model里的數(shù)據(jù),controller類處理方法
//創(chuàng)建 一張excel表
Sheet sheet = workbook.createSheet("用戶信息表");
//創(chuàng)建表里的第一行
Row headRow = sheet.createRow(0);
//給第一行里的單元格寫東西
headRow.createCell(0).setCellValue("id");
headRow.createCell(1).setCellValue("username");
headRow.createCell(2).setCellValue("password");
//創(chuàng)建單元格樣式
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setAlignment(HorizontalAlignment.LEFT);
Font font=workbook.createFont();
font.setColor(HSSFColorPredefined.RED.getIndex());
cellStyle.setFont(font);
int rowNumber=1;
for(User user:users) {
Row row = sheet.createRow(rowNumber++);//從第二行開始寫正文
row.createCell(0).setCellValue(user.getId());
row.createCell(1).setCellValue(user.getUsername());
row.createCell(2).setCellValue(user.getAge());
}
OutputStream out= response.getOutputStream();
workbook.write(out);
out.flush();
out.close();
}
}
- 編寫Controller類里的方法竣蹦,可以從數(shù)據(jù)庫取數(shù)據(jù)顶猜,這里從form表單中取數(shù)據(jù)來演示,所有jsp中寫一個Form表單用POJO傳數(shù)據(jù)過來:
//創(chuàng)建一張User電子表格
@RequestMapping("/excel")
public ModelAndView excelViewTest() {
Map<String,Object> map = new HashMap<>();
//模擬從數(shù)據(jù)庫中取出三個對象記錄
User user3 = new User();
User user2 = new User();
User user1 = new User();
user1.setId(1);
user1.setUsername("熊少文");
user1.setAge(21);
user2.setId(2);
user2.setUsername("徐會鳳");
user2.setAge(22);
user3.setId(3);
user3.setUsername("黃任剛");
user3.setAge(24);
List<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
users.add(user3);
map.put("users", users);
ModelAndView mv = new ModelAndView(new ExcelView(),map);
return mv;
}
- 測試:
http://localhost/springmvcdemo/excel 回車痘括,會出一個下載對話框长窄,不要管頁面的錯誤颜启。
什么是REST(了解)
什么是REST忠聚?( WebService 兩種方式贾陷,一是 SOAP 方式弧关,二是 REST 方式。) )REST (REpresentation State Transfer) 描述了一個架構(gòu)樣式的網(wǎng)絡(luò)系統(tǒng)肆资,比如 web 應(yīng)用程序矗愧。它首次出現(xiàn)在 2000 年 Roy Fielding 的博士論文中,他是 HTTP 規(guī)范的主要編寫者之一郑原。 REST 指的是一組架構(gòu)約束條件和原則唉韭。滿足這些約束條件和原則的應(yīng)用程序或設(shè)計就是 RESTful。
Web 應(yīng)用程序最重要的 REST 原則是
犯犁,客戶端和服務(wù)器之間的交互在請求之間是無狀態(tài)的属愤。從客戶端到服務(wù)器的每個請求都必須包含理解請求所必需的信息。如果服務(wù)器在請求之間的任何時間點重啟酸役,客戶端不會得到通知住诸。此外,無狀態(tài)請求可以由任何可用服務(wù)器回答涣澡,這十分適合云計算之類的環(huán)境贱呐。客戶端可以緩存數(shù)據(jù)以改進(jìn)性能入桂。
在服務(wù)器端
奄薇,應(yīng)用程序狀態(tài)和功能可以分為各種資源。資源是一個有趣的概念實體抗愁,它向客戶端公開馁蒂。資
源的例子有:應(yīng)用程序?qū)ο蟆?shù)據(jù)庫記錄蜘腌、算法等等沫屡。每個資源都使用 URI (Universal ResourceIdentifier) 得到一個惟一的地址。所有資源都共享統(tǒng)一的界面撮珠,以便在客戶端和服務(wù)器之間傳輸狀態(tài)沮脖。 使用的是標(biāo)準(zhǔn)的 HTTP 方法,比如 GET芯急、PUT倘潜、POST 和 DELETE,還可能包括HEADER 和OPTIONS志于。Hypermedia 是應(yīng)用程序狀態(tài)的引擎,資源表示通過超鏈接互聯(lián)废睦。
舉例:SpringMVC的REST風(fēng)格的四種請求方式
它們分別對應(yīng)四種基本操作:
1伺绽、GET ======獲取資源
2、POST ===== 新建資源
3、PUT======= 更新資源
4奈应、DELETE==== 刪除資源
REST:即 Representational State Transfer澜掩。(資源)表現(xiàn)層狀態(tài)轉(zhuǎn)化。
是目前最流行的一種互聯(lián)網(wǎng)軟件架構(gòu)杖挣。它結(jié)構(gòu)清晰肩榕、符合標(biāo)準(zhǔn)、易于理解惩妇、擴(kuò)展方便株汉, 所以正得到越來越多網(wǎng)站的采用。我們可以通過rest風(fēng)格占位符方式歌殃,利用@PathVariable注解將占位符的值賦給調(diào)用方法參數(shù)乔妈, 實現(xiàn)結(jié)果。
實現(xiàn)方式(REST風(fēng)格四種請求方式的調(diào)用):
我們通過@RequestMapping映射請求中的method參數(shù)實現(xiàn)四種請求方式的調(diào)用氓皱,以下為示例代碼:
- web.xml配置過濾器(springmvc包中已定義好的)路召,用于攔截所有資源,功能是可以將POST請求轉(zhuǎn)為put,delete請求波材。
<!-- 將指定的POST請求股淡,轉(zhuǎn)變?yōu)樾枰膒ut或delete請求,這個過濾器的作用就是這個 -->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 控制類代碼
@RequestMapping(value={"/index","/",""}) //測試時進(jìn)入 localhost/springmvcdemo/index或localhost/springmvcdemo/或localhost/springmvcdemo都可進(jìn)入請求頁
public String index() {
return "index";
}
@RequestMapping(value="/testGet",method=RequestMethod.GET) //可以用超鏈接測試廷区,超鏈接只可GET唯灵,沒法指定其它的方式<a href=""></a>
public String testGet() {
System.out.println("testGet");
return "test";
}
@RequestMapping(value="/testPost",method=RequestMethod.POST)
public String testPost() {
System.out.println("testPost");
return "test";
}
@RequestMapping(value="/testPut",method=RequestMethod.PUT)
public String testPut() {
System.out.println("testPut");
return "redirect:/test";//因為非springmvc頁不技持PUT所要跳轉(zhuǎn)頁面
}
@RequestMapping(value="/testDel",method=RequestMethod.DELETE)
public String testDel() {
System.out.println("testDel");
return "redirect:/test"; //因為非springmvc頁不技持DELETE所要跳轉(zhuǎn)頁面
}
- 響應(yīng)頁 test.jsp,里面只顯示測試提交成功否躲因,沒有其它內(nèi)容早敬。
- 請求頁: index.jsp
在表單域中需要攜帶一個name值為_method,value值為put或者delete的參數(shù)隱藏表單大脉,如下所示:
<a href="${pageContext.request.contextPath}/testGet">超鏈接測試GET</a>
<form action="${pageContext.request.contextPath}/testDel" method="POST">
<input type="hidden" name="_method" value="delete">
<input type="text" value="" name="username" /> <br><br>
<input type="text" value ="" name="age"/><br><br>
<input type="password" name="password"/><br><br>
<input type="submit" value="提交" />
</form>
- GET請求:POST請求:PUT請求:DELETE請求搞监。測試。
測試:http://localhost:8080/springmvcdemo 回車镰矿。輸入一些數(shù)據(jù)琐驴,點提交,再看控制臺輸出秤标。
整合SpringMVC和Spring和Hibernate 案例绝淡。
http://www.reibang.com/writer#/notebooks/50759535/notes/91053055