使用 spring 部署时的映射冲突 boot Jersey starter 部署为 WAR
Mapping conflict when deploying with spring boot Jersey starter deployed as WAR
我们正在使用 Spring Boot with its 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
启动后触发,无法注册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;
}
最后一段代码将失败,因为没有映射到已注册的资源配置 class('jerseyServlet'
键只有一个)。
如果没有报告任何映射冲突,这 not 会失败。
为什么?
我 运行 遇到了一个类似的问题,我有一个 Spring 带有 Jersey JAX-RS Web 服务的启动应用程序。使用嵌入式 Tomcat 时一切正常,但当我尝试在同一版本 (Tomcat8) 的常规 Tomcat 上部署 war 时,一切都变得糟糕起来。
问题是默认情况下嵌入式Tomcat不扫描jar文件中的ServletContainerInitializer,而常规的会扫描并且与Spring设置的ServletContainer/Config冲突.
除了排除包含 JerseyServletContainerInitializer
的 jar 之外,我找到了一个选项来告诉 tomcat 过滤掉这个特定的 ServletContainerInitializer (SCI)。在上下文中设置 containerSciFilter 属性有帮助:
<Context containerSciFilter="JerseyServletContainerInitializer">
...
</Context>
我没有在我的 META-INF/services 中定义任何 SCI,但是包含 JerseySCI 的 jar 已经定义了它,并且它在 Tomcat 找到的正确路径上。
考虑到这是最接近的 matchinb 问题并且没有答案,我不会重新发布我的问题并尝试回答这个问题,因为我相信原因是相同的。
我们正在使用 Spring Boot with its 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
启动后触发,无法注册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;
}
最后一段代码将失败,因为没有映射到已注册的资源配置 class('jerseyServlet'
键只有一个)。
如果没有报告任何映射冲突,这 not 会失败。 为什么?
我 运行 遇到了一个类似的问题,我有一个 Spring 带有 Jersey JAX-RS Web 服务的启动应用程序。使用嵌入式 Tomcat 时一切正常,但当我尝试在同一版本 (Tomcat8) 的常规 Tomcat 上部署 war 时,一切都变得糟糕起来。
问题是默认情况下嵌入式Tomcat不扫描jar文件中的ServletContainerInitializer,而常规的会扫描并且与Spring设置的ServletContainer/Config冲突.
除了排除包含 JerseyServletContainerInitializer
的 jar 之外,我找到了一个选项来告诉 tomcat 过滤掉这个特定的 ServletContainerInitializer (SCI)。在上下文中设置 containerSciFilter 属性有帮助:
<Context containerSciFilter="JerseyServletContainerInitializer">
...
</Context>
我没有在我的 META-INF/services 中定义任何 SCI,但是包含 JerseySCI 的 jar 已经定义了它,并且它在 Tomcat 找到的正确路径上。
考虑到这是最接近的 matchinb 问题并且没有答案,我不会重新发布我的问题并尝试回答这个问题,因为我相信原因是相同的。