
HttpMethod雖然它被設計為final class而非enum(出于歷史兼容性考慮),但它的作用與枚舉完全一致:為 HTTP 協議中定義的 8 種標準請求方法提供類型安全的常量,并允許擴展非標準方法。下面我將其拆解為三個層次,詳細解釋每一部分的設計意圖和實際用途。1. 類定義與整體設計publicfinalclassHttpMethodimplementsComparableHttpMethod,Serializable{// ...}final class:表示該類不能被繼承,確保所有實例的行為都是確定且統一的。ComparableHttpMethod:實現自然排序,基于方法名稱的字符串順序(如DELETEGET)。主要用于集合排序。Serializable:允許HttpMethod對象在網絡傳輸或序列化到磁盤時保持狀態(例如在分布式緩存或 RPC 調用中)。設計意圖:在 Spring 3.0 之前,HttpMethod是一個普通的enum。后來為了允許用戶自定義非標準 HTTP 方法(如 WebDAV 的PROPFIND),Spring 將其改為final class,同時保留預定義常量。這種設計既提供了類型安全,又保持了擴展性。2. 預定義常量(標準 HTTP 方法)類中定義了 8 個public static final常量,對應 HTTP/1.1 規范(RFC 2616)及 PATCH(RFC 5789)中的所有方法:常量名對應方法典型用途GETGET請求獲取資源(安全、冪等)HEADHEAD僅獲取響應頭,不返回實體(安全、冪等)POSTPOST創建新資源或提交數據(非安全、非冪等)PUTPUT完整更新資源(冪等)PATCHPATCH部分更新資源(非冪等)DELETEDELETE刪除資源(冪等)OPTIONSOPTIONS查詢服務器支持的 HTTP 方法(安全、冪等)TRACETRACE回顯服務器收到的請求(用于診斷,常被禁用)每個常量的注釋都引用了相應的 RFC 文檔,方便開發者查閱標準。實現細節:每個常量都是通過私有構造器new HttpMethod("GET")創建的,因此所有預定義常量都是該類的單例實例。3. 核心靜態方法values()publicstaticHttpMethod[]values(){HttpMethod[]copy=newHttpMethod[values.length];System.arraycopy(values,0,copy,0,values.length);returncopy;}作用:返回所有預定義常量的副本數組,避免外部修改內部數組。用法:類似枚舉的values(),通常用于遍歷或轉換為集合。valueOf(String method)publicstaticHttpMethodvalueOf(Stringmethod){Assert.notNull(method,"Method must not be null");returnswitch(method){case"GET"-GET;case"HEAD"-HEAD;// ...default-newHttpMethod(method);};}作用:將字符串轉換為HttpMethod對象。關鍵行為:如果字符串匹配預定義常量(區分大小寫,必須是大寫),則返回對應的單例。如果字符串不匹配,則創建一個新的HttpMethod實例(例如"PROPFIND")。注意:這意味著HttpMethod.valueOf("get")會返回一個新對象,且該對象與HttpMethod.GET不相等(equals比較字符串名稱)。這種設計使得任何字符串都能被包裝為HttpMethod,但只有標準方法才擁有單例。4. 實例方法name()返回 HTTP 方法名稱的字符串(如"GET")。matches(String method)判斷當前對象的方法名是否與給定字符串相等(區分大小寫)。等價于name().equals(method),但更語義化。compareTo(HttpMethod other)基于name的字典序進行比較,符合Comparable契約。equals/hashCode/toString重寫自Object,均基于name字段。因此兩個不同實例但名稱相同(如new HttpMethod("GET")和HttpMethod.GET)會被視為相等,但實際開發中不會這樣使用。5. 設計亮點與實戰關聯類型安全與擴展性的平衡類型安全:方法參數使用HttpMethod而非String,防止拼寫錯誤。擴展性:允許創建任意非標準方法對象,而無需修改類定義,適配了 WebDAV、自定義 REST 動詞等場景。在 Spring 生態中的廣泛應用RestTemplate、WebClient、@RequestMapping等均使用HttpMethod作為參數或屬性。在WebSocket 握手場景中,握手請求本身就是一個 HTTP 升級請求,其方法通常是GET。因此HttpMethod.GET在HandshakeInterceptor中會被用來判斷請求類型。與你的聊天軟件的聯系在你的HandshakeInterceptor實現中,可以通過ServerHttpRequest.getMethod()獲取請求方法:if(request.getMethod()!=HttpMethod.GET)