Java 如何从Spring控制器启动CommandLineRunner

Java 如何从Spring控制器启动CommandLineRunner,java,spring-mvc,spring-boot,main,Java,Spring Mvc,Spring Boot,Main,在我启动的顶级包中有一个主Spring Boot应用程序,在子包中有不同的控制器: i、 e 我可以通过URL:or启动Spring批处理 然而,在另一个包中,我有: ca.example.batch.job3.Job3Controller ca.example.batch.job3.Job3Application 。。。它不是Spring批处理,而是Spring CommandLineRunner。我想知道是否有一种方法可以在不自动启动CommandLineRunner的情况下启动MainB

在我启动的顶级包中有一个主Spring Boot应用程序,在子包中有不同的控制器:

i、 e

我可以通过URL:or启动Spring批处理

然而,在另一个包中,我有:

ca.example.batch.job3.Job3Controller
ca.example.batch.job3.Job3Application
。。。它不是Spring批处理,而是Spring CommandLineRunner。我想知道是否有一种方法可以在不自动启动CommandLineRunner的情况下启动MainBatchApplication,而是通过控制器运行它,即

我看到的控制器代码是:

package ca.example.batch.job3;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Job3Controller {

    @RequestMapping("/batch/startJob3")
    public String handle() throws Exception {

        Job3Application app = new Job3Application();

        Logger logger = LoggerFactory.getLogger(this.getClass());

        logger.info("app: " + app);

        String args = "";
        app.run(args);

        return "COMPLETE";
    }
}
Job3应用程序是:

package ca.example.batch.job3;

import static java.lang.System.exit;
import java.util.List;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.Banner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Import;
import ca.example.batch.common.CommonLibraryReference;
import ca.example.batch.common.domain.WasHost;
import ca.example.batch.common.svc.WasHostService;

@SpringBootApplication
@Import(CommonLibraryReference.class)
public class Job3Application implements CommandLineRunner {

    private final Logger logger = LoggerFactory.getLogger(Job3Application.class);

    @Autowired
    public DataSource dataSource;

    @Autowired
    public WasHostService wasHostService;

    public Job3Application() {
    }

    public static void main(String[] args) throws Exception {
        new SpringApplicationBuilder(Job3Application.class)
        .web(WebApplicationType.NONE)
        .bannerMode(Banner.Mode.OFF)
        .run(args);
    }

    @Override
    public void run(String... strings) throws Exception {
        logger.info("Loading data...");

        logger.info("wasHostService: " + wasHostService);
        List<WasHost> hostList = wasHostService.findAll();
        if (!hostList.isEmpty()) {
            for (WasHost host : hostList) {
                logger.info("hostname: " + host.getHostname());
            }
        } else {
            logger.info("No hosts found in database. Aborting data collection.");
            exit(0);
        }
    }
}
。。。当我启动控制器请求时

如果这不是正确的方法,请提出建议

基本上,我要做的是从控制器中启动main(),但使用MainBatchApplication运行时来运行它(如果有意义的话)。程序完成后,将返回代码发送回控制器并显示在浏览器中

谢谢,,
Joey

ca.example.batch.MainBatchApplication
是您启动的主要应用程序。 所以它扫描package
ca.example.batch
中的所有组件。这意味着它应该检测
ca.example.batch.job3.job3应用程序
,因此您应该能够在
Job3Controller

这应该起作用:

@Controller
public class Job3Controller {
  private final Job3Application job3Application;      

  public Job3Controller (Job3Application job3Application){
     this.job3Application = job3Application;
  }

  @RequestMapping("/batch/startJob3")
  public String handle() throws Exception {
    String[] args = ...
    this.job3Application.run(args);
    return "COMPLETE";
  }

  ....
}

已删除答案,因为问题已更改<代码>Job3应用程序运行(…)仅执行一些日志记录或终止应用程序!?所以我认为这不是很有用。为了简单起见,我删除了很多代码。然而,看看我的代码,Job3Application应该从数据库中检索一个列表并记录它们。由于«wasHostService»为空,因此不会发生这种情况。如果我单独运行Job3应用程序,它可以正常工作。使用控制器请求时失败…我猜您忘记在
MainBatchApplication
中添加
@Import(CommonLibraryReference.class)
?不,这是它的一部分。我将它添加到Job3Application中,以查看它是否有帮助,但它没有。关于“app”的实例化在Job3Controller内部,不初始化Job3Application中的@Autowired WashistService。为什么不在运行程序和控制器之间创建一个共享服务,这样就不必混合实现?@Darrenforsyth正确,这将是一个更好的方法(我在评论中建议了这一点)。。。但这并不能回答“如何从Spring Controller启动CommandLineRunner”的问题,通过代码,我在MainBatchApplication启动时得到了以下信息:
考虑在配置中定义“ca.example.batch.job3.Job3Application”类型的bean。
如果未在
MainBatchApplication
中排除
Job3Application
,则它应该存在。每个
@springboot应用程序
本身就是一个
@配置
,所以它是一个bean。。。你能演示如何使用MainBatchApplication吗?啊!我排除了“CommandLineRunner”类型的类,因为我不希望它以MainBatchApplication启动,但仅在调用Job3Controller时启动。如果我从MainBatchApplication中删除exclude,我应该在Job3Application中执行哪些操作以防止自动运行?
""2018-07-07 12:56:09 [http-nio-9191-exec-1] INFO  o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring FrameworkServlet 'dispatcherServlet'
""2018-07-07 12:56:09 [http-nio-9191-exec-1] INFO  c.e.b.job3.Job3Controller - app: ca.example.batch.job3.Job3Application@472d7ac
""2018-07-07 12:56:09 [http-nio-9191-exec-1] INFO  c.e.b.job3.Job3Application - Loading data...
""2018-07-07 12:56:09 [http-nio-9191-exec-1] INFO  c.e.b.job3.Job3Application - wasHostService: null
""2018-07-07 12:56:09 [http-nio-9191-exec-1] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
"java.lang.NullPointerException: null
    at ca.example.batch.job3.Job3Application.run(Job3Application.java:47)
    at ca.example.batch.job3.Job3Controller.handle(Job3Controller.java:21)
@Controller
public class Job3Controller {
  private final Job3Application job3Application;      

  public Job3Controller (Job3Application job3Application){
     this.job3Application = job3Application;
  }

  @RequestMapping("/batch/startJob3")
  public String handle() throws Exception {
    String[] args = ...
    this.job3Application.run(args);
    return "COMPLETE";
  }

  ....
}