小工具知识网

当前位置: 首页 > 行业知识 > Spring Boot项目中不使用@RequestMapping相关注解,如何动态发布自定义URL路径

行业知识

Spring Boot项目中不使用@RequestMapping相关注解,如何动态发布自定义URL路径

2026-11-03 18:01:52 来源:互联网转载

一、前言

在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;@RestControllerpublic class TestController {    @RequestMapping("/test/url")    public String test(@RequestParam String name, @RequestBody Map map) { // 这里只是方便测试,实际情况下,请勿使用Map作为参数接收        StringBuilder stringBuilder = new StringBuilder();        stringBuilder.append("hello, ").append(name).append(", receive param:");        for (Map.Entry entry : map.entrySet()) {            stringBuilder.append("\n").append("key: ").append(entry.getKey()).append("--> value: ").append(entry.getValue());        }        return stringBuilder.toString();    }}

测试效果:

三、自定义URL发布逻辑

参考步骤二的测试截图效果,我们自定义发布一个URL。

1. 新建一个spring boot项目,导入相关依赖

                    org.springframework.boot            spring-boot-starter-web                            org.projectlombok            lombok        

2. 修改Controller实现类代码

去掉@RestController和@RequestMapping相关注解,示例代码如下:

import org.springframework.stereotype.Component;import org.springframework.web.bind.annotation.ResponseBody;import java.util.Map;// @RestController@Componentpublic class TestController {    //@RequestMapping("/test/url")    @ResponseBody  // 注意:此注解需要添加,不能少    public String test(/*@RequestParam*/ String name,/* @RequestBody*/ Map map) { // 这里只是方便测试,实际情况下,请勿使用Map作为参数接收        StringBuilder stringBuilder = new StringBuilder();        stringBuilder.append("hello, ").append(name).append(", receive param:");        for (Map.Entry 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 */@Componentpublic class CustomRegisterUrl implements ApplicationListener {    /**     * 标识事件监听器是否已经注册,避免重复注册     */    private volatile AtomicBoolean flag = new AtomicBoolean(false);    /**     * 需要发布的地址     */    public static final String CUSTOM_URL = "/test/url";    @Autowired    private RequestMappingHandlerMapping requestMappingHandlerMapping;    @Autowired    private TestController testController;    @SneakyThrows    @Override    public 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;@Componentpublic class CustomHandlerUrl {    public static final Method HANDLE_CUSTOM_URL_METHOD;    private static final ObjectMapper OBJECTMAPPER = new ObjectMapper();    @Autowired    private 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 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 */@Componentpublic class CustomRegisterUrl implements ApplicationListener {    /**     * 标识事件监听器是否已经注册,避免重复注册     */    private volatile AtomicBoolean flag = new AtomicBoolean(false);    /**     * 需要发布的地址     */    public static final String CUSTOM_URL = "/test/url";    @Autowired    private RequestMappingHandlerMapping requestMappingHandlerMapping;    @Autowired    private CustomHandlerUrl customHandlerUrl;    @Override    public 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时,选择这样处理好了,可以达到出其不意的效果。

上一篇:此 Google 帐号尚未与设备关联。要安装应用,请先访问设备上的 Play 商店应用。 了解详情(已解决)

下一篇:服务器ip地址怎么换国家?