34

springboot入门08 – 创建非web项目

 4 years ago
source link: https://www.zhyea.com/2019/12/11/springboot-base-08-create-non-web-app.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

概述

从开始使用SpringBoot到现在,一直都是在用SpringBoot开发web服务(API服务)。直到前段时间,需要帮其他组的同事写一个非web的简单服务时,才想到Springboot是不是也支持非web项目。

答案是肯定的:spring诞生之初就不是为web项目定制的,springBoot无非是在spring核心项目的基础上添加了一些方便开发者使用的组件,所以使用springboot开发非web项目也是可行的。

首先我们要弄明白常用的web项目和非web项目的区别在哪儿?私以为是服务启动和执行逻辑触发的方式:

  • web项目需要依赖web容器来启动,通过http请求来触发相关的服务;
  • 非web项目则不需要依赖web容器来启动,它可以是自启动的;
  • 非web项的服务通常是主动触发的或者通过非http的方式被动触发的。

接下来详细介绍下如何使用springboot构建非web项目。

依赖

创建web项目通常需要使用的依赖是 spring-boot-starter-web

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

这个依赖间接引用了tomcat,spring-webmvc,spring-context,json-starter等依赖。这些在非web项目里基本上都用不到,非web项目可以直接使用 spring-boot-starter

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

spring-boot-starter间接引用了spring-core、yaml、auto-configure等依赖,已经足够用来创建一个普通的spring项目了。

如果有特殊情况(说实话,我强烈怀疑)非要使用 spring-boot-starter-web 依赖来构建非web项目也不是不行,只需要加一些配置来避免启动web容器就行:

spring:
  main:
    web-application-type: none

或者在启动类中添加web配置并设置为 NONE

@SpringBootApplication
public class MyApplication {
 
    public static void main(String[] args) {
        new SpringApplicationBuilder()
                .web(NONE)
                .main(MyApplication.class)
                .build(args);
    }
 
}

启动

springboot非web项目的启动类定义和web项目并无不同。如下:

@SpringBootApplication
public class MyApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
 
}

但是执行启动类中的main方法以后呢?如果是web项目,在启动后等待HTTP请求调用就行了。不过这里是非web项目,我们得想办法执行我们定义好的业务逻辑。接下来按常见的业务逻辑特征分别介绍下。

1. 任务需要定时执行

这种情况需要配置定时任务。SpringBoot对定时任务的支持还算可以。前段时间我写过关于《 SpringBoot定时任务配置 》这样的文章,有需要可以参考下,这里就不重复介绍了。

2. 在某个类的实例注入后就立即执行

这种场景说实话不多见。通常是需要该类实现 InitializingBean 接口,并在 afterPropertiesSet 方法中实现相关的逻辑。如下:

@Service
public class MyService implements InitializingBean {
 
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("--------->>> start from my service");
    }
}

还有一种方式是使用java提供的 @ PostConstruct 注解:

@Service
public class MyService {
 
    @PostConstruct
    public void init() {
        System.out.println("--------->>> start from my service init method");
    }
 
}

建议最好使用前者。

3. 使用SpringBoot的提供的主动执行接口

springboot提供了两个接口 ApplicationRunner CommandLineRunner 来支持主动执行业务逻辑。

比如我们可以直接实现 ApplicationRunner 接口,并在 run 方法中添加业务逻辑:

@Component
public class MyRunner1 implements ApplicationRunner {
 
    @Autowired
    private MyService myService;
 
    @Override
    public void run(ApplicationArguments args) {
        System.out.println("--------->>> my runner1 has started");
        System.out.println(myService.getId());
    }
 
}

CommandLineRunner 接口和 ApplicationRunner 接口的差别不大。从执行时机还是调用过程上来着,这两者几乎都是一样的。这唯一的区别在于他们提供的 run 方法的args参数类型上:

  • ApplicationRunner 的args参数是ApplicationArguments类型,对原始参数做了一层封装;
  • CommandLineRunner 的args参数是字符串类型,取的是启动类收到的原始参数。

这种差别源于SpringBoot对二者的定位上:

ApplicationRunner 适用于启动即执行的场景,只需要读取一次参数信息即可。它的参数通常是“option=value”这种结构的,如:“–foo=bar –foo=baz” 。 ApplicationArguments 中封装了一些对这种参数进行处理的方法,以便开发使用。

CommandLineRunner 从名字上看就是用来做命令行交互用的,所以它这里直接取了原始参数,看一个使用示例:

@Component
public class MyRunner3 implements CommandLineRunner {
 
    @Override
    public void run(String... args) throws Exception {
        System.out.println("Please enter your name:");
        try (Scanner scanner = new Scanner(System.in)) {
            String name = scanner.nextLine();
            System.out.println("Hello " + name + "!");
            System.out.println("Bye!");
        }
    }
 
}

如果在执行命令行交互之前也需要读取解析传入的参数,那么这里的 MyRunner3 类完全也可以实现 ApplicationRunner 接口。二者的差别几乎可以忽略。

在一个应用里面可以有多个 ApplicationRunner CommandLineRunner 的实现。要调整两者的实现类之间的执行顺序可以使用 @ Order 注解。

就这样。这一节虽然介绍的是如何创建启动非web项目,但是在web项目中也会有主动触发一些执行逻辑的需要,上面介绍的这些方案也是完全可用的。

示例代码已上传到了 GitHub/Zhyea ,有需要可自行查阅。

End!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK