Rest風格的介紹
如今各大公司都是使用restful風格來定義接口,restful也是一套接口的規範,restful可以使我們的接口更加簡潔、快捷高效、透明。
請求方式 | 對應屬性 | 使用方式 |
GET | 查詢 | 表單請求方式為get |
POST | 新增 | 表單請求方式為post |
DELETE | 删除 | 表單請求方式為post/前段架構中發ajax請求可以為delete |
PUT | 修改 | 表單請求方式為post/前段架構中發ajax請求可以為put |
很顯然,這對應着我們開發中必不可少的增删改查。下面來個具體的案例來介紹一下。
Rest風格的案例
Controller層
@RestController
public class RestStyleController {
@RequestMapping(value = "getRestStyle",method = RequestMethod.GET)
// @GetMapping("/getRestStyle") 等價于上面代碼
public String getRestStyle(){
return "this is getRestStyle";
}
@RequestMapping(value = "postRestStyle",method = RequestMethod.POST)
// @PostMapping("/postRestStyle") 等價于上面代碼
public String postRestStyle(){
return "this is postRestStyle";
}
@RequestMapping(value = "deleteRestStyle",method = RequestMethod.DELETE)
// @DeleteMapping("/deleteRestStyle") 等價于上面代碼
public String deleteRestStyle(){
return "this is deleteRestStyle";
}
@RequestMapping(value = "putRestStyle",method = RequestMethod.PUT)
// @PutMapping("/putRestStyle") 等價于上面代碼
public String putRestStyle(){
return "this is putRestStyle";
}
}
HTML代碼,注意HTML檔案要放在Spring boot預設掃描的靜态檔案夾裡面,比如static等等...
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>RestStyleTest</title>
</head>
<body>
<h1>CRUD攻城獅</h1>
<!-- get請求 -->
<form action="/getRestStyle" method="get">
<input type="submit" value="get查詢請求">
</form>
<!-- post請求 -->
<form action="/postRestStyle" method="post">
<input type="submit" value="post增加請求">
</form>
<!-- delete請求 -->
<form action="/deleteRestStyle" method="post">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="delete删除請求">
</form>
<!-- put請求 -->
<form action="/putRestStyle" method="post">
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="put修改請求">
</form>
</body>
</html>
測試如下:
測試DELETE和PUT的時候就發現報405錯誤了,後端控制台說目前請求不支援Post請求,不用擔心我們看到源碼。
這裡自動裝配的時候給出一個條件,也就是我們的配置檔案中是否配置了spring.mvc.formcontent.filter.enable是不是為true,預設是false,也就是說Spring boot并沒有把支援rest風格的配置類給注入到IoC容器中,是以我們在我們的.properties或者.yaml檔案中配置一下就可以了。
# 開啟支援rest風格的請求
spring.mvc.hiddenmethod.filter.enabled=true
重新開機一下項目。再次測試!
測試全部通過,那麼下面就是源碼環節!
Rest風格的底層源碼
如今都是Spring boot的天下,以前傳統的ssm架構+tomcat項目已經基本淘汰了,是以源碼隻講解Spring boot的。
對于Spring boot來說是幫開發者減輕了大部分的配置,讓開發者專注于業務層面,是以我們就往自動配置檔案走,Spring boot對于自動配置是有一個規範也就是需要在MATE-INF/spring.factories中定義好自動配置的類,讓Spring boot來掃描并注入到IoC容器中,是以我們在Spring boot自帶的自動配置包中的spring.factories中找到WebMvcAutoConfiguration,關于Web開發的自動配置基本都在這裡了。
我覺得繼續往下之前,我們可以來一個推理過程:
- 我們可以清楚的看到自動配置的類是有Filter的蹤迹,是以目測他是通過JavaWeb的過濾器來做的一些判斷和修改。
- 我們再編寫DELETE和PUT兩個方式的請求的表單時候,需要寫一個input來隐藏,中間有一個name标簽為_method,value标簽為DELETE,是以我們可以推測底層肯定是通過這個隐藏的标簽的值來做的判斷。
并且這裡複習一下JavaWeb的過濾器。
init:對過濾器做一些初始化操作
doFilter:放行操作,可以在放行前做一些自定義的事情
destroy:摧毀前的回調
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 擷取到目前的request請求對象
HttpServletRequest requestToUse = request;
// 判斷目前請求是否是post請求,雖然我們可能是DELETE或者是PUT但是請求方法還是POST
if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
// 從request請求中擷取到this.methodParam的值,這個值就是_method
String paramValue = request.getParameter(this.methodParam);
// 判斷是否存在_method
// 如果不存在就直接跳過這裡,執行doFilter執行下一個過濾器了
if (StringUtils.hasLength(paramValue)) {
// 轉換成大寫
String method = paramValue.toUpperCase(Locale.ENGLISH);
// 判斷是不是rest風格的參數。
if (ALLOWED_METHODS.contains(method)) {
// 是rest風格的就建立一個HttpMethodRequestWrapper
// 其實HttpMethodRequestWrapper也就是一個标準的裝飾器模式,套了一層而已底層還是HttpServletRequest
requestToUse = new HttpMethodRequestWrapper(request, method);
}
}
}
// 放行操作
filterChain.doFilter(requestToUse, response);
}
上面代碼塊的大緻操作:
- 擷取到request請求對象
- 判斷是不是post請求,因為我們定義的DELETE還是PUT最終請求方式都是post方式送出
- 如果是post請求就擷取到我們隐藏表單的值,也就是_method的值
- 判斷_method對應的值是不是SpringMVC支援的rest風格的值。
- 如果是SpringMVC支援的rest風格的值,就建立一個HttpMethodRequestWrapper對象,HttpMethodRequestWrapper也就是在原本的request上面套了一層而已。
- 放行,後續使用的都是HttpMethodRequestWrapper對象。
這個方法介紹完就介紹完底層了,也就是通過過濾器把請求的參數給擷取到,然後封裝成一個特别的request請求對象然後後續就是通過tomcat與servlet打交道,最後就到了DispatcherServlet的doDispatch方法然後就處理我們的請求。不是很懂DispatcherServlet的可以跳轉下面連結學習
DispatcherServlet的初步認識
https://blog.csdn.net/qq_43799161/article/details/122283520?spm=1001.2014.3001.5501SpringMVC工作流程
https://blog.csdn.net/qq_43799161/article/details/122309958?spm=1001.2014.3001.5501
我們知道底層肯定是過濾器,但是我們是不是要考慮一下為什麼會走到這個doFilterInternal重寫方法來?
模闆模式的學習
https://blog.csdn.net/qq_43799161/article/details/123635463?spm=1001.2014.3001.5501
大緻就是tomcat維護了一個過濾器鍊,一個一個執行,而對于SpringMVC來說實作了過濾器,是以請求一過來先進入到Tomcat,然後執行一個過濾器鍊(這裡包括SpringMVC定義的)然後就走到OncePerRequestFilter過濾器,這類也是HiddenHttpMethodFilter父類,他其中定義了一個模闆模式的模闆方法,來讓HiddenHttpMethodFilter子類實作邏輯,而子類也是對Rest方式接口做一個判斷來對request對象做一個增強。
總結
對于Rest風格的使用來說沒啥好總結的,但是對于源碼來說呢。葉子->樹幹->整課樹,是以看任何一個關于Spring系列的架構都少不了一些核心源碼的支援。是以建議大家沒事多去累計一些關鍵核心源碼,因為如今JavaEE已經是Spring系列的天下了,什麼都逃不過這些核心源碼!部落客也是一個專門寫熱門架構使用和源碼解讀的,是以可以關注一下~!
最後,如果本帖對您有一定的幫助,希望您點贊+關注+收藏,您的支援是給我最大的動力,後續一直會更新熱門架構的使用和源碼解讀~!