war 打包出错(tomcat外置)

Blade 未结 3 1987
riversky2021
riversky2021 剑圣 2021-11-17 18:10

一、该问题的重现步骤是什么?

  1. maven 依赖


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>

2. 打包类型

<packaging>war</packaging>

3. 入口类修改

Application SpringBootServletInitializer{

   SpringApplicationBuilder (SpringApplicationBuilder builder) {
      BladeApplication.(CommonConstant.Application.).sources(Application.)}

   (String[] args) {
      BladeApplication.(CommonConstant.Application.args)}

}


二、你期待的结果是什么?实际看到的又是什么?

打包成功后的war包,放到tomcat中可以运行。

实际看到

IDEA里可以正常运行,也可以打war包,就是放入tomcat时无法使用

三、你正在使用的是什么产品,什么版本?在什么操作系统上?

spring-boot版本  win10系统   idea  jdk8  tomcat8.5

四、请提供详细的错误堆栈信息,这很重要。

021-11-17 17:49:59.927  WARN 8652 --- [ost-startStop-1] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is java.lang.NoSuchMethodError: org.apache.tomcat.util.modeler.Registry.disableRegistry()V

2021-11-17 17:49:59.936  INFO 8652 --- [ost-startStop-1] ConditionEvaluationReportLoggingListener :


Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.

2021-11-17 17:49:59.977 ERROR 8652 --- [ost-startStop-1] o.s.b.d.LoggingFailureAnalysisReporter   :


***************************

APPLICATION FAILED TO START

***************************


Description:


An attempt was made to call a method that does not exist. The attempt was made from the following location:


    org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:177)


The following method did not exist:


    org.apache.tomcat.util.modeler.Registry.disableRegistry()V


The method's class, org.apache.tomcat.util.modeler.Registry, is available from the following locations:


    jar:file:/D:/devsoft/java/tomcat/apache-tomcat-8.5.72/lib/tomcat-coyote.jar!/org/apache/tomcat/util/modeler/Registry.class


The class hierarchy was loaded from the following locations:


    org.apache.tomcat.util.modeler.Registry: file:/D:/devsoft/java/tomcat/apache-tomcat-8.5.72/lib/tomcat-coyote.jar



Action:


Correct the classpath of your application so that it contains a single, compatible version of org.apache.tomcat.util.modeler.Registry


17-Nov-2021 17:49:59.978 涓ラ噸 [localhost-startStop-1] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start:

        org.apache.catalina.LifecycleException: 鏃犳硶鍚姩缁勪欢[StandardEngine[Catalina].StandardHost[localhost].StandardContext[/blade-api]]

                at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)

                at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)

                at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:753)

                at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:727)

                at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695)

                at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1016)

                at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1903)

                at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

                at java.util.concurrent.FutureTask.run(FutureTask.java:266)

                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

                at java.lang.Thread.run(Thread.java:748)

        Caused by: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is java.lang.NoSuchMethodError: org.apache.tomcat.util.modeler.Registry.disableRegistry()V

                at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:161)

                at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)

                at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)

                at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:755)

                at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)

                at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:402)

                at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)

                at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:173)

                at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:153)

                at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:95)

                at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:172)

                at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5221)

                at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)

                ... 10 more

        Caused by: java.lang.NoSuchMethodError: org.apache.tomcat.util.modeler.Registry.disableRegistry()V

                at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:177)

                at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:178)

                at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:158)

                ... 22 more

17-Nov-2021 17:49:59.980 涓ラ噸 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR 閮ㄧ讲 Web 搴旂敤绋嬪簭 archive [D:\devsoft\java\tomcat\apache-tomcat-8.5.72\webapps\blade-api.war] 鏃跺嚭閿?

        java.lang.IllegalStateException: 鍚姩瀛愮骇鏃跺嚭閿?

                at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:757)

                at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:727)

                at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695)

                at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1016)

                at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1903)

                at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

                at java.util.concurrent.FutureTask.run(FutureTask.java:266)

                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

                at java.lang.Thread.run(Thread.java:748)

        Caused by: org.apache.catalina.LifecycleException: 鏃犳硶鍚姩缁勪欢[StandardEngine[Catalina].StandardHost[localhost].StandardContext[/blade-api]]

                at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)

                at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)

                at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:753)

                ... 9 more

        Caused by: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is java.lang.NoSuchMethodError: org.apache.tomcat.util.modeler.Registry.disableRegistry()V

                at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:161)

                at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)

                at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143)

                at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:755)

                at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)

                at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:402)

                at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)

                at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:173)

                at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:153)

                at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:95)

                at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:172)

                at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5221)

                at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)

                ... 10 more

        Caused by: java.lang.NoSuchMethodError: org.apache.tomcat.util.modeler.Registry.disableRegistry()V

                at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:177)

                at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:178)

                at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:158)

                ... 22 more

五、若有更多详细信息,请在下面提供。


希望作者能能重视下这个问题实践下。论坛上的几个方法都试了。在群里也没有回复。

image.png

3条回答
  • 2021-11-22 23:20

    按照如下步骤尝试,如果还不行,麻烦发一个邮件到bladejava@qq.com附上帖子地址并说明使用的bladex版本

     1. 添加tomcat依赖

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <scope>provided</scope>
    </dependency>


     2. blade-core-boot排除undertow依赖

    <dependency>
                <groupId>org.springblade</groupId>
                <artifactId>blade-core-boot</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.springblade</groupId>
                        <artifactId>blade-core-cloud</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-undertow</artifactId>
                    </exclusion>
                </exclusions>
    </dependency>

      

    3.pom文件修改打包类型为war

    <groupId>org.springblade</groupId>
    <artifactId>BladeX-Boot</artifactId>
    <packaging>war</packaging>
    <version>2.8.2.RELEASE</version>


    4.添加war包插件

    <plugin>
                   <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <configuration>
                        <!--如果想在没有web.xml文件的情况下构建WAR,请设置为false。-->
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                    </configuration>
    </plugin>

    5.application.yaml添加修改

    #服务器配置

    server:
      port: 80
    spring:
      application:
        name: blade-api
      profiles:
        active: dev
      main:
        allow-bean-definition-overriding: true

      

      6.Application类修改,最重要的一步

    image.png


      7.打包

     mvn package -Dmaven.test.skip=true


    ======补充说明=====

    打war包的时候,如果工程依赖的是springboot 2.7.x 则需要做额外的一步操作。针对BladeApplication二次开发一下。

    如果是springboot 3.x则无需修改,主要针对以前的版本需要改动。

    比如创建一个BladeXApplication到业务工程,然后拷贝如下代码,之后把启动类的BladeApplication改成BladeXApplication即可:

    package org.springblade.core.launch;    
    import org.springblade.core.launch.constant.AppConstant;    
    import org.springblade.core.launch.constant.NacosConstant;    
    import org.springblade.core.launch.service.LauncherService;    
    import org.springframework.boot.builder.SpringApplicationBuilder;    
    import org.springframework.context.ConfigurableApplicationContext;    
    import org.springframework.core.env.*;    
    import org.springframework.util.Assert;    
    import org.springframework.util.StringUtils;    
    import java.nio.charset.StandardCharsets;    
    import java.util.*;    
    import java.util.function.Function;    
    import java.util.stream.Collectors;    
    /**    
    * 项目启动器,搞定环境变量问题    
    *    
    * @author Chill    
    */    
    public class BladeXApplication {    
    /**    
    * Create an application context    
    * java -jar app.jar --spring.profiles.active=prod --server.port=2333    
    *    
    * @param appName application name    
    * @param source  The sources    
    * @return an application context created from the current state    
    */    
    public static ConfigurableApplicationContext run(String appName, Class source, String... args) {    
    SpringApplicationBuilder builder = createSpringApplicationBuilder(appName, source, args);    
    return builder.run(args);    
    }    

    public static SpringApplicationBuilder createSpringApplicationBuilder(String appName, Class source, String... args) {
    return createSpringApplicationBuilder(null,appName, source, args);
    }


    public static SpringApplicationBuilder createSpringApplicationBuilder(SpringApplicationBuilder builder, String appName, Class source, String... args) {    
    Assert.hasText(appName, "[appName]服务名不能为空");    
    // 读取环境变量,使用spring boot的规则    
    ConfigurableEnvironment environment = new StandardEnvironment();    
    MutablePropertySources propertySources = environment.getPropertySources();    
    propertySources.addFirst(new SimpleCommandLinePropertySource(args));    
    propertySources.addLast(new MapPropertySource(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, environment.getSystemProperties()));    
    propertySources.addLast(new SystemEnvironmentPropertySource(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, environment.getSystemEnvironment()));    
    // 获取配置的环境变量    
    String[] activeProfiles = environment.getActiveProfiles();    
    // 判断环境:dev、test、prod    
    List<String> profiles = Arrays.asList(activeProfiles);    
    // 预设的环境    
    List<String> presetProfiles = new ArrayList<>(Arrays.asList(AppConstant.DEV_CODE, AppConstant.TEST_CODE, AppConstant.PROD_CODE));    
    // 交集    
    presetProfiles.retainAll(profiles);    
    // 当前使用    
    List<String> activeProfileList = new ArrayList<>(profiles);    
    Function<Object[], String> joinFun = StringUtils::arrayToCommaDelimitedString;    

    if(builder==null){
        // 如果builder为空 创建 此操作将启动内嵌web容器 以jar模式启动
        builder = new SpringApplicationBuilder(source);
    }
       
    String profile;    
    if (activeProfileList.isEmpty()) {    
    // 默认dev开发    
    profile = AppConstant.DEV_CODE;    
    activeProfileList.add(profile);    
    builder.profiles(profile);    
    } else if (activeProfileList.size() == 1) {    
    profile = activeProfileList.get(0);    
    } else {    
    // 同时存在dev、test、prod环境时    
    throw new RuntimeException("同时存在环境变量:[" + StringUtils.arrayToCommaDelimitedString(activeProfiles) + "]");    
    }    
    String startJarPath = BladeApplication.class.getResource("/").getPath().split("!")[0];    
    String activePros = joinFun.apply(activeProfileList.toArray());    
    System.out.printf("----启动中,读取到的环境变量:[%s],jar地址:[%s]----%n", activePros, startJarPath);    
    Properties props = System.getProperties();    
    props.setProperty("spring.application.name", appName);    
    props.setProperty("spring.profiles.active", profile);    
    props.setProperty("info.version", AppConstant.APPLICATION_VERSION);    
    props.setProperty("info.desc", appName);    
    props.setProperty("file.encoding", StandardCharsets.UTF_8.name());    
    props.setProperty("blade.env", profile);    
    props.setProperty("blade.name", appName);    
    props.setProperty("blade.is-local", String.valueOf(isLocalDev()));    
    props.setProperty("blade.dev-mode", profile.equals(AppConstant.PROD_CODE) ? "false" : "true");    
    props.setProperty("blade.service.version", AppConstant.APPLICATION_VERSION);    
    props.setProperty("loadbalancer.client.name", appName);    
    Properties defaultProperties = new Properties();    
    defaultProperties.setProperty("nacos.logging.default.config.enabled", "false");    
    defaultProperties.setProperty("spring.main.allow-bean-definition-overriding", "true");    
    defaultProperties.setProperty("spring.sleuth.sampler.percentage", "1.0");    
    defaultProperties.setProperty("spring.cloud.alibaba.seata.tx-service-group", appName.concat(NacosConstant.NACOS_GROUP_SUFFIX));    
    defaultProperties.setProperty("spring.cloud.nacos.config.file-extension", NacosConstant.NACOS_CONFIG_FORMAT);    
    defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].data-id", NacosConstant.sharedDataId());    
    defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].group", NacosConstant.NACOS_CONFIG_GROUP);    
    defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].refresh", NacosConstant.NACOS_CONFIG_REFRESH);    
    defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].data-id", NacosConstant.sharedDataId(profile));    
    defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].group", NacosConstant.NACOS_CONFIG_GROUP);    
    defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].refresh", NacosConstant.NACOS_CONFIG_REFRESH);    
    builder.properties(defaultProperties);    
    // 加载自定义组件    
    List<LauncherService> launcherList = new ArrayList<>();    
    ServiceLoader.load(LauncherService.class).forEach(launcherList::add);    
    launcherList.stream().sorted(Comparator.comparing(LauncherService::getOrder)).collect(Collectors.toList())    
    .forEach(launcherService -> launcherService.launcher(builder, appName, profile, isLocalDev()));    
    return builder;    
    }    
    /**    
    * 判断是否为本地开发环境    
    *    
    * @return boolean    
    */    
    public static boolean isLocalDev() {    
    String osName = System.getProperty("os.name");    
    return StringUtils.hasText(osName) && !(AppConstant.OS_NAME_LINUX.equalsIgnoreCase(osName));    
    }    
    }    
    @EnableScheduling
    @SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
    public class Application extends SpringBootServletInitializer {
    
       public static void main(String[] args) {
          BladeXApplication.run(CommonConstant.APPLICATION_NAME, Application.class, args);
       }
    
       @Override
       protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
          return BladeXApplication.createSpringApplicationBuilder(application,CommonConstant.APPLICATION_NAME,Application.class).sources(Application.class);
       }
    
    }



    1 讨论(0)
  • 2021-11-23 14:30

    可以了,非常感谢

    0 讨论(0)
  • 2021-12-02 11:21

    按照上面的配置结果,tomcat启动获取nacos数据源配置信息时,获取不到值,你们有这个问题吗

    0 讨论(0)
提交回复