一旦我释放 jar 并尝试在 Idea 之外运行它,就会出现错误:
Exception in thread "main" org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/context]
Offending resource: class path resource [spring/spring-app.xml]
这是开始类:package ru.start;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@Configuration
public class Start {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/spring-app.xml");
// ((ClassPathXmlApplicationContext) (ctx)).close();
}
}
这是spring-app.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd">
<bean id="logger" scope="prototype" class="org.slf4j.LoggerFactory" factory-method="getLogger">
<constructor-arg name="name" value="log" />
</bean>
<context:component-scan base-package="ru.iiko"/>
<task:annotation-driven executor="executor" scheduler="scheduler"/>
<task:executor id="executor" pool-size="5"/>
<task:scheduler id="scheduler" pool-size="10"/>
</beans>
也许我没有在 pom.xml 中提取一些东西?这是我对 spring 的依赖项:
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>${spring.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
帮助我理解为什么...
在我看来,问题在于 Maven 项目的构建算法。
构建时,Maven 提取所有依赖项的内容并将它们与您的类混合放在根目录中。
同样的命运等待着所有资源,包括那些位于 META-INF 目录中的资源。
这就是问题所在。
因为 Maven 不会“合并”文件的内容,而是简单地覆盖它们,结果可能会丢失任何数据。
在您的情况下, META-INF 目录中的三个 spring 依赖项包含同名的设置文件。
但是根据 maven 算法,只有一个版本进入最终的 jar,因为 在提取每个后续依赖项时,具有相同名称的文件会被简单地覆盖。
战斗已经完成了一半——问题的根源找到了。
仍然需要找到解决方案。
在 SO 的英文版上,在类似的情况下,他们建议使用onejar-maven-plugin,这有助于正确打包所有依赖项而不会发生这种冲突。
反过来,我一直使用原始的Spring Boot Maven 插件并且不知道悲伤。
将spring-boot-maven-plugin 插件
build.plugins
添加到pom.xml部分并用maven重建项目。
这种情况下的 Spring Boot 会小心地将所有依赖项以 jar 文件的形式放在 lib 文件夹中,这将有助于避免冲突和覆盖设置文件。
结果,我们有DO
和之后
(没有错误,spring中的任务正在运行)
附加链接:
https ://docs.spring.io/spring-boot/docs/current/reference/html/build-tool-plugins-maven-plugin.html
https://code.google.com/archive/p/ onejar-maven-plugin/
https://stackoverflow.com/questions/11160534/how-to-create-spring-based-executable-jar-with-maven