Spring框架的學習階段四---Spring-MVC
spring-mvc
基於spring的, ioc控制反轉, di依賴注入, aop面向切面程式設計
model 模型 - 資料和操作資料的邏輯(狹義的就是資料) 包括了實體類和業務類(例如 User,UserService) view 檢視 - 資料展現, 包括(jsp, jstl, el) controller 控制器 把模型和檢視關聯在一起, 包括servlet
讓程式的各個部分分工清晰,各司其職。讓程式的可維護性提高。
使用步驟:
-
在pom.xml檔案中新增 spring-webmvc等6個依賴 注意pom.xml檔案中需要新增
<packaging>war</packaging>
專案名:war exploded
-
在spring-mvc.xml中新增mvc的xml名稱空間
-
前控制器 -- 統一的入口 它是由spring-mvc 提供的的一個servlet: DispatcherServlet 在web.xml 對它進行配置, maven 的目錄結構中,該檔案的路徑是 src/main/webapp/WEB-INF/web.xml
xml 28行
<!-- 職責: 1.作為統一入口 2.建立spring容器 3.在tomcat啟動時,就把spring容器建立好 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 指明瞭spring配置檔案的位置 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <!-- 在tomcat啟動時,就建立這個servlet,並初始化該servlet --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> <!-- 給 DispatcherServlet 指定路徑 假設瀏覽器 /hello 沒有,會找 / 這個路徑 /s1 沒有,會找 / 這個路徑 只要沒有其他servlet能夠精確匹配這個請求路徑,這個請求都會被 / 的這個servlet來處理 --> </servlet-mapping>
-
控制器 @Controller public class 控制器類{
@RequestMapping("/請求路徑") public String 控制器方法(){
} } // 控制器類要交給spring容器管理 並spring-mvc中加入:
<mvc:annotation-driven/>
來啟用mvc的相關功能 -
處理檢視 控制器方法的返回值是檢視名 字首+檢視名+字尾就構成了最終jsp檢視路徑, 控制器會根據檢視路徑用請求轉發跳轉過去
xml 4行
<mvc:view-resolvers> <mvc:jsp prefix="/" suffix=".jsp"/> </mvc:view-resolvers>
-
請求被處理的流程
- tomcat先將該路徑與servlet進行匹配,結果沒有精確的地址與之匹配,就找到了 / 這個地址 / 地址對應的是DispatcherServlet,由它來處理請求
- DispatcherServlet 再到spring容器中找控制器類 把每個控制器中帶有@RequestMapping的方法路徑與請求路徑進行匹配,
- 匹配到了就執行該方法, 如果匹配不到報404錯誤
- 根據方法的返回結果找到jsp檢視
- 由jsp檢視生成html程式碼作為響應返回給瀏覽器
-
以maven外掛方式執行tomcat 在pom.xml中加入外掛資訊:
xml 11行
<plugin> <!-- 配置一個內嵌的tomcat -->
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port> <!-- 埠號 -->
<path>/</path> <!-- 專案在tomcat中的訪問路徑 -->
<uriEncoding>utf-8</uriEncoding> <!-- 設定get請求中解碼的字符集,解決get請求中的中文亂碼問題 -->
</configuration>
</plugin>
然後在右側的maven選單中找到tomcat7外掛,執行tomcat7:run這個命令
- 接收請求引數
-
把方法引數和請求引數直接對應
-
寫一個實體型別,把實體的屬性與請求引數對應
-
路徑引數(把引數值不是寫在?之後,而是包含在路徑當中) /deleteUser?id=1 傳統寫法 /deleteUser/1 路徑引數 要刪除1號使用者 /deleteUser/2 要刪除2號使用者
路徑引數可以通過@PathVariable 與方法引數一一對應
- 使用模型資料 Model 介面, 代表了模型資料, 它也是加在控制器方法之上 可以直接使用它的實現類ModelMap或Map 向模型新增資料: model.addAttribute("變數名", 值); model中的資料在轉發之前,都會被存入request作用域
springmvc中 常見錯誤: 400 錯誤:發生在請求引數賦值給方法引數時,發生了型別轉換問題 例如:字串轉整數 字串轉日期 對於日期需要加 @DateTimeFormat(pattern="日期格式") 中文亂碼問題: 可以配置spring提供的字元編碼過濾器
xml 15行
<!-- spring 提供的字元編碼過濾器 -->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/ *</url-pattern>
</filter-mapping>
7行
靜態資源的 404 錯誤
靜態資源是指 圖片、css、html、js
原因是DispatcherServlet的路徑是/ 跟tomcat中處理圖片的Servlet路徑衝突了
所以所有圖片的請求被DispatcherServlet所處理,把圖片的路徑當做了控制器路徑
解決辦法:
在spring配置檔案中加入:`<mvc:default-servlet-handler/>`
讓tomcat能夠熱部署,讓類的修改不用重啟伺服器就可以生效
- 首先保證 打包方式是 war exploded
- 其次,啟動tomcat使用debug方式啟動
- 在tomcat設定時,on frame deactivation 選中 update classes and resources 選項 當游標從idea切換至瀏覽器時,就會更新修改 限制:只能針對當前存在的類生效,如果是新增的類檢測不到 配置檔案的改動檢測不到
- json格式的響應 js 代表javascript object 物件, notation 標記
之前返回的大部分響應型別 text/html json也是一種響應格式:也是文字格式的,更類似於javascript的物件寫法 { "username":"張三", "age":18 } 如果轉換json時出現了錯誤: No converter found for return value of type: 是因為json轉換的jar包沒有加, 可以在pom檔案中加入相應的依賴:
xml 6行
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.1</version>
</dependency>
在控制器方法上新增@ResponseBody註解,它可以把方法的返回值轉換成json字串
java中 map以及實體類 會被轉換為json中的物件 {屬性名:屬性值} java中 list或陣列 會被轉換為json中的陣列 [元素1, 元素2, ...]
jackson常見註解: @JsonFormat 可以對日期型別進行格式化 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 注意加8小時才是北京時間 @JsonIgnore 可以在轉換時忽略加了@JsonIgnore的屬性 @JsonProperty("新的屬性名") 可以在轉換時改變屬性的名字