Spring Boot項目中不使用@RequestMapping相關注解,如何動態發布自定義URL路徑

一、前言

在Spring Boot項目開發過程中,對于接口API發布URL訪問路徑,一般都是在類上標識@RestController或者@Controller注解,然后在方法上標識@RequestMapping相關注解,比如:@PostMapping@GetMapping注解,通過設置注解屬性,發布URL。在某些場景下,我覺得這樣發布URL太麻煩了,不適用,有沒有什么其他方法自由發布定義的接口呢?答案是肯定的。

二、一般開發流程

按照上面的描述,我們先看一下一般常用的開發代碼:

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.Map;@RestController
public class TestController {@RequestMapping("/test/url")public String test(@RequestParam String name, @RequestBody Map<String, Object> map) { // 這里只是方便測試,實際情況下,請勿使用Map作為參數接收StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("hello, ").append(name).append(", receive param:");for (Map.Entry<String, Object> entry : map.entrySet()) {stringBuilder.append("\n").append("key: ").append(entry.getKey()).append("--> value: ").append(entry.getValue());}return stringBuilder.toString();}}

測試效果:

在這里插入圖片描述

三、自定義URL發布邏輯

參考步驟二的測試截圖效果,我們自定義發布一個URL。

1. 新建一個spring boot項目,導入相關依賴

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>

2. 修改Controller實現類代碼

去掉@RestController@RequestMapping相關注解,示例代碼如下:

import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;import java.util.Map;// @RestController
@Component
public class TestController {//@RequestMapping("/test/url")@ResponseBody  // 注意:此注解需要添加,不能少public String test(/*@RequestParam*/ String name,/* @RequestBody*/ Map<String, Object> map) { // 這里只是方便測試,實際情況下,請勿使用Map作為參數接收StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("hello, ").append(name).append(", receive param:");for (Map.Entry<String, Object> entry : map.entrySet()) {stringBuilder.append("\n").append("key: ").append(entry.getKey()).append("--> value: ").append(entry.getValue());}return stringBuilder.toString();}}

3. 自定義一個事件監聽,實現URL發布功能

參考代碼如下:

import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;/*** 注冊一個web容器初始化以后的事件監聽,注冊自定義URL*/
@Component
public class CustomRegisterUrl implements ApplicationListener<WebServerInitializedEvent> {/*** 標識事件監聽器是否已經注冊,避免重復注冊*/private volatile AtomicBoolean flag = new AtomicBoolean(false);/*** 需要發布的地址*/public static final String CUSTOM_URL = "/test/url";@Autowiredprivate RequestMappingHandlerMapping requestMappingHandlerMapping;@Autowiredprivate TestController testController;@SneakyThrows@Overridepublic void onApplicationEvent(WebServerInitializedEvent event) {if (flag.compareAndSet(false, true)) {// 構建請求映射對象RequestMappingInfo requestMappingInfo = RequestMappingInfo.paths(CUSTOM_URL) // 請求URL.methods(RequestMethod.POST, RequestMethod.GET) // 請求方法,可以指定多個.build();// 發布url,同時指定執行該請求url的具體類變量的的具體方法requestMappingHandlerMapping.registerMapping(requestMappingInfo, testController, testController.getClass().getMethod("test", String.class, Map.class));}}
}

4. 測試效果

同樣請求:http://localhost:8080/test/url?name=jack

在這里插入圖片描述

可以看到,此時請求效果并不是正常的,存在參數丟失,怎么辦呢?

注意:如果請求出現如下錯誤:

java.lang.IllegalArgumentException: Expected lookupPath in request attribute "org.springframework.web.util.UrlPathHelper.PATH".

可以在application.yaml文件中添加如下內容:

spring:mvc:pathmatch:matching-strategy: ant_path_matcher

5. 增加統一請求處理器

為了實現參數可以正常解析,同時方便增加自定義處理邏輯,我們可以增加一個統一的請求處理器,參考示例:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;@Component
public class CustomHandlerUrl {public static final Method HANDLE_CUSTOM_URL_METHOD;private static final ObjectMapper OBJECTMAPPER = new ObjectMapper();@Autowiredprivate TestController testController;static {// 提前準備好參數對象Method tempMethod = null;try {tempMethod = CustomHandlerUrl.class.getMethod("handlerCustomUrl", HttpServletRequest.class, HttpServletResponse.class);} catch (NoSuchMethodException e) {e.printStackTrace();}HANDLE_CUSTOM_URL_METHOD = tempMethod;}@ResponseBody/***  攔截自定義請求的url,可以做成統一的處理器,這里我只做簡單實現,專門處理test*/public Object handlerCustomUrl(HttpServletRequest request, HttpServletResponse response) throws IOException {// 獲取參數 get方式請求參數String name = request.getParameter("name");// 獲取 post方式請求參數Map<String, Object> map = OBJECTMAPPER.readValue(request.getInputStream(), Map.class);// 執行業務方法String result = testController.test(name, map);return result;}
}

6. 修改事件監聽邏輯

修改事件監聽邏輯,此時注冊URL時,綁定統一處理器就行了。

示例代碼:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import java.util.concurrent.atomic.AtomicBoolean;/*** 注冊一個web容器初始化以后的事件監聽,注冊自定義URL*/
@Component
public class CustomRegisterUrl implements ApplicationListener<WebServerInitializedEvent> {/*** 標識事件監聽器是否已經注冊,避免重復注冊*/private volatile AtomicBoolean flag = new AtomicBoolean(false);/*** 需要發布的地址*/public static final String CUSTOM_URL = "/test/url";@Autowiredprivate RequestMappingHandlerMapping requestMappingHandlerMapping;@Autowiredprivate CustomHandlerUrl customHandlerUrl;@Overridepublic void onApplicationEvent(WebServerInitializedEvent event) {if (flag.compareAndSet(false, true)) {// 構建請求映射對象RequestMappingInfo requestMappingInfo = RequestMappingInfo.paths(CUSTOM_URL) // 請求URL.methods(RequestMethod.POST, RequestMethod.GET) // 請求方法,可以指定多個.build();// 發布url,指定一下url的處理器requestMappingHandlerMapping.registerMapping(requestMappingInfo, customHandlerUrl, CustomHandlerUrl.HANDLE_CUSTOM_URL_METHOD);}}
}

7. 重新測試

在這里插入圖片描述

此時,請求可以發現,效果和使用@RestController+@RequestMapping注解就一樣了。

四、寫在最后

自定義發布URL路徑一般情況下很少使用,不過針對特殊url的處理,以及自定義rpc框架發布url時,選擇這樣處理好了,可以達到出其不意的效果。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/715884.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/715884.shtml
英文地址,請注明出處:http://en.pswp.cn/news/715884.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Siamrpn++論文中文翻譯(詳細!)

SiamRPN: Evolution of Siamese Visual Tracking with Very Deep Networks SiamRPN&#xff1a;具有非常深度網絡的Siamese視覺跟蹤的進化 【siamrpn論文地址】 https://arxiv.org/abs/1812.11703 摘要 基于Siamese網絡的跟蹤器將跟蹤表示為目標模板和搜索區域之間的卷積特征…

【STA】多場景時序檢查學習記錄

單周期路徑 建立時間時序檢查 在時鐘的有效沿到達觸發器之前&#xff0c;數據應在一定時間內保持穩定&#xff0c;這段時間即觸發器的建立 時間。滿足建立時間要求將確保數據可靠地被捕獲到觸發器中。 建立時間檢查是從發起觸發器中時鐘的第一個有效沿到捕獲觸發器中時鐘后面…

理解大模型的5個關鍵公式

理解大模型的5個關鍵公式_嗶哩嗶哩_bilibili PPT&#xff1a;https://link.excalidraw.com/p/readonly/aBWlNjEckdUlrszwwo6V

基于springboot+vue的社區醫院管理系統

博主主頁&#xff1a;貓頭鷹源碼 博主簡介&#xff1a;Java領域優質創作者、CSDN博客專家、阿里云專家博主、公司架構師、全網粉絲5萬、專注Java技術領域和畢業設計項目實戰&#xff0c;歡迎高校老師\講師\同行交流合作 ?主要內容&#xff1a;畢業設計(Javaweb項目|小程序|Pyt…

chatgpt-3的文章生成器有哪些?可以批量生成文章的生成器

GPT-3&#xff08;Generative Pre-trained Transformer 3&#xff09;作為人工智能領域的一項重大突破&#xff0c;開啟了新一代的文本生成技術。同時市面上也涌現出了一些GPT-3文章生成器&#xff0c;為用戶提供了快速、高效地生成各種類型文章的工具。本文將介紹一些中國的GP…

unity-unity2d基礎操作筆記(三)0.5.000

目標是:牢記以下137條操作,越級上升到中級階段 unity-unity2d基礎操作筆記(三) 一百零一、如何操作一個游戲物體由多個部分組成的動畫一百零二、如何使用rigidbody 2d進行物體移動一百零三、獲取游戲物體身上的組件方法一百零四、代碼控制物體朝向一百零五、不使用插件,純…

C#上位機調試經驗

1.使用Visual Studio的遠程工具 因為上位機軟件安裝在工控機上&#xff0c;不方便調試。如果直接把代碼放在工控機上&#xff0c;又不太安全。 可以在工控機上安裝一個Visual Studio的遠程工具&#xff0c;把隨身帶的筆記本電腦通過網線插在工控機上 這樣可以在筆記本上使用…

s3cmd工具使用

1. 安裝s3cmd工具 [roottestserver01 ~]# yum install s3cmd 2. 配置s3cmd, 按提示輸入相應的ak&#xff0c;sk&#xff0c;endpoint等信息 [roottestserver01 ~]# s3cmd --configure 3. s3cmd使用 [roottestserver01 ~]# s3cmd mb s3://abc &#xff08;創建一個桶&am…

python筆記_程序流程控制

A&#xff0c;順序控制 程序從上到下逐行執行 python定義變量時&#xff0c;會合法地向前引用 age 1 age2 age 1 age2 age 1 age 1 ——>錯誤&#xff0c;age應在age2之前 B&#xff0c;分支控制 1&#xff0c;單分支if 語法 if 條件表達式 &#xff1a; 代碼塊 說明…

【六】【SQL】多表查詢,笛卡爾積

笛卡爾積 笛卡爾積發生在當你在查詢中將兩個或多個表進行交叉連接&#xff08;CROSS JOIN&#xff09;或者沒有指定任何連接條件時。假設第一個表有M行&#xff0c;第二個表有N行&#xff0c;那么結果集將包含M x N個記錄。在大多數情況下&#xff0c;笛卡爾積并不是你想要的結…

數字化轉型導師堅鵬:證券公司數字化思維升級之道

證券公司數字化思維升級之道 ——數字化思維之六脈神劍 課程背景&#xff1a; 很多證券公司存在以下問題&#xff1a; 不知道數字化轉型如何改變思維模式&#xff1f; 不清楚需要建立什么樣的數字化思維&#xff1f; 不知道如何開展數字化思維提升工作&#xff1f; 課…

Redis之十:Spring Data Redis --- CrudRepository方式

SpringData Redis CrudRepository方式 Spring Data Redis 的 CrudRepository 是 Spring Data 框架中用于提供基礎 CRUD&#xff08;創建、讀取、更新和刪除&#xff09;操作的一個接口。在與 Redis 集成時&#xff0c;盡管 Redis 是一個鍵值存儲系統&#xff0c;并沒有像關系型…

華為機試真題實戰應用【算法代碼篇】-去除多余空格(附Java、C++和python代碼)

目錄 問題描述 輸入描述 輸出描述 樣例 思路解析 代碼實現

關于福彩歷史數據采集器和體彩歷史數據采集器的下載安裝說明

前段時間因為研究基于人工神經網絡&#xff08;深度學習&#xff0c;所謂的“AI”算法&#xff09;對3D開獎數據進行預測&#xff0c;開發了兩款瀏覽器插件----“福彩歷史數據采集器”和“體彩歷史數據采集器”。之所以開發這兩款插件&#xff0c;是因為不管是基于什么樣的方式…

Unity 游戲設計模式:觀察者模式

本文由 簡悅 SimpRead 轉碼&#xff0c; 原文地址 mp.weixin.qq.com 在 unity 游戲設計中&#xff0c;觀察者模式&#xff08;Observer Pattern&#xff09;有著重要的作用&#xff0c;它主要用于實現對象之間的一對多的依賴關系&#xff0c;當一個對象的狀態發生變化時&#x…

【QT+QGIS跨平臺編譯】之六十三:【QGIS_CORE跨平臺編譯】—【錯誤處理:未定義的類QgsMapLayer - QgsMapLayerModel】

文章目錄 一、未定義的類QgsMapLayer二、解決辦法 一、未定義的類QgsMapLayer 報錯&#xff1a; 二、解決辦法 QgsMapLayerModel.h文件中 ①第27行修改為&#xff1a; #include "QgsMapLayer.h" ②第23行增加&#xff1a; #include <QPointer>

Github 2024-03-03 開源項目日報Top9

根據Github Trendings的統計&#xff0c;今日(2024-03-03統計)共有9個項目上榜。根據開發語言中項目的數量&#xff0c;匯總情況如下&#xff1a; 開發語言項目數量非開發語言項目4Rust項目1C項目1Jupyter Notebook項目1Python項目1Shell項目1 任天堂Switch模擬器yuzu&#x…

將jar程序封裝為docker鏡像 shell腳本

將JAR程序封裝為Docker鏡像通常涉及編寫一個Dockerfile&#xff0c;然后使用docker build命令構建鏡像。然而&#xff0c;如果你想要通過一個shell腳本來自動化這個過程&#xff0c;你可以創建一個腳本&#xff0c;該腳本首先創建一個Dockerfile&#xff0c;然后使用docker bui…

嵌入式驅動學習第一周——linux設備管理模型

前言 現在來聊點原理性的東西——linux設備管理模型 嵌入式驅動學習專欄將詳細記錄博主學習驅動的詳細過程&#xff0c;未來預計四個月將高強度更新本專欄&#xff0c;喜歡的可以關注本博主并訂閱本專欄&#xff0c;一起討論一起學習。現在關注就是老粉啦&#xff01; 行文目錄…

編寫dockerfile掛載卷

編寫dockerfile文件 [rootwq docker-test-volume]# vim dockerfile1 [rootwq docker-test-volume]# cat dockerfile1 FROM centosVOLUME ["volume01","volume02"]CMD echo "------end------" CMD /bin/bash [rootwq docker-test-volume]#使用do…