如何设置 Spring 以便我可以省略 applicationContext.xml

How to set up Spring so that I can omit applicationContext.xml

我有一个使用 spring 设置上下文的 JAX 应用程序。

我已经设置了一个 AppConfig 来处理这个...就像这样。

@Configuration
@ComponentScan("com.whatever")
public class AppConfig {... //etc

但是,我不断收到错误消息,因为应用程序正在寻找 applicationContext.xml

org.springframework.beans.factory.BeanDefinitionStoreException: 
IOException parsing XML document from class path resource [applicationContext.xml];

我想我必须对我的 web.xml 文件做点什么...但我不太明白。这是我的 web.xml

<web-app version="3.1" xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd">

<listener>
    <listener-class>com.whatever.etc.ApplicationListener</listener-class>
</listener>

<!-- Application -->
<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>
            io.swagger.jaxrs.listing,
            com.shutterstock.media.api
        </param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.provider.scanning.recursive</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.whatever.etc.MainClass</param-value>
    </init-param>
    <init-param>
        <param-name>dirAllowed</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <!-- used to overwrite default 4xx state pages -->
        <param-name>jersey.config.server.response.setStatusOverSendError</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>

<servlet-mapping>
    <servlet-name>Jersey Web Application</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

<!-- Swagger -->
<servlet>
    <servlet-name>Jersey Swagger</servlet-name>
    <servlet-class>io.swagger.jersey.config.JerseyJaxrsConfig</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>

</web-app>

我能给你的最好建议是将你的项目完全转换为 spring 引导,以便利用它提供的所有强大功能。

您应该从项目中完全删除所有 XML 并执行以下步骤:

TL;DR

启动 spring 的一种简单方法是使用 spring initializr (Spring initializr) 并开始将您的代码迁移到新项目。

在现有项目中迁移到 spring 启动的开始步骤说明:

Maven 依赖项

添加以下依赖项并删除所有其他相关的 spring 依赖项。一般来说,如果您需要任何其他依赖项,请先尝试检查是否有 spring 启动程序。 (还要确保你的包装是jar。如果你想要war,你应该遵循这个link:convert to war

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
    <!-- Spring Boot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jersey</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <!-- Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Spring 引导应用程序

在您的基础包中创建一个带有 @SpringBootApplication 注释的 class,如下所示。从现在开始,仅在该包的子包中创建 classes,以便 spring 可以自动捕获所有组件:

@SpringBootApplication
public class FooApplication {

    public static void main(String[] args) {
        SpringApplication.run(FooApplication .class, args);
    }

}

Java 配置

现在您可以轻松地添加一个名为 config 的包,例如在您的基础包下,并使用您的自定义配置添加 @Configuration 带注释的 bean。

申请.properites/yml

如果您还没有,请将 application.properties/yml 添加到 src/main.resources,至少要进行以下配置(可以在此处找到更多属性:spring boot common properties

  • 通过添加映射球衣 servlet 端点:spring.jersey.application-path=/

球衣配置

您需要在扩展 ResourceConfig:

的自定义 java 配置 class 中注册球衣供应商
@Configuration
public class JerseyConfiguration extends ResourceConfig {

    public JerseyConfiguration() {
        register(FooController.class);
        register(OtherController.class);
        ...
    }

}

重要提示

完成此转换后,您不再需要 web.xml,因为 spring 引导会为您创建 servlet。您应该从项目中删除除 pom.xml 之外的所有 XML,并将所有内容转换为 java。它可以与使用 @ImportResource 的 XML 配置共存,但不推荐这样做。

为了 运行 您的项目现在使用 maven 使用 maven build 和命令:spring-boot:run.

如果系统提供任何静态文件,请将它们从 src/main/webapp 移至 src/main/resources/static(更多信息请点击此处:Static Content

所有这些应该让您开始使用 spring 引导,并允许您删除 applicationContext.xml,同时保持 spring 引导的最佳实践。你可以用更简单的方式来做,但我认为从长远来看它会更好地为你服务 运行.

您收到错误是因为 Jersey 与 Spring 集成的默认方式是查找此 applicationContext.xml 文件。如果您想减少 xml,您需要使用 WebApplicationInitializer

以编程方式配置 Spring
@Order(1)
public class SpringWebContainerInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        registerContextLoaderListener(servletContext);

        // Set the Jersey used property so it won't load a ContextLoaderListener
        // see bug report https://java.net/jira/browse/JERSEY-2038
        servletContext.setInitParameter("contextConfigLocation", "");
    }

    private void registerContextLoaderListener(ServletContext servletContext) {
        WebApplicationContext webContext;
        webContext = createWebAplicationContext(SpringAnnotationConfig.class);
        servletContext.addListener(new ContextLoaderListener(webContext));
    }

    public WebApplicationContext createWebAplicationContext(Class... configClasses) {
        AnnotationConfigWebApplicationContext context;
        context = new AnnotationConfigWebApplicationContext();
        context.register(configClasses);
        return context;
    }
}

在这个例子中,你看到的地方

createWebAplicationContext(SpringAnnotationConfig.class)

只需在那里使用您的 AppConfig

我们在这里做的是自己加载 Spring 上下文,当 Jersey 寻找它时,它会找到它,而不是尝试加载上下文本身(否则它会尝试找到applicationContext.xml 文件)。

另请参阅: