嵌入式Tomcat的Spring WebApplicationInitializer(ServletContainerInitializer,@ HandlesTypes)

时间:2016-05-06 11:58:32

标签: spring maven tomcat8 servlet-3.0 spring-web

我无法理解为什么在以下的最小项目中,我在Eclipse和IntelliJ中运行测试时发现了Spring WebApplicationInitializer接口的实现,而在使用Maven(mvn clean test)时则没有。

使用Eclipse和IntellIJ,我看到INFO: Spring WebApplicationInitializers detected on classpath: [com.example.pack.DummyInitializer@26d678a4]

mvn clean test我看到INFO: No Spring WebApplicationInitializer types detected on classpath

在测试中我启动了嵌入式Tomcat:

String pathToWebXML = new File("src/main/webapp/").getAbsolutePath();
tomcat = new Tomcat();
tomcat.setBaseDir("embedded_tomcat");
tomcat.setPort(0);
tomcat.addWebapp("", pathToWebXML);
tomcat.start();

web.xml引用了一个ServletContextListener实现,它创建了一个新的(和空的)AnnotationConfigWebApplicationContext

我将示例项目上传到GitHub:https://github.com/C-Otto/webapplicationinitializer

2 个答案:

答案 0 :(得分:0)

如评论中所示,Tomcat不会扫描默认设置中Maven Surefire(和Maven Failsafe)使用的类路径。大多数类都是使用JAR文件中的MANIFEST.MF文件引用的。

一个选项是禁用Maven插件的useSystemClassLoader设置。但是,这会更改类加载器的详细信息,这可能会导致其他问题。

作为另一种选择,可以禁用useManifestOnlyJar,这可能会导致Windows机器出现问题。

在我们的项目中,我们决定删除初始化程序类,而是注册它们应该手动完成的任何操作。在一个具体的例子中,由于找不到AbstractSecurityWebApplicationInitializer的实现,我们现在在contextInitialized方法中手动注册安全过滤器:

String filterName = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
servletContext.addFilter(filterName, new DelegatingFilterProxy(filterName)).addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");

答案 1 :(得分:0)

您可以告诉Tomcat包含通过surefire创建的jar中的清单文件引用的jar。这可以在context.xml中将Jar Scanner属性scanManifest设置为true来完成。这是Tomcat较新版本中的默认值,如下所述:https://bz.apache.org/bugzilla/show_bug.cgi?id=59961