使用spring boot部署时的映射冲突Jersey部署为WAR

时间:2015-04-14 14:26:55

标签: spring-boot war jersey-2.0 tomcat8

我们将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映射到'/*'。

在某些环境中,泽西岛自己的JerseyServletContainerInitializer会在SpringApplication启动后触发,因为现有PmsiResourceConfiguration映射而无法注册jerseyServlet

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

// 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;
}

最后一段代码将失败,因为注册资源配置类没有映射('jerseyServlet'密钥只有一个)。

如果没有报告任何映射冲突,则会失败。 为什么呢?

1 个答案:

答案 0 :(得分:3)

我遇到了类似的问题,我有一个带有Jersey JAX-RS Web服务的Spring Boot应用程序。使用embeddedTomcat时一切正常,但是当我尝试在相同版本的常规Tomcat(Tomcat8)上部署战争时它就变得很糟糕。

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

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

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

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

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