天天看點

Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結

Rest風格的介紹

如今各大公司都是使用restful風格來定義接口,restful也是一套接口的規範,restful可以使我們的接口更加簡潔、快捷高效、透明。

常見的Rest風格/CRUD

請求方式 對應屬性 使用方式
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>
           

測試如下:

Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結
Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結
Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結
Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結
Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結

 測試DELETE和PUT的時候就發現報405錯誤了,後端控制台說目前請求不支援Post請求,不用擔心我們看到源碼。

Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結

 這裡自動裝配的時候給出一個條件,也就是我們的配置檔案中是否配置了spring.mvc.formcontent.filter.enable是不是為true,預設是false,也就是說Spring boot并沒有把支援rest風格的配置類給注入到IoC容器中,是以我們在我們的.properties或者.yaml檔案中配置一下就可以了。

# 開啟支援rest風格的請求
spring.mvc.hiddenmethod.filter.enabled=true   
           

重新開機一下項目。再次測試!

Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結
Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結

測試全部通過,那麼下面就是源碼環節!

Rest風格的底層源碼

如今都是Spring boot的天下,以前傳統的ssm架構+tomcat項目已經基本淘汰了,是以源碼隻講解Spring boot的。

對于Spring boot來說是幫開發者減輕了大部分的配置,讓開發者專注于業務層面,是以我們就往自動配置檔案走,Spring boot對于自動配置是有一個規範也就是需要在MATE-INF/spring.factories中定義好自動配置的類,讓Spring boot來掃描并注入到IoC容器中,是以我們在Spring boot自帶的自動配置包中的spring.factories中找到WebMvcAutoConfiguration,關于Web開發的自動配置基本都在這裡了。

Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結
Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結

我覺得繼續往下之前,我們可以來一個推理過程:

  1. 我們可以清楚的看到自動配置的類是有Filter的蹤迹,是以目測他是通過JavaWeb的過濾器來做的一些判斷和修改。
  2. 我們再編寫DELETE和PUT兩個方式的請求的表單時候,需要寫一個input來隐藏,中間有一個name标簽為_method,value标簽為DELETE,是以我們可以推測底層肯定是通過這個隐藏的标簽的值來做的判斷。

并且這裡複習一下JavaWeb的過濾器。

Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結

 init:對過濾器做一些初始化操作

doFilter:放行操作,可以在放行前做一些自定義的事情

destroy:摧毀前的回調

Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結
@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);
}
           

上面代碼塊的大緻操作:

  1. 擷取到request請求對象
  2. 判斷是不是post請求,因為我們定義的DELETE還是PUT最終請求方式都是post方式送出
  3. 如果是post請求就擷取到我們隐藏表單的值,也就是_method的值
  4. 判斷_method對應的值是不是SpringMVC支援的rest風格的值。
  5. 如果是SpringMVC支援的rest風格的值,就建立一個HttpMethodRequestWrapper對象,HttpMethodRequestWrapper也就是在原本的request上面套了一層而已。
  6. 放行,後續使用的都是HttpMethodRequestWrapper對象。

這個方法介紹完就介紹完底層了,也就是通過過濾器把請求的參數給擷取到,然後封裝成一個特别的request請求對象然後後續就是通過tomcat與servlet打交道,最後就到了DispatcherServlet的doDispatch方法然後就處理我們的請求。不是很懂DispatcherServlet的可以跳轉下面連結學習

DispatcherServlet的初步認識

Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結

https://blog.csdn.net/qq_43799161/article/details/122283520?spm=1001.2014.3001.5501SpringMVC工作流程

Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結

https://blog.csdn.net/qq_43799161/article/details/122309958?spm=1001.2014.3001.5501

我們知道底層肯定是過濾器,但是我們是不是要考慮一下為什麼會走到這個doFilterInternal重寫方法來?

Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結
Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結

模闆模式的學習

Spring boot實作Rest風格請求及底層原理Rest風格的介紹Rest風格的案例Rest風格的底層源碼總結

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系列的天下了,什麼都逃不過這些核心源碼!部落客也是一個專門寫熱門架構使用和源碼解讀的,是以可以關注一下~!

最後,如果本帖對您有一定的幫助,希望您點贊+關注+收藏,您的支援是給我最大的動力,後續一直會更新熱門架構的使用和源碼解讀~!