天天看點

SpringMVC05:RestFul和控制器

RestFul和控制器

控制器Controller

  • 控制器負責提供通路應用程式的行為,通常通過接口定義或注解定義兩種方法實作。
  • 制器負責解析使用者的請求并将其轉換為一個模型。
  • 在Spring MVC中一個控制器類可以包含多個方法。
  • 在Spring MVC中,對于Controller的配置方式有很多種

實作Controller接口

Controller是一個接口,在org.springframework.web.servlet.mvc包下,接口中隻有一個方法;

package org.springframework.web.servlet.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.ModelAndView;

// 實作該接口的類獲得控制器功能
@FunctionalInterface
public interface Controller {
   // 處理請求且傳回一個模型與視圖對象	
   @Nullable
   ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;

}
           

測試

  1. 建立一個Moudle,springmvc-04-controller。将springmvc-03-annotation拷貝一份。
    • 删掉HelloController
    • springmvc-servlet.xml配置檔案中隻留下視圖解析器
  2. 編寫一個Controller類,ControllerTest1
    package com.edgar.controller;
    
    
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    // 隻要實作了 Controller 接口的類,說明這是一個控制器了
    public class ControllerTest1 implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            ModelAndView mv = new ModelAndView();
            mv.addObject("msg","ControllerTest1");
            mv.setViewName("test");
            return mv;
        }
    }
               
  3. 編寫完畢後,去springmvc-servlet.xml檔案中注冊請求的bean;name對應請求路徑,class對應處理請求的類
    <bean name="/t1" class="com.edgar.controller.ControllerTest1"/>
               
  4. 編寫前端test.jsp,注意在WEB-INF/jsp目錄下編寫,對應我們的視圖解析器
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    ${msg}
    </body>
    </html>
               
  5. 配置Tomcat運作測試,我這裡沒有項目釋出名配置的就是一個 / ,是以請求不用加項目名,OK!
    SpringMVC05:RestFul和控制器

說明:

  • 實作接口Controller定義控制器是較老的辦法
  • 缺點是:一個控制器中隻有一個方法,如果要多個方法則需要定義多個Controller;定義的方式比較麻煩;

使用注解@Controller

  • @Controller注解類型用于聲明Spring類的執行個體是一個控制器(在講IOC時還提到了另外3個注解);
  • Spring可以使用掃描機制來找到應用程式中所有基于注解的控制器類,為了保證Spring能找到你的控制器,需要在配置檔案中聲明元件掃描。
    <!-- 自動掃描指定的包,下面所有注解類交給IOC容器管理 -->
    <context:component-scan base-package="com.edgar.controller"/>
               
  • 增加一個ControllerTest2類,使用注解實作;
    package com.edgar.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    // 被@Controller注解的類,代表這個類被Spring接管,這個類中的所有方法,如果傳回值是String,并且有具體頁面可以跳轉,那麼就會被視圖解析器解析;
    @Controller
    public class ControllerTest2 {
    	// 映射通路路徑
        @RequestMapping("/t2")
        public String test1(Model model) {
            // Spring MVC會自動執行個體化一個Model對象用于向視圖中傳值
            model.addAttribute("msg", "ControllerTest2");
             // 傳回視圖位置
            return "test";
        }
    
        @RequestMapping("/t3")
        public ModelAndView test1(ModelAndView mv) {
            mv.addObject("msg","test3");
            mv.setViewName("test");
            return mv;
        }
    }
               
  • 運作tomcat測試
    SpringMVC05:RestFul和控制器

可以發現,我們的兩個請求都可以指向一個視圖,但是頁面結果的結果是不一樣的,從這裡可以看出視圖是被複用的,而控制器與視圖之間是弱偶合關系。

注解方式是平時使用的最多的方式!

RequestMapping

@RequestMapping

  • @RequestMapping注解用于映射url到控制器類或一個特定的處理程式方法。可用于類或方法上。用于類上,表示類中的所有響應請求的方法都是以該位址作為父路徑。
  • 為了測試結論更加準确,我們可以加上一個項目名測試 myweb
  • 隻注解在方法上面
    package com.edgar.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class ControllerTest3 {
    
        @RequestMapping("t1")
        public String test1(Model model){
            model.addAttribute("msg","ControllerTest3");
            return "test";
        }
    }
               
    通路路徑:

    http://localhost:8080/myweb/t1

  • 同時注解類與方法
    package com.edgar.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    @RequestMapping("/c3")
    public class ControllerTest3 {
    
        @RequestMapping("/t1")
        public String test1(Model model){
            model.addAttribute("msg","ControllerTest3");
            return "test";
        }
    }
               

    http://localhost:8080/myweb/c3/t1

    , 需要先指定類的路徑再指定方法的路徑;

RestFul風格

概念

Restful就是一個資源定位及資源操作的風格。不是标準也不是協定,隻是一種風格。基于這個風格設計的軟體可以更簡潔,更有層次,更易于實作緩存等機制。

功能

資源:網際網路所有的事物都可以被抽象為資源

資源操作:使用POST、DELETE、PUT、GET,使用不同方法對資源進行操作。

分别對應:

  • post:添加
  • delete:删除
  • put:修改
  • get:查詢

傳統方式操作資源:通過不同的參數來實作不同的效果!方法單一,post和get

http://127.0.0.1/item/queryItem.action?id=1

查詢,GET

http://127.0.0.1/item/saveItem.action

新增,POST

http://127.0.0.1/item/updateItem.action

更新,POST

http://127.0.0.1/item/deleteItem.action?id=1

删除,GET或POST

使用RestFul操作資源:可以通過不同的請求方式來實作不同的效果!如下:請求位址一樣,但是功能不同!

http://127.0.0.1/item/1

http://127.0.0.1/item

http://127.0.0.1/item

更新,PUT

http://127.0.0.1/item/1

删除,DELETE

學習測試

  1. 在建立一個類RestFulController
    @Controller
    public class RestFulController {
    }
               
  2. 在Spring MVC中可以i使用 @PathVariable 注解,讓方法參數的值對應綁定到一個URL模闆變量上。
    package com.edgar.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    public class RestFulController {
    	// 映射通路路徑
        // 原來的 : http://localhost:8080/add?a=1&b=2
        // RestFul : http://localhost:8080/add/a/b
        @RequestMapping(value = "/add/{a}/{b}", method = RequestMethod.GET)
        public String test1(@PathVariable int a, @PathVariable int b, Model model) {
            int res = a + b;
            // Spring MVC會自動執行個體化一個Model對象用于向視圖中傳值
            model.addAttribute("msg", "結果1為" + res);
            // 傳回視圖位置
            return "test";
        }
    }
               
  3. 我們來測試請求看下
    SpringMVC05:RestFul和控制器
  4. 思考:使用路徑變量的好處?
    • 是路徑變得更加簡潔
    • 獲得參數更加友善,架構會自動進行類型轉換
    • 隐藏了參數名,更加安全
    • 通過路徑變量的類型可以限制通路參數,如果類型不一樣,則通路不到對應的請求方法,如這裡通路的路徑是/add/1/a,則路徑方法不比對,而不會是參數轉換失敗
    SpringMVC05:RestFul和控制器
  5. 我們來修改下對應的參數類型,再次測試
    // 映射通路路徑(value或path)
    @RequestMapping(value = "/add/{a}/{b}", method = RequestMethod.GET)
    public String test1(@PathVariable int a, @PathVariable String b, Model model) {
        String res = a + b;
        // Spring MVC會自動執行個體化一個Model對象用于向視圖中傳值
        model.addAttribute("msg", "結果1為" + res);
        // 傳回視圖位置
        return "test";
    }
               
    SpringMVC05:RestFul和控制器

使用method屬性指定請求類型

用于限制請求的類型,可以收窄請求範圍。可以指定的請求類型:

GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
           

1,GET

安全、幂等;

用于擷取資源;

2,HEAD

與get方法類似,但不傳回message body内容,僅僅是獲得擷取資源的部分資訊(content-type、content-length);

restful架構中較少使用

3,POST

非安全、非幂等;

用于建立子資源

4,PUT

非安全、幂等;

用于建立、更新資源;

5,DELETE

删除資源;

6,OPTIONS

用于url驗證,驗證接口服務是否正常;

7,TRACE

維基百科“回顯伺服器收到的請求,這樣用戶端可以看到(如果有)哪一些改變或者添加已經被中間伺服器實作。”

8,PATCH

用于建立、更新資源,于PUT類似,差別在于PATCH代表部分更新;

後來提出的接口方法,使用時可能去要驗證用戶端和服務端是否支援;

我們來測試一下:

  • 修改上面的一個方法
    // 映射通路路徑(value或path)
    @RequestMapping(value = "/add/{a}/{b}", method = RequestMethod.POST)
    public String test1(@PathVariable int a, @PathVariable String b, Model model) {
        String res = a + b;
        // Spring MVC會自動執行個體化一個Model對象用于向視圖中傳值
        model.addAttribute("msg", "結果1為" + res);
        // 傳回視圖位置
        return "test";
    }
               
  • 我們使用浏覽器位址欄進行通路預設是Get請求,會報錯405:
    SpringMVC05:RestFul和控制器
  • 如果将POST修改為GET則正常了
    // 映射通路路徑(value或path)
    @RequestMapping(value = "/add/{a}/{b}", method = RequestMethod.GET)
    public String test1(@PathVariable int a, @PathVariable String b, Model model) {
        String res = a + b;
        // Spring MVC會自動執行個體化一個Model對象用于向視圖中傳值
        model.addAttribute("msg", "結果1為" + res);
        // 傳回視圖位置
        return "test";
    }
               
    SpringMVC05:RestFul和控制器

小結

Spring MVC的 @RequestMapping 注解能夠處理HTTP請求的方法,比如GET, PUT, POST, DELETE 以及 PATCH。

所有的位址欄請求預設都會是 HTTP GET 類型的。

方法級别的注解變體有如下幾個:組合注解

@PostMapping
@DeleteMapping
@PutMapping
@GetMapping
@PatchMapping
           

@GetMapping 是一個組合注解,平時使用的會比較多!

它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一個快捷方式。

@GetMapping("/add/{a}/{b}")
public String test2(@PathVariable int a, @PathVariable String b, Model model) {
    String res = a + b;
    model.addAttribute("msg", "結果2為" + res);
    return "test";
}
           

等價于

@RequestMapping(value = "/add/{a}/{b}", method = RequestMethod.GET)
public String test2(@PathVariable int a, @PathVariable String b, Model model) {
    String res = a + b;
    model.addAttribute("msg", "結果2為" + res);
    return "test";
}
           

SpringMVC05:RestFul和控制器