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.rhkb.cn/news/269109.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Gitlab: PHP项目CI/CD实践

目录 1 说明 2 CI/CD 2.1 部署方式一&#xff1a;增量部署 2.1.1 目标服务器准备 2.2.2 Gitlab及Envoy脚本 2.2 部署方式二&#xff1a;镜像构建与部署 2.2.1 推送到私有化容器仓库 准备工作 脚本 要点 2.2.2 推送到hub.docker.com 准备工作 脚本 3 参考&#x…

鸿蒙实战应用开发:【拨打电话】功能

概述 本示例通过输入电话&#xff0c;进行电话拨打&#xff0c;及电话相关信息的显示。 样例展示 涉及OpenHarmony技术特性 网络通信 基础信息 拨打电话 介绍 本示例使用call相关接口实现了拨打电话并显示电话相关信息的功能 效果预览 使用说明 1.输入电话号码后&#…

「滚雪球学Java」:多线程(章节汇总)

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

STM32F1 - SPI读写Flash

Serial peripheral interface 1> 实验概述2> SPI硬件框图初始化程序 3> STM32的SPI通信时序3.1> 时序图3.2> 文字描述3.3> 注意事项3.4> 流程图表示3.5> 程序表示接收程序&#xff1a;发送程序&#xff1a; 4> SPI的4种模式5> W25Q128存储结构块…

【学习心得】网站运行时间轴(爬虫逆向)

一、网站运行时间轴 掌握网站运行时间轴&#xff0c;有助于我们对“请求参数加密”和“响应数据加密”这两种反爬手段的深入理解。 二、从网站运行的时间轴角度来理解两种反爬手段 1、加载HTML&#xff1a; 这是浏览器访问网站时的第一步&#xff0c;服务器会返回基础…

docker基线安全修复和容器逃逸修复

一、docker安全基线存在的问题和修复建议 1、将容器的根文件系统挂载为只读 修复建议&#xff1a; 添加“ --read-only”标志&#xff0c;以允许将容器的根文件系统挂载为只读。 可以将其与卷结合使用&#xff0c;以强制容器的过程仅写入要保留的位置。 可以使用命令&#x…

基于Springboot的助农管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的助农管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&…

台式电脑电源各线的电压和电流输出和输出电流

台式电脑电源是电脑硬件的重要组成部分。 它为计算机的各个部件提供所需的电压和电流。 不同的硬件设备和组件有不同的电压和电流输出。 下面详细介绍台式电脑电源各线的电压&#xff0c;包括3.3V、5V、12V、-12V、-5V和5VSB&#xff0c;以及它们的输出电流和用途。 3.3V&#…

Java递归生成本地文件目录树形结构

Java递归生成本地文件目录(树行结构) 1.读取txt文件保存的文件目录结构 2.递归生成本地文件目录树形结构&#xff0c;并修改目录文件前缀进行递增 3.结果截图 4.代码 package com.zfi.server.device;import io.swagger.annotations.Api; import org.springframework.web.bind…

Leaflet 加载高德地图

前言 在前面的文章中&#xff0c;我们学习了如何使用 Leaflet 创建一个基本的地图。在本文中&#xff0c;我们将学习如何在 Leaflet 中加载高德地图&#xff0c;并结合实际应用构建地图点击事件。 一、介绍 高德地图是一款由高德软件提供的数字地图服务&#xff0c;在国内使用…

数学建模【灰色关联分析】

一、灰色关联分析简介 一般的抽象系统,如社会系统、经济系统、农业系统、生态系统、教育系统等都包含有许多种因素&#xff0c;多种因素共同作用的结果决定了该系统的发展态势。人们常常希望知道在众多的因素中&#xff0c;哪些是主要因素&#xff0c;哪些是次要因素;哪些因素…

Apache SeaTunnel 2.3.4 版本发布:功能升级,性能提升

​Apache SeaTunnel团队自豪地宣布2.3.4版本正式发布&#xff01;本次更新聚焦于增强核心功能&#xff0c;改善用户体验&#xff0c;并进一步优化文档质量。 此次版本发布带来了多项重要更新和功能增强&#xff0c;包括核心与API的修复、文档的全面优化、Catalog支持的引入&…

【S32DS报错】-7-程序进入HardFault_Handler,无法正常运行

【S32K3_MCAL从入门到精通】合集&#xff1a; S32K3_MCAL从入门到精通https://blog.csdn.net/qfmzhu/category_12519033.html 问题背景&#xff1a; 在S32DS IDE中使用PEmicro&#xff08;Multilink ACP&#xff0c;Multilink Universal&#xff0c;Multilink FX&#xff09…

【Kotlin】函数

1 常规函数 1.1 无参函数 fun main() {myFun() }fun myFun() {println("myFun") // 打印: myFun } 1.2 有参函数 1&#xff09;常规调用 fun main() {myFun("myFun") // 打印: myFun }fun myFun(str: String) {println(str) } 2&#xff09;形参指定默…

Doris实战——美联物业数仓

目录 一、背景 1.1 企业背景 1.2 面临的问题 二、早期架构 三、新数仓架构 3.1 技术选型 3.2 运行架构 3.2.1 数据模型 纵向分域 横向分层 数据同步策略 3.2.2 数据同步策略 增量策略 全量策略 四、应用实践 4.1 业务模型 4.2 具体应用 五、实践经验 5.1 数据…

张宇30讲学习笔记

初等数学 x \sqrt{x} x ​是算数平方根&#xff0c;一定≥0&#xff1b; x 2 \sqrt{x^2} x2 ​|x| x2|x2||x|2 x3≠|x3||x|3 不等式 a>0&#xff0c;b>0&#xff0c;则ab≥2 a b \sqrt{ab} ab ​ 对数 ln a b \frac{a}{b} ba​lna-lnb 高等数学 单调性 线性代数

【六袆 - MySQL】MySQL 5.5及更高版本中,InnoDB是新表的默认存储引擎;

InnoDB 这是一个MySQL组件&#xff0c;结合了高性能和事务处理能力&#xff0c;以确保可靠性、健壮性和并发访问。它体现了ACID设计哲学。它作为一个存储引擎存在&#xff0c;处理使用ENGINEINNODB子句创建的或修改的表。请参阅第14章“InnoDB存储引擎”以获取有关架构细节和管…

Android14之解决编译报错:bazel: no such file or directory(一百八十九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

【暗月安全】2021年渗透测试全套培训视频

参与培训需要遵守国家法律法规&#xff0c;相关知识只做技术研究&#xff0c;请勿用于违法用途&#xff0c;造成任何后果自负与本人无关。 中华人民共和国网络安全法&#xff08;2017 年 6 月 1 日起施行&#xff09; 第二十二条 任何个人和组织不得从事入侵他人网络、干扰他…

12 权重衰退【李沐动手学深度学习v2课程笔记】

1.权重衰退 使用均方范数来进行权重衰退 柔性限制 柔性限制对最优解的影响 参数更新法则 总结 2.代码实现 %matplotlib inline import torch from torch import nn from d2l import torch as d2l 生成数据 n_train, n_test, num_inputs, batch_size 20, 100, 200, 5 true_w, t…