You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中如何基于注解修改@RequestMapping的URL端点?

解决Spring Boot通过自定义注解修改RequestMapping端点的问题

问题原因

你之前的代码没生效,核心原因是Spring Boot默认已经注册了RequestMappingHandlerMapping,你用@Component注册的自定义实现不会替换掉默认实例,请求依然会走默认的HandlerMapping,所以你的路径修改逻辑不会被触发。

解决步骤

1. 确保自定义@Version注解的定义正确

支持类和方法级别标注,灵活控制版本路径:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Version {
    int value();
}

2. 调整自定义RequestMappingHandlerMapping实现

去掉@Component注解,专注实现路径修改逻辑,优先读取方法上的@Version,再读取类上的:

public class VersionedRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        RequestMappingInfo methodMapping = super.getMappingForMethod(method, handlerType);
        if (methodMapping == null) {
            return null;
        }

        // 优先获取方法上的版本注解,没有则取类上的
        Version versionAnnotation = AnnotationUtils.findAnnotation(method, Version.class);
        if (versionAnnotation == null) {
            versionAnnotation = AnnotationUtils.findAnnotation(handlerType, Version.class);
        }

        if (versionAnnotation != null) {
            String versionPath = "/v" + versionAnnotation.value();
            RequestMappingInfo versionMapping = RequestMappingInfo.paths(versionPath).build();
            return versionMapping.combine(methodMapping);
        }

        return methodMapping;
    }
}

3. 通过配置类替换默认的HandlerMapping

实现WebMvcRegistrations接口,注册自定义的HandlerMapping,确保它替换Spring默认的实例:

@Configuration
public class WebVersionConfig implements WebMvcRegistrations {
    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        VersionedRequestMappingHandlerMapping handlerMapping = new VersionedRequestMappingHandlerMapping();
        // 设置与默认HandlerMapping相同的优先级和基础配置,保证原有功能不受影响
        handlerMapping.setOrder(0);
        handlerMapping.setInterceptors(getInterceptors());
        handlerMapping.setContentNegotiationManager(getContentNegotiationManager());
        handlerMapping.setCorsConfigurations(getCorsConfigurations());
        return handlerMapping;
    }

    // 注入默认的拦截器、内容协商管理器、跨域配置,保持原有行为
    @Autowired(required = false)
    private List<HandlerInterceptor> interceptors = Collections.emptyList();

    @Autowired
    private ContentNegotiationManager contentNegotiationManager;

    @Autowired(required = false)
    private Map<String, CorsConfiguration> corsConfigurations = Collections.emptyMap();

    private List<HandlerInterceptor> getInterceptors() {
        return this.interceptors;
    }

    private ContentNegotiationManager getContentNegotiationManager() {
        return this.contentNegotiationManager;
    }

    private Map<String, CorsConfiguration> getCorsConfigurations() {
        return this.corsConfigurations;
    }
}

4. 测试验证

编写测试控制器:

@RestController
@Version(1)
public class TestController {
    @GetMapping("/test")
    public ResponseEntity<String> testV1() {
        return ResponseEntity.ok("Hello from v1/test");
    }

    @Version(2)
    @GetMapping("/test")
    public ResponseEntity<String> testV2() {
        return ResponseEntity.ok("Hello from v2/test");
    }
}

启动项目后,访问/v1/test会返回v1的内容,访问/v2/test会返回v2的内容,符合预期。

内容的提问来源于stack exchange,提问作者AbdulazizYas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 23:02:35