spring boot—为什么在作为jar运行时获取java.lang.classnotfoundexception,但是可以很好地与intellij idea配合使用

deyfvvtc  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(326)

spring boot版本:2.4.1
Spring Cloud版本:2020.0.0
我的代码

@Configuration
public class BaseConfig {

    @Bean
    public Module sortJacksonModule() {
        return new SortJacksonModule();
    }
}

我的pom.xml依赖关系

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-openfeign-core</artifactId>
</dependency>

我的pom.xml插件

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

使用intellij idea运行时,效果很好。
但是当用jar运行时 mvn clean package ),它显示

Caused by: java.lang.NoClassDefFoundError: feign/codec/EncodeException
        at org.springframework.cloud.openfeign.support.SortJacksonModule.setupModule(SortJacksonModule.java:47) ~[spring-cloud-openfeign-core-3.0.0.jar!/:3.0.0]
        at com.fasterxml.jackson.databind.ObjectMapper.registerModule(ObjectMapper.java:819) ~[jackson-databind-2.11.3.jar!/:2.11.3]
        at com.fasterxml.jackson.databind.ObjectMapper.registerModules(ObjectMapper.java:1021) ~[jackson-databind-2.11.3.jar!/:2.11.3]
        at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.configure(Jackson2ObjectMapperBuilder.java:712) ~[spring-web-5.3.2.jar!/:5.3.2]
        at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.build(Jackson2ObjectMapperBuilder.java:680) ~[spring-web-5.3.2.jar!/:5.3.2]
        at org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration.jacksonObjectMapper(JacksonAutoConfiguration.java:101) ~[spring-boot-autoconfigure-2.4.1.jar!/:2.4.1]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_232]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_232]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_232]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_232]
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.2.jar!/:5.3.2]
        ... 113 common frames omitted
Caused by: java.lang.ClassNotFoundException: feign.codec.EncodeException
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_232]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[na:1.8.0_232]
        at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151) ~[demo-spring-core-11-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[na:1.8.0_232]
        ... 124 common frames omitted

在研究了错误日志之后,我发现 feign.codec.EncodeException 中的可选依赖项 spring-cloud-openfeign-core ,所以classnotfoundexception是正确的行为(可选的依赖项不包括在最终的jar中)。
所以我的问题是:为什么intellij idea可以毫无差错地运行?我尝试了intellij idea run和mvn spring-boot:run,都很好。
更新:添加示例
经过更多的研究,我发现这种情况只发生在上课不打电话的时候。

try {
            System.out.println("not important code");
        } catch (Exception e) {
            throw new EncodeException("not exist class");
        }

在本例中,try-catch从不抛出异常。以及 EncodeException 类位于可选依赖项中。此代码在intellij idea中运行良好,但在作为 java -jar .jar ===========使用最少的演示再次更新
我创建了一个最小的演示来重现这个问题。
一个独立的演示模块

<dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-core</artifactId>
            <version>10.10.1</version>
            <optional>true</optional>
        </dependency>
import feign.codec.EncodeException;

/**
 * Hello world!
 */
public class App {

    public void testOptional() {
        try {
            System.out.println("test");
        } catch (Exception e) {
            throw new EncodeException("never throw this");
        }
    }
}

演示spring项目(由 spring initializr 并添加依赖项)

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>demo-module</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
@Component
public class MyMain implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        new App().testOptional();
    }
}
ego6inou

ego6inou1#

在idea(ctrl-alt-shift-s)中检查您的项目类路径——我敢说可选的jar在module compile类路径中的某个地方,它足以在ide中运行您的类——但不能在独立的jar中运行。可选意味着在maven上下文中,它在编译时出现在类路径上,但不打包到结果工件中。

rm5edbpk

rm5edbpk2#

有一个选项叫做 Enable launch optimization 在intellij idea run config中,取消选中它,一切都按预期工作。

相关问题