网上的文章五花八门,不写SpringBoot的版本号,导致代码拿来主义不好使了。
本文采用的版本
SpringBoot 2.7.7Java 1.8
目录
- 1、默认访问路径
- 2、整个项目增加路由前缀
- 3、通过注解方式增加路由前缀
- 4、按照目录结构/包名添加前缀
- 总结
- 参考文章
1、默认访问路径
package com.example.demo.controller.api;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/api")public class AppIndexController {@GetMapping("/index")public String index() {return "app";}}
访问地址:http://localhost:8080/api/index
2、整个项目增加路由前缀
application.yml
server:servlet:context-path: /prefix
访问地址:http://localhost:8080/prefix/api/index
注意:该方案会将所有的路由都增加一个前缀
3、通过注解方式增加路由前缀
注解
package com.example.demo.annotation;import org.springframework.core.annotation.AliasFor;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RestController;import java.lang.annotation.*;/** * controller层统一使用该注解 */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@RestControllerpublic @interface ApiRestController {/** * Alias for {@link Controller#value}. */@AliasFor(annotation = Controller.class)String value() default "";}
配置
package com.example.demo.config;import com.example.demo.annotation.ApiRestController;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/** * 配置统一的后台接口访问路径的前缀 */@Configurationpublic class CustomWebMvcConfig implements WebMvcConfigurer {@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {configurer.addPathPrefix("/api", c -> c.isAnnotationPresent(ApiRestController.class));}}
使用注解
package com.example.demo.controller.api;import com.example.demo.annotation.ApiRestController;import org.springframework.web.bind.annotation.GetMapping;@ApiRestController// @RestController// @RequestMapping("/api")public class AppIndexController {@GetMapping("/index")public String index() {return "app";}}
访问地址:http://localhost:8080/api/index
4、按照目录结构/包名添加前缀
没有成功,可能是版本的问题
按照网上的实现方式
// 核心代码RequestMappingInfo.paths(prefix).build().combine(mappingInfo);
会报错
Neither PathPatterns nor String patterns condition
2023年6月9日补充
感谢评论区的大佬 @孤独和弦 帮助,补充第四种方式
思路:
将原有路由的所有路径取出,手动拼接前缀,再和原有路由配置合并
项目结构
$ tree -I target -I test.├── pom.xml└── src└── main├── java│ └── com│ └── example│ └── demo│ ├── Application.java│ ├── config│ │ ├── AutoPrefixConfiguration.java│ │ └── AutoPrefixUrlMapping.java│ └── controller│ └── v1│ └── IndexController.java└── resources├── application.yml├── static└── templates
配置 application.yml
# 需要添加路径前缀的包名api-package: com.example.demo.controller
AutoPrefixUrlMapping.java
package com.example.demo.config;import org.springframework.beans.factory.annotation.Value;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.Objects;/** * 自动补全路由前缀处理类 */public class AutoPrefixUrlMapping extends RequestMappingHandlerMapping {/** * 读取基础包配置 */@Value("${api-package}")private String bathApiPackagePath;/** * 重写方法路由获取 * * @param method * @param handlerType * @return */@Overrideprotected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {RequestMappingInfo mappingInfo = super.getMappingForMethod(method, handlerType);if (Objects.nonNull(mappingInfo)) {String prefix = this.getPrefix(handlerType);if (prefix != null) {String[] paths = mappingInfo.getPatternValues().stream().map(path -> prefix + path).toArray(String[]::new);return mappingInfo.mutate().paths(paths).build();}}return mappingInfo;}/** * 获取方法路由前缀 * * @param handleType * @return */private String getPrefix(Class<?> handleType) {String packageName = handleType.getPackage().getName();// 如果包含指定的包则返回前缀if (packageName.startsWith(this.bathApiPackagePath)) {return packageName.substring(this.bathApiPackagePath.length()).replace(".", "/");} else {return null;}}}
AutoPrefixConfiguration.java
package com.example.demo.config;import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;import org.springframework.stereotype.Component;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;/** * 自动补全路由前缀配置类 */@Componentpublic class AutoPrefixConfiguration implements WebMvcRegistrations {@Overridepublic RequestMappingHandlerMapping getRequestMappingHandlerMapping() {return new AutoPrefixUrlMapping();}}
控制器
package com.example.demo.controller.v1;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/api")public class IndexController {@GetMapping("/index")public String index() {return "Hello";}}
访问路径:http://localhost:8080/v1/api/index
总结
方 式 | 适用范围 |
---|---|
RequestMapping/PostMapping/GetMapping | 单个方法 或 单个类(多个方法) |
自定义注解 | 多个控制器(可以不同目录) |
目录 / 包名 前缀 | 多个控制器(同目录) |
配置 context-path | 全局前缀 |
包名前缀只能是符合java包名规范的才可以,比如中划线就不行,需要修改代码自定义做映射
参考文章
- SpringBoot2.x 给Controller的RequestMapping添加统一前缀
- SpringBoot – 根据目录结构自动生成路由前缀