Spring MVC 簡介
MVC概述
- MVC 是 Model-View-Control 的簡稱,即模型-視圖-控制器。它是一個存在於服務器表達層的模型,它將應用分開,改變應用之間的高度耦合。
- 視圖
- 數據的展現。視圖是用戶看到並與之交互的界面。視圖向用戶顯示相關的數據,並能接收用戶的輸入數據,但是它並不進行任何實際的業務處理。視圖可以向模型查詢業務狀態,但不能改變模型。視圖還能接受模型發出的數據更新事件,從而對用戶界面進行同步更新。
- 模型
- 應用對象。模型是應用程序的主體部分。 模型代表了業務數據和業務邏輯; 當數據發生改變時,它要負責通知視圖部分;一個模型能爲多個視圖提供數據。由於同一個模型可以被多個視圖重用,所以提高了應用的可重用性。
- 控制器
- 邏輯處理、控制實體數據在視圖上展示、調用模型處理業務請求。當 Web 用戶單擊 Web 頁面中的提交按鈕來發送 HTML 表單時,控制器接收請求並調用相應的模型組件去處理請求,然後調用相應的視圖來顯示模型返回的數據。
- MVC 模型運行機制
在 MVC 模式中,Web 用戶向服務器提交的所有請求都由控制器接管。接受到請求之後,控制器負責決定應該調用哪個模型來進行處理;然後模型根據用戶請求進行相應的業務邏輯處理,並返回數據;最後控制器調用相應的視圖來格式化模型返回的數據,並通過視圖呈現給用戶。
三層架構概述
- Presentation tier + Application tier + Data tier (展現層 + 應用層 + 數據訪問層)
- 實際上MVC只存在三層架構的展現層,M實際商是數據模型,是包含數據的對象.
- Service和Dao層反饋在應用層和數據訪問層
Spring MVC 介紹
Spring Web MVC處理請求的流程
具體執行步驟如下:首先用戶發送請求—–>前端控制器,前端控制器根據請求信息(如URL)來決定選擇哪一個頁面控制器進行處理並把請求委託給它,即以前的控制器的控制邏輯部分;圖2-1中的1、2步驟;
頁面控制器接收到請求後,進行功能處理,首先需要收集和綁定請求參數到一個對象,這個對象在Spring Web MVC中叫命令對象,並進行驗證,然後將命令對象委託給業務對象進行處理;處理完畢後返回一個ModelAndView(模型數據和邏輯視圖名);圖2-1中的3、4、5步驟;
前端控制器收回控制權,然後根據返回的邏輯視圖名,選擇相應的視圖進行渲染,並把模型數據傳入以便視圖渲染;圖2-1中的步驟6、7;
前端控制器再次收回控制權,將響應返回給用戶,圖2-1中的步驟8;至此整個結束
Spring MVC的優勢
清晰的角色劃分:前端控制器(DispatcherServlet)、請求到處理器映射(HandlerMapping)、處理器適配器(HandlerAdapter)、視圖解析器(ViewResolver)、處理器或頁面控制器(Controller)、驗證器( Validator)、命令對象(Command 請求參數綁定到的對象就叫命令對象)、表單對象(Form Object 提供給表單展示和提交到的對象就叫表單對象)。
分工明確,而且擴展點相當靈活,可以很容易擴展,雖然幾乎不需要;
由於命令對象就是一個POJO,無需繼承框架特定API,可以使用命令對象直接作爲業務對象;
和Spring 其他框架無縫集成,是其它Web框架所不具備的;
可適配,通過HandlerAdapter可以支持任意的類作爲處理器;
可定製性,HandlerMapping、ViewResolver等能夠非常簡單的定製;
功能強大的數據驗證、格式化、綁定機制;
利用Spring提供的Mock對象能夠非常簡單的進行Web層單元測試;
本地化、主題的解析的支持,使我們更容易進行國際化和主題的切換。
強大的JSP標籤庫,使JSP編寫更容易。
………………還有比如RESTful風格的支持、簡單的文件上傳、約定大於配置的契約式編程支持、基於註解的零配置支持等等。
Spring MVC的常用註解
- @ Controller 表明這個類是Spring MVC裏的Controller.Dispatcher Servlet 會自動掃描註解了此註解的類.在聲明普通Bean的時候,使用@Component,@Service,@Repository和@Controller是等同的,因爲@Service,@Repository,@Controller都組合了@Component元註解.但在Spring MVC聲明控制器Bean的時候,只能使用@Controller.
- @RequestMapping 用來映射Web請求(訪問路徑和參數),處理類和方法.其支持Servlet的request和response作爲參數.
- @ResponseBody 支持將返回值放在response體內,而不是返回一個頁面,此註解可放置在返回值前或者方法上.
- @RequestBody 允許request的參數在request體中,而不是直接鏈接在地址後面.此註解放置在參數前.
- @PathVariable 用來接收路徑參數,此註解放置在參數前.
- @RestController 這是一個組合註解,組合了@Controller和@ResponseBody
- 延伸閱讀: 什麼是request,response
- Spring MVC 基本配置
Spring MVC的定製配置需要我們的配置類集成一個WebMvcConfigurerAdapter類,並在此類使用@EnableWebMvc註解,來開啓Spring MVC的配置支持. - Spring MVC 靜態資源配置
Spring Boot默認的靜態資源配置
如果需要直接訪問靜態資源,可以在我們的配置類中重寫 addResourceHandlers方法 快捷的ViewController
無需做任何業務處理,只是簡單的頁面轉向,可以使用addViewControllers方法來實現.package com.wangge.buzmgt.config; import com.wangge.json.JSONFormatMethodProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.ByteArrayHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.ResourceHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter; import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter; import org.springframework.http.converter.xml.SourceHttpMessageConverter; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import java.util.ArrayList; import java.util.List; @Configuration @EnableWebMvc public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers (ViewControllerRegistry registry) { registry.addViewController ("/").setViewName ("index"); registry.addViewController ("/left").setViewName ("left"); } @Override public void addReturnValueHandlers (List<HandlerMethodReturnValueHandler> returnValueHandlers) { returnValueHandlers.add (new JSONFormatMethodProcessor (messageConverter ())); } private List<HttpMessageConverter<?>> messageConverter () { List<HttpMessageConverter<?>> converters = new ArrayList<> (); converters.add (new ByteArrayHttpMessageConverter ()); converters.add (new StringHttpMessageConverter ()); converters.add (new ResourceHttpMessageConverter ()); converters.add (new SourceHttpMessageConverter<> ()); converters.add (new AllEncompassingFormHttpMessageConverter ()); converters.add (new Jaxb2RootElementHttpMessageConverter ()); converters.add (new MappingJackson2HttpMessageConverter ()); return converters; } @Override public void addResourceHandlers (ResourceHandlerRegistry registry) { registry.addResourceHandler ("/static/**").addResourceLocations ("classpath:/static/"); } }
其中 addResourceLocations 指的是文件放置的目錄,addResourceHandler指的是對外暴露的訪問路徑.