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;
}
測試
- 建立一個Moudle,springmvc-04-controller。将springmvc-03-annotation拷貝一份。
- 删掉HelloController
- springmvc-servlet.xml配置檔案中隻留下視圖解析器
- 編寫一個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; } }
- 編寫完畢後,去springmvc-servlet.xml檔案中注冊請求的bean;name對應請求路徑,class對應處理請求的類
<bean name="/t1" class="com.edgar.controller.ControllerTest1"/>
- 編寫前端test.jsp,注意在WEB-INF/jsp目錄下編寫,對應我們的視圖解析器
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${msg} </body> </html>
- 配置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
學習測試
- 在建立一個類RestFulController
@Controller public class RestFulController { }
- 在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"; } }
- 我們來測試請求看下
SpringMVC05:RestFul和控制器 - 思考:使用路徑變量的好處?
- 是路徑變得更加簡潔
- 獲得參數更加友善,架構會自動進行類型轉換
- 隐藏了參數名,更加安全
- 通過路徑變量的類型可以限制通路參數,如果類型不一樣,則通路不到對應的請求方法,如這裡通路的路徑是/add/1/a,則路徑方法不比對,而不會是參數轉換失敗
SpringMVC05:RestFul和控制器 - 我們來修改下對應的參數類型,再次測試
// 映射通路路徑(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和控制器