【问题标题】:How to add "api" prefix to all controllers under com.myproject.api?如何为 com.myproject.api 下的所有控制器添加“api”前缀?
【发布时间】:2017-08-01 15:46:32
【问题描述】:

我试图找到它,但我发现了许多不同的场景,但没有这个。

我想要做的是在 com.myproject.api 下的控制器中的所有路由中添加“/api/”前缀。 我希望 com.myapp.api 包下的所有控制器都使用“/api/*”,并且 com.myapp.web 下的所有控制器都没有前缀

Spring / Spring Boot 可以吗?

【问题讨论】:

  • 这不一样。

标签: java spring spring-mvc spring-boot spring-webflow


【解决方案1】:

已回复herehere

在 src/main/resources 下添加application.properties 文件,选项如下:

server.contextPath=/api

查看common properties的官方参考。

【讨论】:

  • 我不想为所有人添加 Base url。我正在使用模板和要添加前缀的 api 构建前端应用程序
  • 您希望 com.myproject.api/** 用于 HTML 视图,而 com.myproject.api/api/** 用于您的其他控制器(例如 REST 控制器)?
  • 没有。我希望 com.myapp.api 包下的所有控制器都使用“/api/*”,并且 com.myapp.web 下的所有控制器都没有前缀
【解决方案2】:

您应该将@RequestMapping("/api") 添加到每个所需的@Controller@RestController 类的顶部。

当类和方法都具有该注解时,Spring Boot 在构建 url 时附加它们。在下面的示例中,该方法将绑定到/api/user 路由。

@RequestMapping("/api")
@RestController
public class MyController {

  @RequestMapping("/user")
  public List<User> getUsers(){
     return ...
  }

}

【讨论】:

  • '每个所需的 Controller 或 RestController 类的顶部。' - 所以以某种方式配置Spring来做到这一点不是不可能的吗?会更容易维护
  • 你说的是包级别的注解但是Spring的@RequestMapping不支持。
  • 不能以某种方式作为 server.contextPath 完成,但仅适用于包?
【解决方案3】:

如果你使用的是springboot,可以添加以下内容:

server.servlet.context-path=/api

到 application.properties 文件。

【讨论】:

  • 这不是被问到的。问题是给定包中的处理程序,这样 /login 之类的东西不会移动到 /api 子路径中
【解决方案4】:

只要您使用MVC,我就可以通过以下方式实现我认为您正在寻找的结果。

先做一个实现WebMvcRegistrations的配置类

@Configuration
public class WebMvcConfig implements WebMvcRegistrations {

    @Value("${Prop.Value.String}") //"api"
    private String apiPrefix;

    @Value("${Prop.Package.Names}") //["com.myapp.api","Others if you like"]
    private String[] prefixedPackages;

    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        return new PrefixedApiRequestHandler(apiPrefix,prefixedPackages);
    }
}

然后创建一个扩展RequestMappingHandlerMapping的类 并覆盖getMappingForMethod

@Log4j2
public class PrefixedApiRequestHandler extends RequestMappingHandlerMapping {

    private final String prefix;

    private final String[] prefixedPackages;

    public PrefixedApiRequestHandler(final String prefix, final String... packages) {
        super();
        this.prefix = prefix;
        this.prefixedPackages = packages.clone();

    }

    @Override
    protected RequestMappingInfo getMappingForMethod(final Method method, final Class<?> handlerType) {

        RequestMappingInfo info = super.getMappingForMethod(method, handlerType);
        if (info == null) {
            return null;
        }

        for (final String packageRef : prefixedPackages) {
            if (handlerType.getPackageName().contains(packageRef)) {
                info = createPrefixedApi().combine(info);

                log.trace("Updated Prefixed Mapping " + info);
                return info;
            }
        }
        log.trace("Skipped Non-Prefixed Mapping " + info);
        return info;
    }

    private RequestMappingInfo createPrefixedApi() {
        String[] patterns = new String[prefix.length()];
        for (int i = 0; i < patterns.length; i++) {
            // Build the URL prefix
            patterns[i] = prefix;
        }

        return new RequestMappingInfo(
                new PatternsRequestCondition(patterns,
                        getUrlPathHelper(),
                        getPathMatcher(),
                        useSuffixPatternMatch(),
                        useTrailingSlashMatch(),
                        getFileExtensions()),
                new RequestMethodsRequestCondition(),
                new ParamsRequestCondition(),
                new HeadersRequestCondition(),
                new ConsumesRequestCondition(),
                new ProducesRequestCondition(),
                null);
    }
}

然后,您应该会看到 /api/(ControllerMapping) 的所有映射,仅在指定的包中。注意:我的控制器顶部有@RequestMapping("/")

【讨论】:

  • 这里填充的patterns[i]数组有问题。为什么我们要通过复制与 pattern.length 相同的次数来填充它?因此,如果模式是“内部”,我们将拥有 8 个模式副本
  • 注意:这里使用的大多数构造函数/对象在 Spring5 中已被弃用
【解决方案5】:

使用 Spring Boot,这对我有用:

@Configuration
@EnableWebMvc
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("/api",
               HandlerTypePredicate.forBasePackage("com.your.package"));
    }
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-29
  • 1970-01-01
  • 2020-04-26
  • 2011-10-14
相关资源
最近更新 更多