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

Spring REST通过自定义方法级注解为请求映射添加URL前后缀

实现结论

该需求完全可实现,无需修改原有@GetMapping/@PostMapping/@PutMapping/@DeleteMapping等标准映射注解的路径值,核心是介入Spring MVC请求映射的注册流程,在映射信息最终生效前动态修改匹配路径。

实现思路

核心扩展点是Spring MVC负责扫描、注册控制器请求映射的核心组件RequestMappingHandlerMapping,重写其生成方法级映射信息的钩子方法,识别方法上的自定义注解,动态拼接前缀/后缀路径即可。

步骤1:定义自定义@Read注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Read {
    // 路径拼接模式:PREFIX前缀(类路径后、方法路径前拼接),SUFFIX后缀(方法路径后拼接)
    Mode mode() default Mode.PREFIX;
    // 要拼接的路径段
    String pathSegment() default "/read";

    enum Mode {
        PREFIX, SUFFIX
    }
}

步骤2:自定义请求映射处理器

继承RequestMappingHandlerMapping,重写getMappingForMethod方法,在Spring默认生成的映射信息基础上,根据@Read注解的配置修改路径:

import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.Method;
import java.util.List;

public class CustomPathHandlerMapping extends RequestMappingHandlerMapping {

    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        // 先获取Spring默认生成的方法映射信息
        RequestMappingInfo originalMapping = super.getMappingForMethod(method, handlerType);
        if (originalMapping == null) {
            return null;
        }

        // 查找方法上的@Read注解
        Read readAnn = AnnotatedElementUtils.findMergedAnnotation(method, Read.class);
        if (readAnn == null) {
            return originalMapping;
        }

        RequestMappingInfo.Builder mappingBuilder = originalMapping.mutate();
        String segment = readAnn.pathSegment();

        if (readAnn.mode() == Read.Mode.PREFIX) {
            // 前缀模式:直接追加路径段,Spring会自动按层级拼接,最终效果为 类路径 + /read + 方法路径
            mappingBuilder.paths(segment);
        } else {
            // 后缀模式:遍历原有方法路径,在末尾拼接路径段,提前处理双斜杠问题
            List<String> newPaths = originalMapping.getPatternValues().stream()
                    .map(path -> path.endsWith("/") 
                            ? path + segment.substring(1) 
                            : path + segment)
                    .toList();
            mappingBuilder.paths(newPaths.toArray(new String[0]));
        }

        return mappingBuilder.build();
    }
}

步骤3:注册自定义映射处理器到Spring容器

替换Spring MVC默认的RequestMappingHandlerMapping,让自定义逻辑生效。Spring Boot项目可直接通过实现WebMvcRegistrations接口完成注册:

import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

@Configuration
public class WebConfig implements WebMvcRegistrations {
    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        return new CustomPathHandlerMapping();
    }
}
效果验证

添加以上配置后,你给出的控制器代码无需修改原有@PutMapping的路径值:

  • 当@Read注解mode设为PREFIX时,访问路径为 http://localhost:8080/something/read/some/path/
  • 当@Read注解mode设为SUFFIX时,访问路径为 http://localhost:8080/something/some/path/read/
注意事项
  • 路径拼接逻辑可根据自身需求调整,比如统一处理斜杠、支持占位符解析等。
  • 该实现完全兼容Spring MVC原有映射规则,请求方法校验、参数条件、produces/consumes等配置不会受影响。
  • 如果需要其他类似@Write/@Admin等自定义路径注解,只需在getMappingForMethod方法中增加对应注解的判断逻辑即可,也可以把你之前实现的类级别注解路径拼接逻辑合并到该类中统一维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:12:22