亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
1. 前言

說起 Spring MVC 框架的攔截器,就不得不提起原生 Servlet 中的過濾器,兩者的功能性質是一樣的,但底層實現機制會有差異性。攔截器用到了代理設計模式,是 Spring AOP 的具體實際應用。過濾器使用的是函數回調機制。本節課程將和大家一起學習 Spring MVC 中的攔截器。通過本節課程,你將了解到攔截器的工作模式及基礎原理。重點是要掌握攔截器的實現過程。

3. 小結

本節和大家講解了如何使用 Spring MVC 提供的 MultipartResolver 組件完成文件的上傳。其配置過程并不很難,但大家需要注意的是,在接收文件數據時會涉及到 @RequestPart 注解、MultipartFile 接口,結合兩者能很好的注放上傳數據,方便開發者的后續處理。

7. 小結

本章節講解了如何使用 XML 方式搭建 Spring MVC 項目,雖然現在流行使用 JAVA 方式,但 XML 仍然是一個不錯的選擇。無論是使用 XML 還是 JAVA 方式,其本質是一樣的,只是使用了不同的語法方式進行表達。這相當于有人用英文或中文對你說 “我愛你”。當然,你需要了解英文或中文。對于 Spring MVC 而言,對 XML 和 JAVA 的理解是無障礙的。也意味著你可以隨心選擇 JAVA 或 XML 方式。

5. 小結

本節課程和大家講解了在控制器方法中如何直接使用原生 Servlet API 和 更底層的 IO 流對象。使用起來不難。但通過本節課程,希望大家能更透徹地理解 Spring MVC 和原生 Servlet API、網絡編程之間的關系。Servlet API 是 J2EE 擬定的 企業級 WEB 應用程序開發規范,可以認為是官方提出來的開發框架。對 WEB 開發過程中的更低級的網絡流操作進行了封裝;Spring MVC 則是對原生 Servlet API 進一步進行了封裝。一切只是為了讓開發過程更高效。

1. 前言

本節課將和大家一起講解 Spring MVC 的地址請求映射方案。通過本節課程的學習,你將了解到:如何使用注解的方式進行映射;如何對請求的 URL 進行篩選、過濾。本章節內容相對而言較易理解,請掌握本章節中所提及的注解的使用。

3. 小結

本章節和大家一起聊了聊在 Spring MVC 項目如何使用 log4j 2 日志系統。log4j 是一個獨立的日志系統。可以在需要提供日志的項目中以模塊化的方式輕松使用。log4j 有很多可配置項,大家可以參考官方文檔。對于本課程的配置而言,已經足夠常規要求。

4. 使用 IO 流

WEB 程序整體上是 B / S 結構,本質上是基于底層網絡的程序,是 C / S 結構體系的升級?;貞浺幌戮W絡編程的幾個基本要素:服務器端建立監聽端口;客戶端向監聽端口發起網絡連接;連接成功后建立起雙向的網絡流傳輸通道;彼此之間通過網絡流通道進行數據交流。程序的本質就是解決數據從哪里來、如何處理數據以及數據要去哪里的問題。基于網絡的程序也是如此,其數據的來來往往是通過 IO 流實現的。WEB 程序也是網絡程序,數據的來去也是通過 IO 流實現??赡苣銜f,使用原生 Servlet 規范開發 WEB 項目時,你從沒有接觸或使用過這樣的流、哪樣的流。那是因為無論你使用原生 Servlet API 還是使用 Spring MVC 開發 WEB ,兩者已經幫你隱藏了其中的細節。HttpServletRequest 其本質就是封裝網絡輸入流的操作。如果你不信,你可以查看 HttpServletRequest 的相關方法,會看到:InputStream inStream=request.getInputStream();觸類旁通,此時你應該能理解到 HttpServletResponse 封裝了網絡輸出流的相關操作。OutputStream outputStream= response.getOutputStream();那么,在 Spring MVC 中我們能不能在控制器的方法中直接引用底層的 IO 流對象?當然可以!TIps: Spring MVC 既可以把原生的 Servlet API 對象注入到控制器的方法中,也可以把更底層的 IO 流對象注入到控制器方法中。

2. 前期準備

搭建 Spring MVC 項目,可以使用 JAVA 方式進行組件信息配置,也可以使用 XML 方式,甚至可以使用 JAVA 和 XML 的混合模式?,F在主流框架都流行使用 JAVA 方式(注解),逐步減少對 XML 方式的依賴。主要是 JAVA 方法更適合 JAVA 開發者的習慣,并簡化了配置過程。Spring MVC 項目是基于 Spring 的核心基礎功能(IOC、AOP)之上的,Spring 建議 Spring MVC 項目中創建 2 個 WebApplication 對象(也稱為上下文容器對象)。這 2 個上下文對象分別依賴于 DispatcherServlet 和 ContextLoaderListener 組件完成創建。DispatcherServlet 是整個程序的調度中心(本質就是一個 Servlet),Spring MVC 程序啟動時必須要初始化完成對 DispatcherServlet 組件的創建。此組件還會創建一個與自己有關聯的 WebApplication 工廠對象,即 Web 上下文對象;ContextLoaderListener 是由 Spring 提供的監聽器組件,它可以監聽程序的啟動過程,并在程序啟動時創建另一個 WebApplication 工廠對象,即 Root 上下文對象。所以,必須配置好 DispatcherServlet 和 ContextLoaderListener ,保證程序啟動時創建它們。使用 XML 配置之前,先準備好 3 個 XML 文件:web.xml: 理論上,在新建 Spring MVC WEB 項目時, WEB-INF 目錄中會自動創建這個文件。如果不存在,就需要創建一個;spring-mvc.xml: 由開發者新建,一般放在項目的 src/main/resources 目錄下面;application.xml: 由開發者新建,放在項目的 src/main/resources 目錄下面。Tips: spring-mvc.xml 和 application.xml 的文件名可由開發者根據語義自行指定。這 2 個文件也可以根據需要更改存放目錄。 這 2 個 XML 文件中必須至少包括 beans 根元素說明。<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"></beans>

2. @RequestMapping

什么是地址請求映射?Spring MVC WEB 項目中,每一次請求都會交給用戶控制器響應。為了保證用戶能請求到用戶控制器,則需要 Spring MVC 向外提供用戶控制器對外的請求接口。這就是請求地址映射。如何映射?答案是:可以使用 @RequestMapping 注解。@RequestMapping 注解的作用:把用戶控制器以 URL 邏輯名的方式向外映射,用于由外向內的請求調用。Tips: 向外提供映射是 @RequestMapping 注解的事情。解析請求包中的信息,查找是否存在相匹配的控制器,這個工作由映射器組件完成。

2.1 Model

這個字面意思很明顯,咱就是一個模型組件。Model 是一個接口類型,Model 接口中提供了標準的保存數據的方法。Model addAttribute(String attributeName, @Nullable Object attributeValue);Model 使用起來很簡單,將 Model 設為控制器方法的參數便可 ,其它的交給 Spring MVC,因為 Model 是一個接口類型,Spring MVC 會為我們辨明身份,注入一個具體的實例對象。@RequestMapping(value="/login",method=RequestMethod.POST)public String login01(User user,Model map) { if("mk".equals(user.getUserName()) && "123".equals(user.getUserPassword())) { map.addAttribute("loginUser", user); return "index"; } return "fail";}Model 接口中還有其它的方法,但都不常用,感興趣的話大家可以查閱其源代碼或 API 文檔。

3.1 攔截器接口規范

自定義攔截器之前,首先要了解 Spring MVC 提供的攔截器接口,自定義攔截器必須遵循此接口規范。public interface HandlerInterceptor { /** * 用戶控制器之前攔截,實現用戶控制器數據的預處理工作,第三個參數為響應的用戶控制器 */ default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } /** *對用戶控制器處理后的數據再進一步處理 */ default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } /** * 視圖解析器對 View 渲染完成后對最后結果進行處理 */ default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { }}Spring MVC 提供有攔截器適配器,適配器對攔截器接口做了簡單封裝。public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor{ //……}

1. 前言

本章節將和大家一起聊聊在 Spring MVC 項目中如何添加日志系統。通過本課程,你將了解到:添加 log4j 日志子系統的流程。這個是本章節的重點;log4j 日志系統的相關配置。

4. 小結

本章節和大家講解了 Spring MVC 的攔截器,需要大家掌握攔截的工作原理以及實現自定義攔截器。特別注意的是要理解多個攔截器在一起協作工作時方法之間是如何調用的。

3.2 測試 CSRF

為請求增加有效的 CSRF Token:mvc.perform(post("/").with(csrf()))把 CSRF Token 增加到請求頭中:mvc.perform(post("/").with(csrf().asHeader()))增加一個不合法的 CSRF Token:mvc.perform(post("/").with(csrf().useInvalidToken()))配置請求攜帶默認用戶信息:mvc.perform(get("/").with(user("user")))配置請求攜帶自定義用戶信息mvc.perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))使用自定義的 userDetails 實例:mvc.perform(get("/").with(user(userDetails)))使用匿名用戶:mvc.perform(get("/").with(anonymous()))使用自定義身份信息:mvc.perform(get("/").with(authentication(authentication)))使用自定義安全上下文:mvc.perform(get("/").with(securityContext(securityContext)))將用戶信息應用到所有請求中:mvc = MockMvcBuilders .webAppContextSetup(context) .defaultRequest(get("/").with(user("user").roles("ADMIN"))) .apply(springSecurity()) .build();我們還可以使用注解方式配置用戶信息:@Test@WithMockUser(roles="ADMIN")public void requestProtectedUrlWithUser() throws Exception {mvc .perform(get("/")) ...}

4. 小結

本節課程和大家一起講解了 Model 、ModelMap、ModelAndView 數據模型,并講解了可以使用 @SessionAttributes 注解提升數據模型的作用域。從功能層面上講,所有數據模型組件的功能是一樣的。從底層上講,區別在于實現 Map 的數據結構。直接使用 Map 做數據模型時, Spring MVC 注入的是一個 LinkedHashMap 實例。ModelMap 是 LinkedHashMap 的子類,本質還是 LinkedHashMap,只是封裝了 put 方法,讓其顯得高級一點。Model 是接口,Spring MVC 注入的也是 LinkedHashMap 實例。所以,無論是使用 Map 、Model 還是 ModelMap 其實都是在借助 LinkedHashMap 完成數據的存儲。其區別在于應用場景,有時,需要接口注入,有時可能需要類注入。當然,還會有自己的功能實現。

2. @ResponseBody

WEB 應用程序中,控制器處理過的數據,一般都是通過視圖技術渲染成 HTML 后交給瀏覽器進行解析。最近幾年,項目整體結構流行采用前后端分離模式。什么是前后端分離結構?傳統項目,數據由后臺完全處理,前端頁面僅僅用來顯示結果數據。所謂前后端分離,會把一部分數據邏輯交給前端處理。也就意味著,交給前端的數據僅僅只是半成品數據,需要前端語言如 JS 進一步處理后再交給 HTML 顯示。后端一般選擇以 JSON 的格式向前端進行數據傳遞。Spriing MVC 可以使用 @ResponseBody 完成這個操作。@ResponseBody 是 Spring MVC 提供的一個很有意思的注解,一般放置在控制器方法的前面。

4. 小結

本章節和大家講解了 Spring MVC 中如何優雅的處理異常。主要有 3 種方案:將異常映射成為 HTTP 狀態碼;使用全局異常處理組件。建議大家使用這種方式,具有很多的隔離性、統一性;使用注解的方式處理異常。

3. 會話作用域

Map、Model 、ModelMap、ModelAndView 這幾個數據模型組件,默認情況下,其中所保存的數據都是請求作用域級別的。在很多應用場景下,需要數據在整個會話過程中都能訪問到。比如登錄者信息、購物車信息等。面對這種數據需求時,Spring MVC 又如何實現?你能想到的,Spring MVC 早就想到了。使用 @SessionAttributes 注解即可。@SessionAttributes 注解是類級別的注解,需要添加在控制器類的前面。@Controller@RequestMapping("/user")@SessionAttributes("loginUser")public class UserAction {@RequestMapping(value="/login",method=RequestMethod.POST) public ModelAndView login01(User user) { ModelAndView mv=new ModelAndView(); if("mk".equals(user.getUserName()) && "123".equals(user.getUserPassword())) { mv.addObject("loginUser", user); mv.setViewName("index"); return mv; } mv.setViewName("fail"); return mv;}}Tips: @SessionAttributes(“loginUser”) 中的屬性名 loginUser 必須保持和 mv.addObject(“loginUser”, user); 中的 loginUser 名一樣。從底層思維來講, Spring MVC 即把數據保存到請求作用域中、也保存到會話作用域中。測試時,只需要在 index.jsp 中添加如下面的 EL 表達式,指明數據的作用域。<body> 我是首頁 <br/> 請求作用域中得到當前登錄者:${requestScope.loginUser.userName} <br/> 會話作用域中得到當前登錄者:${sessionScope.loginUser.userName}</body>啟動瀏覽器,打開登錄頁面,輸入登錄名、登錄密碼、點擊登錄,然后在瀏覽器中會看到無論是請求作用域、還是會話作用域中都可以獲取到登錄者的信息。

2.2 ModelMap

這個組件的字面意思是說,我是用 Map 存儲數據的模型??梢圆殚喴幌缕湓创a結構.,本質上還就是一個鏈表實現的 Map,都是一家人呀。Map、Map …… 又見 Map。ModelMap 中提供的方法和 Model 接口差不多,不同之處在于有自己的實現。public class ModelMap extends LinkedHashMap<String, Object> { public ModelMap addAttribute(String attributeName, @Nullable Object attributeValue) { Assert.notNull(attributeName, "Model attribute name must not be null"); put(attributeName, attributeValue); return this; } }如何使用?在 Spring MVC 的世界,會讓你感覺到自己的多余,因為很多事情 Spring MVC 都幫你溫柔的解決。一樣的,只需要設定為控制器方法的參數就可以了。@RequestMapping(value="/login",method=RequestMethod.POST)public String login01(User user,ModelMap map) { if("mk".equals(user.getUserName()) && "123".equals(user.getUserPassword())) { map.addAttribute("loginUser", user); return "index"; } return "fail";}會發現,大家除了名字不一樣外,其它好像也沒有什么不一樣。

3. 其他

head 內還可以包括 link、script 等標簽,用于引用 css JavaScript 文件等作用,例如:960在實際項目開發中,為了更好的擴展性和可維護性,一般會把 head 標簽以及其中的內容放到一個全局 include 文件,因為這個文件一般改動不太頻繁且每個文件都必須引用,所以由框架在加載的時候自動引用,這樣的設計方式符合 MVC 以及面向對象開發的思想。

直播
查看課程詳情
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號