如何为所有控制器配置默认@RestController URI 前缀?

2022-09-02 05:17:15

我知道您可以设置以更改根上下文。server.contextPathapplication.properties

另外,我可以在Spring Boot的应用程序配置中添加一个额外的上下文,如下面的示例(在Groovy中)一样,将“/api”添加到根上下文的URL映射中:

@Bean
ServletRegistrationBean dispatcherServlet() {
     ServletRegistrationBean reg = new ServletRegistrationBean(new DispatcherServlet(), "/")
        reg.name = "dispatcherServlet"
        reg.addInitParameter("contextConfigLocation", "")
        reg.addUrlMappings("/api/*")
        reg.loadOnStartup = 2
        reg
    }
}

我正在尝试有一个单独的基本URI“/api”专门用于Web服务调用,我可以利用它来确保安全等。但是,使用上述方法将意味着我的任何URI(无论是否为Web服务)都可以使用“/”或“/api”进行访问,并且不提供具体的隔离。

有没有人知道一种更好的方法,可以使用配置为所有(s)设置基本路径,而不必正式地在每个控制器前面加上/api/前缀?如果我被迫手动为每个控制器添加URI前缀,则可能会错误地省略它并绕过特定于Web服务的安全措施。@RestController

以下是Stack Overflow中对相同类型问题的参考,该问题从未得到完全回答:

Spring Boot:为 RestControllers 配置 url 前缀


答案 1

在当前接受的解决方案的延续下,github问题也解决了同样的问题。

Spring 5.1及更高版本,您可以实现和覆盖如下方法WebMvcConfigurerconfigurePathMatch

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("/api",
                    HandlerTypePredicate.forAnnotation(RestController.class));
    }

}

现在,所有 将作为前缀路径与配置的路径一起。@RestControllers/api

官方文档


答案 2

自Spring Boot 1.4.0.RC1以来,有一个新的解决方案可以解决此类问题(有关详细信息,请参阅 https://github.com/spring-projects/spring-boot/issues/5004)

Shahin ASkari的解决方案禁用了Auto配置的某些部分,因此可能会导致其他问题。

以下解决方案采用了他的想法,并将其正确集成到弹簧靴中。对于我的情况,我希望所有RestControllers都使用基本路径api,但仍然使用根路径提供静态内容(例如,有角度的webapp)

编辑:我在一篇博客文章中总结了它,并带有略微改进的版本,请参阅 https://mhdevelopment.wordpress.com/2016/10/03/spring-restcontroller-specific-basepath/

@Configuration
public class WebConfig {

    @Bean
    public WebMvcRegistrationsAdapter webMvcRegistrationsHandlerMapping() {
        return new WebMvcRegistrationsAdapter() {
            @Override
            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
                return new RequestMappingHandlerMapping() {
                    private final static String API_BASE_PATH = "api";

                    @Override
                    protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
                        Class<?> beanType = method.getDeclaringClass();
                        RestController restApiController = beanType.getAnnotation(RestController.class);
                        if (restApiController != null) {
                            PatternsRequestCondition apiPattern = new PatternsRequestCondition(API_BASE_PATH)
                                    .combine(mapping.getPatternsCondition());

                            mapping = new RequestMappingInfo(mapping.getName(), apiPattern,
                                    mapping.getMethodsCondition(), mapping.getParamsCondition(),
                                    mapping.getHeadersCondition(), mapping.getConsumesCondition(),
                                    mapping.getProducesCondition(), mapping.getCustomCondition());
                        }

                        super.registerHandlerMethod(handler, method, mapping);
                    }
                };
            }
        };
    }

}

推荐