【问题标题】:Mapping conflict when deploying with spring boot Jersey starter deployed as WAR使用部署为 WAR 的 spring boot Jersey starter 部署时的映射冲突
【发布时间】:2015-06-20 05:16:07
【问题描述】:

我们将 Spring Boot 与 Jersey Starter 一起使用,并将其部署为 WAR,以编程方式部署到另一个应用程序的嵌入式 Tomcat。

我们的应用启动后,在某些环境中,会发生映射冲突,记录如下:

o.g.j.s.i.JerseyServletContainerInitializer : Mapping conflict. A Servlet registration exists with same mapping as the Jersey servlet application, named com.vidal.pmsi.config.PmsiResourceConfiguration, at the servlet mapping, /*.

资源配置如下:

@ApplicationPath("/")
@ExposedApplication
@Component
public class PmsiResourceConfiguration extends ResourceConfig {

   public PmsiResourceConfiguration() {
      packages("com.vidal.pmsi.api");
      packages("com.vidal.pmsi.config");
      property(ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK, true);
      property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
   }
}

据我了解,Spring Boot Jersey Starter 将注册一个名为“jerseyServlet”的 servlet 映射到“/*”。

在某些环境中,Jersey自己的JerseyServletContainerInitializer会在SpringApplication启动后触发,因为已有jerseyServlet映射,导致注册PmsiResourceConfiguration失败。

这是一个问题,因为我们自己的开源库会尝试(并崩溃)在启动时获取上下文路径:

// compile-time generated Linkers.java
@WebListener
@Generated("fr.vidal.oss.jax_rs_linker.LinkerAnnotationProcessor")
public final class Linkers implements ServletContextListener {
    private static String contextPath = "";
    private static String applicationName = ApplicationName.get();

    @Override
    public void contextInitialized(ServletContextEvent sce) {
         //applicationName = FQCN of PmsiResourceConfiguration
        contextPath = ContextPaths.contextPath(sce.getServletContext(), applicationName);
    }

    // [...]
}
// ContextPaths.java
public static String contextPath(ServletContext servletContext, String registeredKey) {
    // registeredKey is therefore the FQCN of PmsiResourceConfiguration
    String mappedPath = stripWildcard(servletContext.getServletRegistration(registeredKey).getMappings().iterator().next());
    return servletContext.getContextPath() + mappedPath;
}

最后的 sn-p 代码将失败,因为没有映射到已注册的资源配置类('jerseyServlet' 键只有一个)。

当没有报告任何映射冲突时,这不会失败。 为什么?

【问题讨论】:

    标签: spring-boot war jersey-2.0 tomcat8


    【解决方案1】:

    我遇到了一个类似的问题,我有一个带有 Jersey JAX-RS Webservice 的 Spring Boot 应用程序。使用 EmbeddedTomcat 时一切正常,但当我尝试在相同版本的常规 Tomcat (Tomcat8) 上部署战争时,它就崩溃了。

    问题是默认情况下,embeddedTomcat 不会扫描 jar 文件中的 ServletContainerInitializer,但常规的会扫描,这与 Spring 设置的 ServletContainer/Config 冲突。

    除了排除包含JerseyServletContainerInitializer 的 jar 之外,我还找到了一个选项来告诉 tomcat 过滤掉这个特定的 ServletContainerInitializer (SCI)。在上下文中设置containerSciFilter 属性有助于:

    <Context containerSciFilter="JerseyServletContainerInitializer">
    ...
    </Context>
    

    我没有在 META-INF/services 中定义任何 SCI,但包含 JerseySCI 的 jar 已经定义了它,并且它位于 Tomcat 可以找到的正确路径上。


    考虑到这是最接近的 matchinb 问题并且没有答案,我不会重新发布我的问题并尝试回答这个问题,因为我相信原因是相同的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-10
      • 2018-12-05
      • 1970-01-01
      • 2014-10-18
      • 2016-08-11
      • 2020-06-17
      • 2018-05-18
      相关资源
      最近更新 更多