SpringMVC_One

不穿格子衫的徍爺發表於2019-07-04

SpringMVC_One

SpringMVC的優勢 (面試)

清晰的角色劃分:

  • 前端控制器(DispatcherServlet)
  • 請求到處理器對映器(HandlerMapping)
  • 處理器介面卡(HandlerAdapter)
  • 檢視解析器(ViewResolver)
  • 處理器或頁面控制器(Controller)
  • 驗證器( Validator)
  • 命令物件(Command 請求引數繫結到的物件就叫命令物件)
  • 表單物件(Form Object 提供給表單展示和提交到的物件就叫表單物件)。

2、分工明確,而且擴充套件點相當靈活,可以很容易擴充套件,雖然幾乎不需要。

3、由於命令物件就是一個POJO,無需繼承框架特定API,可以使用命令物件直接作為業務物件。

4、和Spring 其他框架無縫整合,是其它Web框架所不具備的。

5、可適配,通過HandlerAdapter可以支援任意的類作為處理器。

6、可定製性,HandlerMapping、ViewResolver等能夠非常簡單的定製。

7、功能強大的資料驗證、格式化、繫結機制。

8、利用Spring提供的Mock物件能夠非常簡單的進行Web層單元測試。

9、本地化、主題的解析的支援,使我們更容易進行國際化和主題的切換。

10、強大的JSP標籤庫,使JSP編寫更容易。

………………還有比如RESTful風格的支援、簡單的檔案上傳、約定大於配置的契約式程式設計支援、基於註解的零配置支援等等


SpringMVC和Struts2的優略分析 (面試)

共同點:

  • 它們都是表現層框架,都是基於MVC模型編寫的。
  • 它們的底層都離不開原始ServletAPI(HttpServletRequest、HttpServletResponse…)。
  • 它們處理請求的機制都是一個核心控制器。

區別:

  • Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
  • Spring MVC 是基於方法設計的,而Struts2是基於類,Struts2每次執行都會建立一個動作類。所以Spring MVC 會稍微比 Struts2 快些。
  • Spring MVC 使用更加簡潔,同時還支援 JSR303, 處理 ajax 的請求更方便 ,而struts2處理ajax的時候,需要匯入一個struts2的外掛包,並通過返回型別指定ajax的json資料。
  • (JSR303 是一套JavaBean引數校驗的標準,它定義了很多常用的校驗註解,我們可以直接將這些註解加在我們JavaBean的屬性上面,就可以在需要校驗的時候進行校驗了。) (回去之後,有興趣可以搜一下springMVC校驗機制)
  • Struts2 的OGNL 表示式使頁面的開發效率相比Spring MVC 更高些,但執行效率並沒有比JSTL提升,尤其是struts2的表單標籤,遠沒有html執行效率高。

SpringMVC的入門

導包配置xml:

  1. <!-- 版本鎖定 -->
  2. <properties>
  3. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  4. <maven.compiler.source>1.8</maven.compiler.source>
  5. <maven.compiler.target>1.8</maven.compiler.target>
  6. <spring.version>5.0.2.RELEASE</spring.version>
  7. </properties>
  8. <dependencies>
  9. <dependency>
  10. <groupId>org.springframework</groupId>
  11. <artifactId>spring-context</artifactId>
  12. <version>${spring.version}</version>
  13. </dependency>
  14. <dependency>
  15. <groupId>org.springframework</groupId>
  16. <artifactId>spring-web</artifactId>
  17. <version>${spring.version}</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>org.springframework</groupId>
  21. <artifactId>spring-webmvc</artifactId>
  22. <version>${spring.version}</version>
  23. </dependency>
  24. <dependency>
  25. <groupId>javax.servlet</groupId>
  26. <artifactId>servlet-api</artifactId>
  27. <version>2.5</version>
  28. <scope>provided</scope>
  29. </dependency>
  30. <dependency>
  31. <groupId>javax.servlet.jsp</groupId>
  32. <artifactId>jsp-api</artifactId>
  33. <version>2.0</version>
  34. <scope>provided</scope>
  35. </dependency>
  36. </dependencies>

配置web.xml 在web.xml配置檔案中核心控制器DispatcherServlet

  1. <!-- SpringMVC的核心控制器 -->
  2. <servlet>
  3. <servlet-name>dispatcherServlet</servlet-name>
  4. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  5. <!-- 配置Servlet的初始化引數,讀取springmvc的配置檔案,建立spring容器 -->
  6. <init-param>
  7. <param-name>contextConfigLocation</param-name>
  8. <param-value>classpath:springmvc.xml</param-value>
  9. </init-param>
  10. <!-- 配置servlet啟動時載入物件 -->
  11. <load-on-startup>1</load-on-startup>
  12. </servlet>
  13. <servlet-mapping>
  14. <servlet-name>dispatcherServlet</servlet-name>
  15. <url-pattern>/</url-pattern>
  16. </servlet-mapping>

配置編寫springmvc.xml的配置檔案

在resources下建立springmvc.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:mvc="http://www.springframework.org/schema/mvc"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans.xsd
  9. http://www.springframework.org/schema/mvc
  10. http://www.springframework.org/schema/mvc/spring-mvc.xsd
  11. http://www.springframework.org/schema/context
  12. http://www.springframework.org/schema/context/spring-context.xsd">
  13. <!-- 1:配置spring建立容器時要掃描的包,可以使用@Controller註解 -->
  14. <context:component-scan base-package="com.it"></context:component-scan>
  15. <!-- 2:配置檢視解析器 -->
  16. <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  17. <property name="prefix" value="/WEB-INF/pages/"></property>
  18. <property name="suffix" value=".jsp"></property>
  19. </bean>
  20. <!-- 3:配置spring開啟註解mvc的支援,自動開啟處理器對映器和處理器介面卡 -->
  21. <mvc:annotation-driven></mvc:annotation-driven>
  22. </beans>

v建立index.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <h3>入門案例</h3>
  8. <a href="hello">入門案例</a>
  9. </body>
  10. </html>

建立類HelloController.java

  1. /**
  2. * 控制器
  3. */
  4. @Controller
  5. public class HelloController {
  6. // 請求引數
  7. @RequestMapping(path = "/hello")
  8. public String sayHello(){
  9. System.out.println("Hello SpringMVC!!");
  10. return "success";// 響應結果
  11. }
  12. }

1562245066832

在WEB-INF下建立pages的資料夾,建立success.jsp

  1. <body>
  2. <h1>訪問成功</h1>
  3. </body>

案例執行流程

1562245125035

1562245134306


請求引數的繫結

1.1.1 請求引數的繫結說明

(1)繫結機制

【1】表單提交的資料都是k=v格式的 username=haha&password=123

【2】SpringMVC的引數繫結過程是把表單提交的請求引數,作為控制器中方法的引數進行繫結的

【3】要求:提交表單的name和引數的名稱是相同的

(2)支援的資料型別

【1】基本資料型別和字串型別

【2】實體型別(JavaBean)

【3】集合資料型別(List、map集合等)

基本資料型別和字串型別

(1)提交表單的name和引數的名稱是相同的

(2)區分大小寫

建立param.jsp

  1. <body>
  2. <h3>傳遞引數</h3>
  3. <%--↓提交資料--%>
  4. <a href="param/testParam?username=張三&age=18">入門案例</a>
  5. </body>

建立ParamController.java

  1. @Controller
  2. @RequestMapping(path = "/param")
  3. public class ParamController {
  4. // 請求引數
  5. @RequestMapping(path = "/testParam")
  6. // 接收資料
  7. public String testParam(String username,Integer age){
  8. System.out.println("params測試:username:"+username+" age:"+age);
  9. return "success";// 響應結果
  10. }
  11. }

實體型別(JavaBean)

(1)提交表單的name和JavaBean中的屬性名稱需要一致

(2)如果一個JavaBean類中包含其他的引用型別,那麼表單的name屬性需要編寫成:物件.屬性 例如:address.name

建立類User.java

  1. public class User {
  2. private String username;
  3. private Integer age;
  4. }

在Controller中定義

  1. @RequestMapping(value = "/testParam")
  2. public String testParam(User user){
  3. System.out.println("歡迎執行ParamController中的testParam方法!user:"+user);
  4. return "success";// 執行檢視解析器 /WEB-INF/page/success.jsp
  5. }

建立Account.java

  1. public class Account {
  2. private String name;
  3. private String password;
  4. private Double money;
  5. private User user;
  6. }

param.jsp

  1. <form action="param/saveAccount" method="post">
  2. 賬號:<input type="text" name="name"/><br>
  3. 密碼:<input type="text" name="password"/><br>
  4. 金額:<input type="text" name="money"/><br>
  5. 使用者姓名:<input type="text" name="user.username"/><br>
  6. 使用者年齡:<input type="text" name="user.age"/><br>
  7. <input type="submit" value="提交"/>
  8. </form>

ParamController.java

  1. @RequestMapping(path = "/saveAccount")
  2. public String testParam(Account account){
  3. System.out.println(account);
  4. return "success";// 響應結果
  5. }

請求引數中文亂碼的解決

在web.xml中配置Spring提供的過濾器類

  1. <!-- 配置過濾器,解決中文亂碼的問題 -->
  2. <filter>
  3. <filter-name>characterEncodingFilter</filter-name>
  4. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  5. <!-- 指定字符集 -->
  6. <init-param>
  7. <param-name>encoding</param-name>
  8. <param-value>UTF-8</param-value>
  9. </init-param>
  10. </filter>
  11. <filter-mapping>
  12. <filter-name>characterEncodingFilter</filter-name>
  13. <url-pattern>/*</url-pattern>
  14. </filter-mapping>

給集合屬性資料封裝(瞭解)

(1)JSP頁面編寫方式:list[0].屬性

(2)JSP頁面編寫方式:map[‘one’].屬性

param.jsp

  1. <form action="param/saveAccount" method="post">
  2. 賬號:<input type="text" name="name"/><br>
  3. 密碼:<input type="text" name="password"/><br>
  4. 金額:<input type="text" name="money"/><br>
  5. 使用者姓名:<input type="text" name="user.username"/><br>
  6. 使用者年齡:<input type="text" name="user.age"/><br>
  7. 使用者姓名(list):<input type="text" name="list[0].username"/><br>
  8. 使用者年齡(list):<input type="text" name="list[0].age"/><br>
  9. 使用者姓名(list):<input type="text" name="list[1].username"/><br>
  10. 使用者年齡(list):<input type="text" name="list[1].age"/><br>
  11. 使用者姓名(map):<input type="text" name="map['one'].username"/><br>
  12. 使用者年齡(map):<input type="text" name="map['one'].age"/><br>
  13. 使用者姓名(map):<input type="text" name="map['two'].username"/><br>
  14. 使用者年齡(map):<input type="text" name="map['two'].age"/><br>
  15. <input type="submit" value="提交"/>
  16. </form>

在Account.java中新增:

  1. private List<User> list;
  2. private Map<String,User> map;

自定義型別轉換器(瞭解)

(1)表單提交的任何資料型別全部都是字串型別,但是後臺定義Integer型別,資料也可以封裝上,說明SpringMVC框架內部會預設進行資料型別轉換。

(2)如果想自定義資料型別轉換,可以實現Converter的介面

在User.java中新增:

  1. public class User {
  2. private String username;
  3. private Integer age;
  4. private Date birthday;
  5. }

param.jsp

  1. <form action="param/saveUser" method="post">
  2. 姓名:<input type="text" name="username"/><br>
  3. 年齡:<input type="text" name="age"/><br>
  4. 生日:<input type="text" name="birthday"/><br>
  5. <input type="submit" value="提交"/>
  6. </form>

ParamController.java

  1. @RequestMapping(path = "/saveUser")
  2. public String saveUser(User user){
  3. System.out.println(user);
  4. return "success";// 響應結果
  5. }

自定義型別轉換器

  1. package com.it.utils;
  2. import org.springframework.core.convert.converter.Converter;
  3. import java.text.DateFormat;
  4. import java.text.SimpleDateFormat;
  5. import java.util.Date;
  6. /**
  7. * 把字串轉換成日期的轉換器
  8. */
  9. public class StringToDateConverter implements Converter<String, Date> {
  10. /**
  11. * 進行型別轉換的方法
  12. */
  13. public Date convert(String source) {
  14. // 判斷
  15. if(source == null) {
  16. throw new RuntimeException("引數不能為空");
  17. }
  18. try {
  19. DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
  20. // 解析字串
  21. Date date = df.parse(source);
  22. return date;
  23. } catch (Exception e) {
  24. throw new RuntimeException("型別轉換錯誤");
  25. }
  26. }
  27. }

【2】註冊自定義型別轉換器,在springmvc.xml配置檔案中編寫配置

  1. <!-- 註冊自定義型別轉換器 -->
  2. <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
  3. <property name="converters">
  4. <set>
  5. <bean class="com.it.utils.StringToDateConverter"></bean>
  6. </set>
  7. </property>
  8. </bean>
  9. <!-- 配置spring開啟註解mvc的支援 -->
  10. <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

常用註解

@RequestParam註解

作用:

把請求中指定名稱的引數給控制器中的形參賦值。

屬性:

value:請求引數中的名稱。

required:請求引數中是否必須提供此引數。預設值:true。表示必須提供,如果不提供將報錯。

defaultValue:表示預設值,如果不傳遞值


建立anno.jsp

  1. <body>
  2. <h3>RequestParam入門案例</h3>
  3. <a href="anno/testRequestParam?name=哈哈&age=22">RequestParam</a>
  4. </body>

建立AnnoController.java

  1. @Controller
  2. @RequestMapping(path = "/anno")
  3. public class AnnoController {
  4. // 請求引數
  5. @RequestMapping(path = "/testRequestParam")
  6. public String testRequestParam(@RequestParam(value = "name") String username,
  7. @RequestParam(value="age",required = true)Integer age){
  8. System.out.println("Hello SpringMVC!!,測試@RequestParam");
  9. System.out.println(username);
  10. System.out.println(age);
  11. return "success";// 響應結果
  12. }
  13. }

@RequestBody註解

作用:

1:@RequestBody主要用來接收前端傳遞給後端的json字串中的資料的(請求體中的資料的)

2:用於獲取請求體內容。直接使用得到是key=value&key=value…結構的資料。 get請求方式不適用。

屬性:

required:是否必須有請求體。預設值是:true。

當取值為true時,get請求方式會報錯。

如果取值為false,get請求得到是null。

  1. <h3>@RequestBody</h3>
  2. post請求jsp程式碼: <br>
  3. <!-- request body註解 -->
  4. <form action="anno/testRequestBody" method="post">
  5. 使用者名稱稱:<input type="text" name="username" ><br/>
  6. 使用者密碼:<input type="password" name="password" ><br/>
  7. 使用者年齡:<input type="text" name="age" ><br/>
  8. <input type="submit" value="儲存">
  9. </form>
  10. get請求jsp程式碼: <br>
  11. <a href="anno/testRequestBody?body=test">requestBody註解get請求</a>
  1. // 請求引數
  2. @RequestMapping(path = "/testRequestBody")
  3. public String testRequestBody(@RequestBody(required = false) String body){
  4. System.out.println("Hello SpringMVC!!,測試@RequestParam");
  5. System.out.println(body);
  6. return "success";// 響應結果
  7. }

@PathVariable註解

作用: 
用於繫結url中的佔位符。例如:請求url中 /delete/{id}/{name},這個{id},{name}就是url佔位符。

url支援佔位符是spring3.0之後加入的。是springmvc支援restful風格URL的一個重要標誌。

屬性:

value:用於指定url中佔位符名稱。

required:是否必須提供佔位符。

  1. <h3>@PathVariable註解</h3>
  2. <!-- PathVariable註解 -->
  3. <a href="anno/testPathVariable/100">pathVariable註解</a>
  1. // 請求引數
  2. @RequestMapping(path = "/testPathVariable/{uid}")
  3. public String testPathVariable(@PathVariable(value = "uid") Integer id){
  4. System.out.println("Hello SpringMVC!!,測試@PathVariable");
  5. System.out.println(id);
  6. return "success";// 響應結果
  7. }

REST風格URL

什麼是rest

REST(英文:Representational State Transfer,簡稱REST,說的意思是:表現層狀態轉變,或者叫做 “表述性狀態轉移”)描述了一個架構樣式的網路系統,比如 web 應用程式。它首次出現在 2000 年 Roy Fielding 的博士論文中,他是 HTTP 規範的主要編寫者之一。在目前主流的三種Web服務互動方案中,REST相比於SOAP(Simple Object Access protocol,簡單物件訪問協議)以及XML-RPC更加簡單明瞭,無論是對URL的處理還是對Payload的編碼,REST都傾向於用更加簡單輕量的方法設計和實現。值得注意的是REST並沒有一個明確的標準,而更像是一種設計的風格。

它本身並沒有什麼實用性,其核心價值在於如何設計出符合REST風格的網路介面。

restful的優點

它結構清晰、符合標準、易於理解、擴充套件方便,所以正得到越來越多網站的採用。

restful的特性:

資源(Resources):網路上的一個實體,或者說是網路上的一個具體資訊。

它可以是一段文字、一張圖片、一首歌曲、一種服務,總之就是一個具體的存在。可以用一個URI(統一資源定位符)指向它,每種資源對應一個特定的 URI 。要獲取這個資源,訪問它的URI就可以,因此 URI 即為每一個資源的獨一無二的識別符。

表現層(Representation):把資源具體呈現出來的形式,叫做它的表現層 (Representation)。

比如,文字可以用 txt 格式表現,也可以用 HTML 格式、XML 格式、JSON 格式表現,甚至可以採用二進位制格式。

狀態轉化(State Transfer):每發出一個請求,就代表了客戶端和伺服器的一次互動過程。

HTTP協議,是一個無狀態協議,即所有的狀態都儲存在伺服器端。因此,如果客戶端想要操作伺服器,必須通過某種手段,讓伺服器端發生“狀態轉化”(State Transfer)。而這種轉化是建立在表現層之上的,所以就是 “表現層狀態轉化”。具體說,就是 HTTP 協議裡面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。它們分別對應四種基本操作:GET 用來獲取資源,POST 用來新建資源,PUT 用來更新資源,DELETE 用來刪除資源。

傳統的例項:唯一的URL地址(統一資源定位符),找到對應的資源


基於HiddentHttpMethodFilter的示例

作用:

由於瀏覽器 form 表單只支援 GET 與 POST 請求,而DELETE、PUT 等 method 並不支援,Spring3.0 新增了一個過濾器,可以將瀏覽器請求改為指定的請求方式,傳送給我們的控制器方法,使得支援 GET、POST、PUT 與DELETE 請求。

在web.xml中配置該過濾器。

  1. <filter>
  2. <filter-name>hiddenHttpMethodFilter</filter-name>
  3. <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>hiddenHttpMethodFilter</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>

第二步:請求方式必須使用post請求。

第三步:按照要求提供_method請求引數,該引數的取值就是我們需要的請求方式。

anno.jsp

  1. resfful風格:jsp中示例程式碼:
  2. <!-- 儲存 -->
  3. <form action="anno/testPathVariable" method="post">
  4. 使用者名稱稱:<input type="text" name="username"><br/>
  5. <!-- <input type="hidden" name="_method" value="POST"> -->
  6. <input type="submit" value="儲存"></form>
  7. <hr/>
  8. <!-- 更新 -->
  9. <form action="anno/testPathVariable" method="post">
  10. 使用者名稱稱:<input type="text" name="username"><br/>
  11. <input type="hidden" name="_method" value="PUT">
  12. <input type="submit" value="更新">
  13. </form>
  14. <hr/>
  15. <!-- 刪除 -->
  16. <form action="anno/testPathVariable/1" method="post">
  17. <input type="hidden" name="_method" value="DELETE">
  18. <input type="submit" value="刪除">
  19. </form>
  20. <hr/>
  21. <!-- 查詢一個 -->
  22. <form action="anno/testPathVariable/1" method="post">
  23. <input type="hidden" name="_method" value="GET">
  24. <input type="submit" value="查詢">
  25. </form>
  26. <hr/>
  1. // 請求引數
  2. @RequestMapping(path = "/testPathVariable",method = RequestMethod.POST)
  3. public String save(User user){
  4. System.out.println("Hello SpringMVC!!,測試@PathVariable,新增-請求方式Post");
  5. System.out.println(user);
  6. return "success";// 響應結果
  7. }
  8. // 請求引數
  9. @RequestMapping(path = "/testPathVariable",method = RequestMethod.PUT)
  10. public String update(User user){
  11. System.out.println("Hello SpringMVC!!,測試@PathVariable,更新-請求方式Put");
  12. System.out.println(user);
  13. return "success";// 響應結果
  14. }
  15. // 請求引數
  16. @RequestMapping(path = "/testPathVariable/{uid}",method = RequestMethod.DELETE)
  17. public String delete(@PathVariable(value = "uid") Integer id){
  18. System.out.println("Hello SpringMVC!!,測試@PathVariable,刪除-請求方式Delete");
  19. System.out.println(id);
  20. return "success";// 響應結果
  21. }
  22. // 請求引數
  23. @RequestMapping(path = "/testPathVariable/{uid}",method = RequestMethod.GET)
  24. public String findById(@PathVariable(value = "uid") Integer id){
  25. System.out.println("Hello SpringMVC!!,測試@PathVariable,查詢一個-請求方式Get");
  26. System.out.println(id);
  27. return "success";// 響應結果
  28. }

但是我們可以在控制檯看到結果,說明執行了對應的方法,但是在響應到Jsp頁面的時候,Jsp頁面不支援PUT和DELETE請求的響應,所以丟擲異常,我們可以使用@ResponseBody(後面講)表示不再響應頁面,即檢視解析器將失效,以文字的形式返回,用在ajax的應用場景(返回文字或者json)

  1. // 修改是PUT協議
  2. @RequestMapping(value = "/testPathVariable",method = RequestMethod.PUT)
  3. public @ResponseBody String update(User user){
  4. System.out.println("put請求,修改");
  5. System.out.println(user);
  6. return "success";
  7. }
  8. // 刪除是DELETE協議
  9. @RequestMapping(value = "/testPathVariable/{id}",method = RequestMethod.DELETE)
  10. public @ResponseBody String delete(@PathVariable(name = "id") Integer id,User user){
  11. System.out.println("delete請求,刪除");
  12. System.out.println(id);
  13. System.out.println(user);
  14. return "success";
  15. }

@RequestHeader註解

作用:

用於獲取請求訊息頭。

屬性:

value:提供訊息頭名稱

required:是否必須有此訊息頭

注:

在實際開發中一般不怎麼用。

  1. <h3>測試@RequestHeader註解</h3>
  2. <!-- RequestHeader註解 -->
  3. <a href="anno/testRequestHeader">獲取請求訊息頭</a>
  1. // 請求引數
  2. @RequestMapping(path = "/testRequestHeader")
  3. public String testRequestHeader(@RequestHeader(value="accept")String requestHeader){
  4. System.out.println("Hello SpringMVC!!,測試@RequestHeader");
  5. System.out.println(requestHeader);
  6. return "success";// 響應結果
  7. }

@CookieValue註解

作用:

用於把指定cookie名稱的值傳入控制器方法引數。

屬性:

value:指定cookie的名稱。

required:是否必須有此cookie。

  1. <h3>測試@CookieValue註解</h3>
  2. <!-- CookieValue註解 -->
  3. <a href="anno/testCookieValue">CookieValue註解</a>
  1. @RequestMapping(path = "/testCookieValue")
  2. public String testCookieValue(@CookieValue(value = "JSESSIONID")String cookieValue){
  3. System.out.println("Hello SpringMVC!!,測試@CookieValue");
  4. System.out.println(cookieValue);
  5. return "success";// 響應結果
  6. }

@ModelAttribute註解

作用:

該註解是SpringMVC4.3版本以後新加入的。它可以用於修飾方法和引數。

出現在方法上,表示當前方法會在控制器的方法執行之前,先執行。它可以修飾沒有返回值的方法,也可以修飾有具體返回值的方法。

出現在引數上,獲取指定的資料給引數賦值。

屬性:

value:用於獲取資料的key。key可以是POJO的屬性名稱,也可以是map結構的key。

應用場景:

當表單提交資料不是完整的實體類資料時,保證沒有提交資料的欄位使用資料庫物件原來的資料。

例如:

我們在編輯一個使用者時,使用者有一個建立資訊欄位,該欄位的值是不允許被修改的。在提交表單資料是肯定沒有此欄位的內容,一旦更新會把該欄位內容置為null,此時就可以使用此註解解決問題。


基於POJO屬性的基本使用

anno.jsp

  1. <h3>測試@ModelAttribute註解</h3>
  2. 需求: 修改使用者資訊,要求使用者的日期不能修改 jsp的程式碼:
  3. <!-- 修改使用者資訊 -->
  4. <form action="anno/testModelAttribute" method="post">
  5. 使用者名稱稱:<input type="text" name="username" ><br/>
  6. 使用者年齡:<input type="text" name="age" ><br/>
  7. <input type="submit" value="儲存">
  8. </form>

AnnoController.java

  1. // ModelAttribute的用法
  2. @ModelAttribute // 在執行的方法之前執行
  3. public void showModel(User user) {
  4. System.out.println("執行了showModel方法"+user);
  5. user.setBirthday(new Date());
  6. }
  7. /** * 模擬修改使用者方法 * @param user * @return */
  8. @RequestMapping("/testModelAttribute")
  9. public String testModelAttribute(User user) {
  10. System.out.println("控制器中處理請求的方法:修改使用者:"+user);
  11. return "success";
  12. }

基於Map的應用場景一:ModelAttribute修飾方法帶返回值

  1. <h3>測試@ModelAttribute註解</h3>
  2. 需求: 修改使用者資訊,要求使用者的日期不能修改 jsp的程式碼:
  3. <!-- 修改使用者資訊 -->
  4. <form action="anno/testModelAttribute" method="post">
  5. 使用者名稱稱:<input type="text" name="username" ><br/>
  6. 使用者年齡:<input type="text" name="age" ><br/>
  7. <input type="submit" value="儲存">
  8. </form>

AnnoController.java

  1. @ModelAttribute // 在執行的方法之前執行
  2. public User showModel(String username) {
  3. //模擬去資料庫查詢
  4. User user = findUserByName(username);
  5. System.out.println("執行了showModel方法"+user);
  6. return user;
  7. }
  8. /** * 模擬修改使用者方法 * @param user * @return */
  9. @RequestMapping("/testModelAttribute")
  10. public String testModelAttribute(User user) {
  11. System.out.println("控制器中處理請求的方法:修改使用者:"+user);
  12. return "success";
  13. }
  14. /** * 模擬去資料庫查詢 * @param username * @return User*/
  15. private User findUserByName(String username) {
  16. User user = new User();
  17. user.setUsername(username);
  18. user.setAge(19);
  19. user.setBirthday(new Date());
  20. return user;
  21. }

基於Map的應用場景二:ModelAttribute修飾方法不帶返回值

  1. @ModelAttribute // 在執行的方法之前執行
  2. public void showModel(String username, Map<String,User> maps) {
  3. //模擬去資料庫查詢
  4. User user = findUserByName(username);
  5. maps.put("abc",user);
  6. System.out.println("執行了showModel方法"+user);
  7. }
  8. /** * 模擬修改使用者方法 * @param user */
  9. @RequestMapping("/testModelAttribute")
  10. public String testModelAttribute(@ModelAttribute(value = "abc") User user) {
  11. System.out.println("控制器中處理請求的方法:修改使用者:"+user);
  12. return "success";
  13. }
  14. /** * 模擬去資料庫查詢 * @param username * @return User*/
  15. private User findUserByName(String username) {
  16. User user = new User();
  17. user.setUsername(username);
  18. user.setAge(19);
  19. user.setBirthday(new Date());
  20. return user;
  21. }

@SessionAttributes註解

  1. 作用:
  2. 用於多次執行控制器方法間的引數共享。 放置到類的上面。
  3. 屬性:
  4. value:用於指定存入的屬性名稱
  5. type:用於指定存入的資料型別。
  6. 相當於將資料存放到Session中。

最好:

  1. <h3>測試@SessionAttributes註解</h3>
  2. <!-- SessionAttribute註解的使用 -->
  3. <a href="anno/sessionAttributePut">存入SessionAttribute</a> <hr/>
  4. <a href="anno/sessionAttributeGet">取出SessionAttribute</a> <hr/>
  5. <a href="anno/sessionAttributeClean">清除SessionAttribute</a>

AnnoController.java

  1. @Controller
  2. @RequestMapping(path = "/anno")
  3. @SessionAttributes(value ={"username","password"},types={Integer.class})
  4. public class AnnoController {
  5. /**
  6. * * 把資料存入SessionAttribute
  7. * * @param model
  8. * * @return
  9. * * Model是spring提供的一個介面,該介面有一個實現類ExtendedModelMap *
  10. * 該類繼承了ModelMap,而ModelMap就是LinkedHashMap子類 */
  11. @RequestMapping("/sessionAttributePut")
  12. public String testPut(Model model){
  13. System.out.println("把資料存入SessionAttribute");
  14. model.addAttribute("username", "泰斯特");
  15. model.addAttribute("password","123456");
  16. model.addAttribute("age", 31);
  17. //跳轉之前將資料儲存到username、password和age中,因為註解@SessionAttribute中有這幾個引數
  18. return "success";
  19. }
  20. /**
  21. * * 獲取SessionAttribute
  22. */
  23. @RequestMapping("/sessionAttributeGet")
  24. public String testGet(ModelMap model){
  25. System.out.println("獲取SessionAttribute");
  26. System.out.println(model.get("username")+";"+model.get("password")+";"+model.get("age"));
  27. return "success";
  28. }
  29. /**
  30. * * 清空SessionAttribute
  31. */
  32. @RequestMapping("/sessionAttributeClean")
  33. public String complete(SessionStatus sessionStatus){
  34. System.out.println("清空SessionAttribute");
  35. sessionStatus.setComplete();
  36. return "success";
  37. }
  38. }