只需要一种选项,以下是原生的中文改写:使用Spring Boot可以启动CLI应用程序

总结

我曾经利用Spring开发了一个基于Web的应用程序,但现在需要开发一个不使用Spring Web的批处理应用程序,因为在批处理应用程序中无法找到处理DI容器的方法,所以决定写这篇文章作为备忘录。

这篇文章的目标

利用Spring Initializr 创建的新项目中,实现一个具有以下功能的命令行应用程序。

    • 実行時に引数を受け取り、指定の機能を実行することができる。

 

    CLIアプリケーションでSpringのBeanを利用する。

环境

    • Java 11

 

    • Spring Boot 2.4.3

 

    Pleiades All in One Eclipse 2020-12

一部分的依存关系

对于Maven项目来说,pom.xml的编写是必要的。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

如果是Gradle项目,则build.gradle文件中的描述是。

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
    useJUnitPlatform()
}

都是使用Spring Initializr创建的。
之后将在Eclipse中导入该项目并进行开发。

关于这次制作的内容

创建的应用程序将接受一个启动参数作为名称,并在控制台上向接收到的名称打招呼。如果没有接收到参数,则输出“Hello World!”。
为了使应用程序正常工作,我们将在启动时使用application.properties禁用Spring Boot的启动横幅。
此外,本次控制台输出使用了Logback。
各项设置如下所示。

spring.main.banner-mode = off
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>

    <logger name="console-logger">
        <appender-ref ref="STDOUT" />
    </logger>
</configuration>

文件层次结构

CliApplication
├ src/main/java
│ └ com.example
│   ├ controller
│   │ └ CliController.java
│   ├ service
│   │ ├ CliService.java
│   │ └ CliServiceImpl.java
│   └ CliApplication.java
└ src/main/resources
├ application.properties
└ logback.xml

Cli应用
├ src/main/java
│ └ com.example
│   ├ 控制器
│   │ └ CliController.java
│   ├ 服务
│   │ ├ CliService.java
│   │ └ CliServiceImpl.java
│   └ CliApplication.java
└ src/main/resources
├ application.properties
└ logback.xml

执行

虽然前面有很长的引言,但首先具有main方法的类如下所示。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import com.example.controller.CliController;

@SpringBootApplication
public class CliApplication {

    private final static Logger logger = LoggerFactory.getLogger("console-logger");

    public static void main(String[] args) {
        logger.info("処理開始!");

        try (ConfigurableApplicationContext ctx = SpringApplication.run(CliApplication.class, args)) {
            CliController controller = ctx.getBean(CliController.class);
            controller.process(args);
        } catch(Exception e) {
            e.printStackTrace();
        }

        logger.info("処理終了!");
    }
}

非常重要的部分是通过 “ConfigurableApplicationContext ctx = SpringApplication.run(CliApplication.class, args)” 来创建 Spring 的 DI Container。
对于 Web 应用程序,当服务器启动时,Bean 会被创建并处于等待状态,以便随时使用。
然而,如果像这次一样,开始后不处于等待状态,即使调用也会出现 NullPointerException,所以需要自己准备使用 DI Container。
通过这样做,就可以使用在 CliApplication.java 包下定义的 Bean,并通过 “ctx.getBean(CliController.class)” 来调用控制器。
try-with-resource 语句块是为了在主类执行后准备使用 DI Container,并在处理完成后将其关闭。

然后,每个控制器类和服务类如下所示。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.example.service.CliService;

@Controller
public class CliController {

    @Autowired
    private CliService service;

    public void process(String[] args) {
        if (args.length == 0) {
            service.greeting();
        } else {
            service.greeting(args[0]);
        }
    }
}
public interface CliService {

    public void greeting();

    public void greeting(String arg);
}

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class CliServiceImpl implements CliService {

    private final static Logger logger = LoggerFactory.getLogger("console-logger");

    public void greeting() {
        logger.info("Hello! World!");
    }
    public void greeting(String arg) {
        logger.info(String.format("Hello! %s!", arg));
    }
}

在Controller类中,不像在主类中那样调用ConfigurableApplicationContext ctx = SpringApplication.run(CliController.class, args),这是因为这样的写法会创建一个依赖注入容器。但是,由于已经在上面的包中创建了一个已存在的依赖注入容器,再次创建一个重复的依赖注入容器是没有必要的。
在主类中准备使用依赖注入容器,并在该范围内调用它,这时候处于所谓的等待状态。因此,在这里使用@Autowired可以使用Bean。

确认动作

如果不带参数启动上述项目,输出如下:

処理開始!
Hello! World!
処理終了!

而且,如果把参数设为“Nobunaga”,输出结果将如下所示。

処理開始!
Hello! Nobunaga!
処理終了!

这个处理非常简单,所以在这方面我没有特别的说明。

这次我们没有处理启动选项,所以在使用Eclipse运行时,请注意在运行配置中取消勾选ANSI控制台输出的复选框,否则会显示”Hello! –spring.output.ansi.enabled=always!”。

ansi.png
广告
将在 10 秒后关闭
bannerAds