【发布时间】: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