2. MVC 上
寫在開頭,關於MVC,Model - View - Controller模式
- Model(模型) - 代表一個存取數據的對象或 JAVA POJO。它也可以帶有邏輯,在數據變化時更新控制器。
- View(視圖) - 代表模型包含的數據的可視化。
- Controller(控制器) - 作用於模型和視圖上。它控制數據流向模型對象,並在數據變化時更新視圖。它使視圖與模型分離開。
這裏有幾個很容易混淆的概念:模式、框架、架構、平臺,它們之間究竟是什麼關聯?
- 模式(設計模式):包括本章講述的MVC模式,均屬於設計模式。設計模式說白了就是:告訴你針對特定問題如何組織類、對象和接口之間的關係,是前人總結的經驗。
- 框架:框架是爲了解決特定問題而存在的,其它諸如模板框架、緩存框架等。
- 架構:從大的層面來說,架構關注的是技術整合、擴展、可維護性。
- 平臺:類似框架,但又結合的架構的考慮,它是更高層面上的“框架”,準確說是一種應用。它是針對企業用戶,爲解決企業業務需要而形成的產品。
概念比較:設計模式 < 框架 < 架構 < 平臺
從複用角度講:設計模式是代碼級複用、框架是模塊級複用、架構是系統級複用、平臺是企業應用級複用。
在項目中使用最多的就是Spring MVC框架了,Spring Boot已經將這一MVC框架進行了自動集成並實現了自動配置,可謂一步到位。
-
Web項目目錄結構及包結構規範
- 項目目錄結構
關於web項目,常規情況下采用maven項目構建工具的打包工具生成。有了Spring Boot這一集成框架,在IDEA中通過Spring Initializr可進行快速SpringBoot項目的搭建。
項目根目錄:src/main- java
- packageName
- conf
- controller
- entity
- service
- impl
- …
- dao
- …
- Application.java (啓動器類)
- packageName
- resources
- static (靜態資源默認)
- css
- js
- …
- template (頁面模板默認)
- application.properties (配置文件)
- static (靜態資源默認)
- java
- 包結構規範:上述項目目錄結構爲標準
- Spring Boot默認掃描規則是:自動掃描啓動器類的同包或者其子包的下的註解。
- 項目目錄結構
-
URL映射到方法
- @RequestMapping
- 用於類上的@RequestMapping註解用來標註請求路徑
- 用於方法上的@RequestMapping註解用來進一步映射特定的URL到具體的處理方法
- @RequestMapping 的屬性
- value :請求的URL路徑,支持URL模板、正則表達式
- method:HTTP請求方法 GET、POST、PUT等
- consumes:允許的媒體類型| consumes = “application/json” 對應HTTP請求的Content-type
- produces:響應的媒體類型| produces = “application/json” 對應HTTP請求的Accept字段
- params:請求的參數,params = “action=update”
- headers:請求HTTP頭的值,headers = “myHeader=myValue”
- URL 路徑匹配
- 屬性value用於匹配URL映射,value支持簡單的表達式來匹配
例如:@RequestMapping(value = “/get/user.json”) - Ant路徑表達式
- Ant 用符號 " * " 來表示匹配任意字符,用 " ** " 來表示統配任意路徑,用 " ? " 來匹配單個字符。
- 屬性value用於匹配URL映射,value支持簡單的表達式來匹配
例子 說明 /user/*.html 匹配 /user/1.html、/user/2.html等 /**/1.html 匹配 /1.html、/user/1.html、/user/add/1.html等 /user/?.html 匹配 /user/1.html,不匹配 /user/11.html -
匹配優先級:如果一個請求有多個 @RequestMapping 能夠匹配
- 有通配符的低於沒有通配符的,比如 /user/add.json 比 /user/*.json 優先匹配。
- 有 “**” 通配符的低於有 “*” 通配符的。
- 其他URL映射:通過外部配置文件可以進行參數獲取
@Value("${paramName}")
private String name; // 將paramName映射到成員變量name屬性
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@Value("#{ }") SpEL表達式
通常用來獲取bean的屬性,或者調用bean的某個方法,也可以表示常量
-
HTTP method 匹配
- @RequestMapping 提供 method 屬性來映射HTTP的請求方法。
- 通常對於Web應用,GET和POST是經常使用的method,對於REST接口,則會採用PUT、DELETE等用來從語義上進一步區分操作。
- Spring 提供簡化後的 @RequestMapping ,提供了新的註解來表示 HTTP 方法。如:
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
- …
-
consumes 和 produces
-
屬性 consumes 表示請求的HTTP頭的Content-type媒體類型與consumes的value匹配才能調用此方法
@GetMapping(value = "/consumes/test.json", consumes = "application/json") @ResponseBody public User forJson() { return userService.getUserById(1l); }
這裏映射指定請求的媒體類型是 application/json 。因此,此方法接收一個如下AJAX請求:
$.ajax({ type: "get", url: "/consumes/test.json", contentType: "application/json", ... });
-
屬性 produces 對應HTTP請求的Accept字段,只有匹配成功才能進行方法調用。
@GetMapping(value = "/user/{userId}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
將通常瀏覽器都會把 Accept 設置爲 *.* ,因此通過瀏覽器直接訪問 “/user/1” ,瀏覽器總是返回對應信息,並通過 @ResponseBody 轉換成JSON格式返回。
-
-
params 和 headers
不同於Servlet規範,在方法中通過 HttpServletRequest 獲取請求的URL、HTTP頭這些信息再進行處理。Spring在方法簽名處提供了很多匹配方式,能進一步規範方法調用,提高代碼可閱讀性。@GetMapping(value = "/update.json", headers = "action=update") // params 同理
- @RequestMapping
-
方法參數
-
@PathVariable
-
用於從請求URL中獲取參數,並映射到方法參數中
@GetMapping(path = "/{userId}.json", produces = "application/json") @ResponseBody public User getUserById(@PathVariable Long userId) { return userService.getUserById(userId); }
符號 {} 中的變量名與方法參數名字對應,若不想對應可以使用:@PathVariable(“userId”) Long id
-
-
Model & ModelAndView
- Model(結構類似Map),可以向視圖中添加需要的變量
- Model對象主要方法:
- Model addAttribute(String attributeName, Object attributeValue):向模型中添加一個變量,參數簽名列表前者指明變量名稱,可以在隨後的視圖中引用。後者代表變量。
- Model addAttribute(Object attributeValue):向模型中添加一個變量,變量的名字就是類名首字母小寫後專爲的Java變量。
- Model addAllAttributes(Map attributes):添加多個變量,若變量存在,則覆蓋。
- Model mergeAttributes(Map attributes):添加多個變量,若變量存在,則忽略。
- Boolean containsAttribute(String attributeName):判斷是否存在變量。
-
如何使用:ModelAndView對象類似Model,但額外提供了一個視圖名稱的配置。
// Model model model.addAttribute("userInfo", user); // ModelAndView view view.addObject("userInfo", user); view.setViewName("/userInfo.html"); return view
-
JavaBean 接收HTTP參數 @RequestParam
-
通過 @RequestParam 限定HTTP參數
-
name:指明HTTP參數名稱
-
required:布爾類型,聲明此參數是否必須有,如果該參數沒有,拋出400錯誤
-
defaultValue:字符類型,如果HTTP參數沒有提供,可以指定一個默認字符串
String getUser(@RequestParam(name = "name", required = false, defaultValue = "zhangsan") String name){...}
-
-
接收一個參數對象:HTTP參數名字對應POJO屬性名
@GetMapping("/getUser") @ResponseBody public String getUser(User user){...}
-
-
@RequestBody 接收JSON
-
方法參數使用 @RequestBody 指定參數類型爲JSON數據,且映射的是一個實體POJO類。
-
Spring Boot默認使用Jackson來處理反序列化工作。
@PostMapping("/save.json") @ResponseBody public String saveUser(@RequestBody User user){...}
-
注意,和JavaBean接收HTTP參數(對象)區分開,接收JSON數據是字符串,採用@RequestBody進行字符串向對象的映射對應
-
-
MultipartFile:處理文件上傳
-
案例代碼
@PostMapping("/form") @ResponseBody public String handleFormUpload(@RequestParam("name") String name, @RequestParam("file") MultipartFile file) throws IOException { if (!file.isEmpty()) { String fileName = file.getOriginalFilename(); InputStream ins = file.getInputStream(); // 處理上傳內容 return "success"; } return "failure"; }
-
MultipartFile相關方法
-
方法名 說明 getOriginalFilename 獲取上傳文件名稱 getBytes 獲取上傳文件內容,轉爲字節數組 getInputStream 獲取一個InputStream isEmpty 文件上傳內容爲空,或者沒有文件上傳 getSize 上傳文件大小 transferTo(File dest) 保存上傳文件到目標文件系統 -
多文件上傳:使用MultipartFile數組類來接收多個文件上傳
@RequestParam("file") MultipartFile[] files
-
上傳文件參數限制:通過配置文件 application.properties 進行配置
-
-
@ModelAttribute
-
該註解通常作用在Controller的某個方法上,此方法會首先被調用,並將結果作爲Model的屬性。
@ModelAttribute public void findUserById(@PathVariable Long id, Model model) { model.addAttribute("user", userService.getUserById(id)); } @GetMapping(path = "/{id}/get.json") @ResponseBody public String getUser(Model model) { System.out.println(model.containsAttribute("user")); return "success"; }
-
-
@InitBinder
- Spring框架通過WebDataBinder 類實現HTTP參數向JavaBean對象的綁定
- 可以通過@InitBinder聲明方法,進行綁定對象的特性拓展