Spring Boot 2.0 讀書筆記_03:MVC 上

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 (啓動器類)
      • resources
        • static (靜態資源默認)
          • css
          • js
        • template (頁面模板默認)
        • application.properties (配置文件)
    • 包結構規範:上述項目目錄結構爲標準
    • 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 用符號 " * " 來表示匹配任意字符,用 " ** " 來表示統配任意路徑,用 " ? " 來匹配單個字符。
    例子 說明
    /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 同理
      
  • 方法參數

    • @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聲明方法,進行綁定對象的特性拓展
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章