如何设置 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 文件)。
另请参阅:
我有一个使用 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
:
@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
@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 文件)。
另请参阅: