Spring boot WAR, развернутый в Tomcat, игнорируется код после SpringApplication.run () - PullRequest
1 голос
/ 26 апреля 2020

Я занимаюсь разработкой веб-приложения для моей дипломной работы в университете. Я испытываю очень тревожное поведение от Tomcat. Хотя я исправил все проблемы, связанные с выполнением WAR на реальном Tomcat 9.0.34 (последняя версия 9), по сравнению со встроенным Tomcat 9.0.31 из-за зависимости «spring-boot-starter-tomcat», которая возникла до сих пор, эта проблема для меня загадочна. Ни один из кодов (я также пытался System.Out.println(...) или logger.info(...), который находится после строки SpringApplication.run(...), не выполняется при развертывании WAR на сервере Tomcat.

Однако код выполняется при запуске с использованием встроенного контейнера Tomcat (например, через java -jar app.war). В моём помете. xml Параметры maven Tomcat помечается в области «время выполнения», поэтому доступны как реальные, так и встроенные параметры Tomcat для ВОЙНА. Мое приложение запускается через эту главную систему:

@SpringBootApplication
@ComponentScan(basePackages={"com.me.myProject"})
@ServletComponentScan
public class MySpringWebApplication extends SpringBootServletInitializer /* needed for WAR packaging */ { 

...public static void main(String[] args){
    ApplicationContext ctx = SpringApplication.run(MySpringWebApplication.class, args);
    DatabaseSeeder sampleDataSeeder = new DatabaseSeeder(ctx.getBean(UserDAO.class), ctx.getBean(RegisterService.class), ctx.getBean(LibraryDAO.class));
    sampleDataSeeder.ensureSampleLibraryExistence(); //this code is not executed in real Tomcat
    sampleDataSeeder.ensureSampleLibraryExistence(); //this code isn't either
    sampleDataSeeder.ensureSampleLibraryExistence(); //I spammed more of this to checkthat it really didn't happen
    sampleDataSeeder.ensureSampleLibraryExistence();
    sampleDataSeeder.ensureSampleLibraryExistence();
    sampleDataSeeder.ensureSampleLibraryExistence();
    EmailService service = ctx.getBean(EmailService.class);
    service.sendEmailToMaintainer("end of main reached", "some text"); //this email is  never sent on real Tomcat but always sent on embedded Tomcat
}}

Я не могу заполнить данные базы данных до инициализации контекста пружины, поскольку он инициализирует мои службы и т. д. c.

есть идеи, что может быть там? Спасибо за любой совет!

Ян

Ответы [ 2 ]

1 голос
/ 26 апреля 2020

Если вы хотите что-то сделать после запуска приложения ... Есть два способа сделать это:

Способ 1:

реализовать CommandLineRunner и реализовать метод запуска ..

@SpringBootApplication
@ComponentScan(basePackages={"com.me.myProject"})
@ServletComponentScan
public class MySpringWebApplication extends SpringBootServletInitializer implements CommandLineRunner /* needed for WAR packaging */ { 
    public static void main(String[] args){
        ApplicationContext ctx = SpringApplication.run(MySpringWebApplication.class, args);
         //this email is  never sent on real Tomcat but always sent on embedded Tomcat
    }

    @Override
    public void run(String... args) throws Exception {
        DatabaseSeeder sampleDataSeeder = new DatabaseSeeder(ctx.getBean(UserDAO.class), ctx.getBean(RegisterService.class), ctx.getBean(LibraryDAO.class));
        sampleDataSeeder.ensureSampleLibraryExistence(); //this code is not executed in real Tomcat
        sampleDataSeeder.ensureSampleLibraryExistence(); //this code isn't either
        sampleDataSeeder.ensureSampleLibraryExistence(); //I spammed more of this to checkthat it really didn't happen
        sampleDataSeeder.ensureSampleLibraryExistence();
        sampleDataSeeder.ensureSampleLibraryExistence();
        sampleDataSeeder.ensureSampleLibraryExistence();
        EmailService service = ctx.getBean(EmailService.class);
        service.sendEmailToMaintainer("end of main reached", "some text");
    }
}

Способ 2:

реализовать ApplicationRunner ..

@Component
public class AppRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
      //do after application running
    }
}
1 голос
/ 26 апреля 2020

При развертывании приложения в контейнере Tomcat ваш основной метод не запускается. Tomcat имеет собственную точку входа из операционной системы, и ваш метод не вызывается.

SpringBootServletInitializer имеет метод configure, который вы можете переопределить, но похоже, что вы пытаетесь загрузить некоторые данные до запуска приложения. Я бы порекомендовал удалить это из приложения и в собственный скрипт, так как вы будете инициализировать эти данные при каждом запуске приложения.

...