本指南将引导您基于 FIT 编程框架打造插件式的应用系统。
您将构建一个服务,该服务可以通过引入不同插件的方式,对同样的功能调用不同的实现。 本章将构建这样一个业务场景:编写应用程序 assistant 和两个 weather 插件,分别为 default-weather 插件和 other-weather 插件。assistant 应用为 HTTP 请求的接收者,我们可以发送请求 http://localhost:8080/weather ,该请求将通过 assistant 应用去调用 weather 插件。当调用 default-weather 插件时,插件的返回值为 "Default weather plugin is working.";当调用 other-weather 插件时,插件的返回值为 "Other weather plugin is working.",assistant 应用程序会将插件的返回值作为响应值输出。 也就是说,当使用 default-weather 的插件时,请求 http://localhost:8080/weather 的返回值为
Default weather plugin is working.
当使用 other-weather 的插件时,请求 http://localhost:8080/weather 的返回值为
Other Weather plugin is working.
所需要的环境:
- 编辑器,如 IntelliJ IDEA
- Java 17
- Maven,推荐版本 Maven 3.8.8+
- fitframework 源码,在
framework/fit/java目录下使用 Maven 对框架进行编译:
mvn clean install
本指引以 IntelliJ IDEA 为例:
先在 IDEA 上创建 Maven 项目,项目名为 weather。
在系统生成的 pom 文件中,添加以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fitframework</groupId>
<artifactId>weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<!-- FIT version -->
<fit.version>3.7.0-SNAPSHOT</fit.version>
<!-- Maven plugin versions -->
<maven.compiler.version>3.11.0</maven.compiler.version>
</properties>
<dependencies>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-api</artifactId>
<version>${fit.version}</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-util</artifactId>
<version>${fit.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.fitframework</groupId>
<artifactId>fit-build-maven-plugin</artifactId>
<version>${fit.version}</version>
<executions>
<execution>
<id>build-service</id>
<goals>
<goal>build-service</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>其中依赖了 fit-api 模块和 fit-util 模块,这两个依赖涉及到了使用 FIT 编程框架进行开发的必需组件。fit-build-maven-plugin 模块用于项目的构建,<goal>标签的build-service 属性指示了编译服务这个构建指令,属于服务的必选指令。
package modelengine.fit.example;
import modelengine.fitframework.annotation.Genericable;
/**
* 表示通用接口服务。
*/
public interface Weather {
/**
* 获取天气信息。
*
* @return 表示天气信息的 {@link String}。
*/
@Genericable(id = "Weather")
String get();
}接口类 Weather 的 get 方法可以返回具体的插件信息,提供给 assistant 应用使用。@Genericable 注解表示这是个接口方法,该注解也可以用在类上,表示该类的所有方法都是接口方法。@Genericable 注解的 id 属性用来唯一标识接口。
@Genericable注解的id命名仅支持数字、大小写字母以及 '-'、'_'、'*'、'.' 字符且长度在128以内。
先在 IDEA 上创建 Maven 项目,项目名为 default-weather。
在系统生成的 pom 文件中,添加以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fitframework</groupId>
<artifactId>default-weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<!-- FIT version -->
<fit.version>3.7.0-SNAPSHOT</fit.version>
<!-- Maven plugin versions -->
<maven.compiler.version>3.11.0</maven.compiler.version>
</properties>
<dependencies>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-api</artifactId>
<version>${fit.version}</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-util</artifactId>
<version>${fit.version}</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.fitframework</groupId>
<artifactId>fit-build-maven-plugin</artifactId>
<version>${fit.version}</version>
<executions>
<execution>
<id>build-plugin</id>
<goals>
<goal>build-plugin</goal>
</goals>
</execution>
<execution>
<id>package-plugin</id>
<goals>
<goal>package-plugin</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>其中依赖了 fit-api 模块和 fit-util 模块,这两个依赖涉及到了使用 Fit 编程框架进行开发的必需组件。且 pom 文件也依赖了此前创建的 weather 接口模块。fit-build-maven-plugin 模块用于项目的构建,<goal> 标签的 build-plugin 和 package-plugin 属性分别指示了编译插件和打包插件两个构建指令,属于插件的必选指令。
在 resources 目录下创建 application.yml 文件,并写入以下内容:
fit:
beans:
packages:
- 'modelengine.fit.example'package modelengine.fit.example;
import modelengine.fitframework.annotation.Component;
import modelengine.fitframework.annotation.Fitable;
/**
* 表示 {@link Weather} 的默认实现。
*/
@Component
public class DefaultWeather implements Weather {
@Override
@Fitable(id = "default-weather")
public String get() {
return "Default weather plugin is working.";
}
}@Fitable 注解表示这是个具体实现,注解的 id 属性用来唯一标识接口。
先在 IDEA 上创建 Maven 项目,项目名为 other-weather。
在系统生成的 pom 文件中,添加以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fitframework</groupId>
<artifactId>other-weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<!-- FIT version -->
<fit.version>3.7.0-SNAPSHOT</fit.version>
<!-- Maven plugin versions -->
<maven.compiler.version>3.11.0</maven.compiler.version>
</properties>
<dependencies>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-api</artifactId>
<version>${fit.version}</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-util</artifactId>
<version>${fit.version}</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.fitframework</groupId>
<artifactId>fit-build-maven-plugin</artifactId>
<version>${fit.version}</version>
<executions>
<execution>
<id>build-plugin</id>
<goals>
<goal>build-plugin</goal>
</goals>
</execution>
<execution>
<id>package-plugin</id>
<goals>
<goal>package-plugin</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>其中依赖了 fit-api 模块和 fit-util 模块,这两个依赖涉及到了使用 Fit 编程框架进行开发的必需组件。且 pom 文件也依赖了此前创建的 weather 接口模块。fit-build-maven-plugin 模块用于项目的构建,<goal> 标签的 build-plugin 和 package-plugin 属性分别指示了编译插件和打包插件两个构建指令,属于插件的必选指令。
在 resources 目录下创建 application.yml 文件,并写入以下内容:
fit:
beans:
packages:
- 'modelengine.fit.example'package modelengine.fit.example;
import modelengine.fitframework.annotation.Component;
import modelengine.fitframework.annotation.Fitable;
/**
* 表示 {@link Weather} 的另一个实现。
*/
@Component
public class OtherWeather implements Weather {
@Override
@Fitable(id = "other")
public String get() {
return "Other weather plugin is working.";
}
}@Fitable 注解表示这是个具体实现,注解的 id 属性用来唯一标识接口。
先在 IDEA 上创建 Maven 项目,项目名为 assistant。
在系统生成的 pom 文件中,添加以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fitframework</groupId>
<artifactId>assistant-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<!-- FIT version -->
<fit.version>3.7.0-SNAPSHOT</fit.version>
<!-- Maven plugin versions -->
<maven.compiler.version>3.11.0</maven.compiler.version>
</properties>
<dependencies>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-starter</artifactId>
<version>${fit.version}</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-plugins-starter-web</artifactId>
<version>${fit.version}</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.fitframework</groupId>
<artifactId>fit-build-maven-plugin</artifactId>
<version>${fit.version}</version>
<executions>
<execution>
<id>package-app</id>
<goals>
<goal>package-app</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>其中添加了 fit-starter 依赖和 fit-plugins-starter-web 依赖,fit-starter 依赖用于应用的启动,fit-plugins-starter-web 依赖使得应用程序具备了 Web 服务的基本能力,使应用能够接收 HTTP 请求并处理。且 pom 文件也依赖了此前创建的 weather 接口模块。fit-build-maven-plugin 模块用于项目的构建,<goal> 标签的 package-app 属性指示了打包应用这个构建指令,属于应用的必选指令。
我们这边在 main 方法中,通过 FitStarter 类的静态方法 start 去启动整个应用,如下图:
package modelengine.fit.example;
import modelengine.fitframework.annotation.ScanPackages;
import modelengine.fitframework.runtime.FitStarter;
/**
* 启动类。
*/
@ScanPackages("modelengine")
public class AssistantStarter {
public static void main(String[] args) {
FitStarter.start(AssistantStarter.class, args);
}
}ScanPackages 注解表示了需要扫描的包路径,通过此配置,FIT 框架会将相应包下的组件扫描到 FIT 的容器中。
在该应用程序中,HTTP 请求由控制器处理。我们可以创建相应的控制器和方法来进行处理,如下图:
package modelengine.fit.example.controller;
import modelengine.fit.example.Weather;
import modelengine.fit.http.annotation.GetMapping;
import modelengine.fitframework.annotation.Component;
import modelengine.fitframework.annotation.Fit;
/**
* 表示控制器。
*/
@Component
public class AssistantController {
private final Weather weather;
public AssistantController(@Fit Weather weather) {
this.weather = weather;
}
/**
* 获取天气信息。
*
* @return 表示天气信息的 {@link String}。
*/
@GetMapping(path = "/weather")
public String getWeather() {
return this.weather.get();
}
}其中控制器资源类作为一个组件,需要在类上标识 @Component 注解。同时考虑到需要请求的 HTTP 调用是 Get 方法,所以在对应的调用方法上需要打上 @GetMapping 注解进行标识,并通过 path 属性确定 HTTP 的访问路径。我们也可以使用 @RequestMapping 注解,再加上 method = HttpRequestMethod.GET 属性,可以达到相同的效果。
通过 path属性,我们可以知道 getWeather方法可以接收请求地址为 http://localhost:8080/weather 的 HTTP 请求,该方法用于调用 Weather 服务,Weather的具体实现需要通过引用的插件来确定。如果想使用 default-weather 插件,在 pom 文件中添加以下依赖:
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>default-weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>此时,assistant 应用完整的 pom 文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fitframework</groupId>
<artifactId>assistant-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<!-- FIT version -->
<fit.version>3.7.0-SNAPSHOT</fit.version>
<!-- Maven plugin versions -->
<maven.compiler.version>3.11.0</maven.compiler.version>
</properties>
<dependencies>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-starter</artifactId>
<version>${fit.version}</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-plugins-starter-web</artifactId>
<version>${fit.version}</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>default-weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.fitframework</groupId>
<artifactId>fit-build-maven-plugin</artifactId>
<version>${fit.version}</version>
<executions>
<execution>
<id>package-app</id>
<goals>
<goal>package-app</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>同理,如果想使用 other-weather 插件,则需要在 pom 文件中添加以下依赖:
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>other-weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>此时,assistant 应用完整的 pom 文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fitframework</groupId>
<artifactId>assistant-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<!-- FIT version -->
<fit.version>3.7.0-SNAPSHOT</fit.version>
<!-- Maven plugin versions -->
<maven.compiler.version>3.11.0</maven.compiler.version>
</properties>
<dependencies>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-starter</artifactId>
<version>${fit.version}</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>fit-plugins-starter-web</artifactId>
<version>${fit.version}</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.fitframework</groupId>
<artifactId>other-weather-for-static</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.fitframework</groupId>
<artifactId>fit-build-maven-plugin</artifactId>
<version>${fit.version}</version>
<executions>
<execution>
<id>package-app</id>
<goals>
<goal>package-app</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>首先需要使用 Maven 进行编译打包,按照 weather 接口模块、default-weather 和 other-weather 插件模块、assistant 应用模块依次编译,若不提前编译,启动时将会找不到依赖:
mvn clean install
当前应用启动有两种方式:
- 通过 IDEA 启动:您可以直接在 IDEA 运行 assistant 应用的启动类 main 方法。
- 通过执行 JAR 文件:您可以使用 Maven 在命令行运行,构建一个包含所有必要依赖项、类和资源的单个可执行 JAR 文件,并运行该文件。
下面简单介绍下执行 JAR 文件的步骤:
编译命令执行后,会生成 target 目录,其中包含了可执行 JAR 文件。然后再运行 assistant 应用模块的 JAR 文件:
java -jar target/assistant-for-static-1.0-SNAPSHOT.jar
若编译失败,请重点检查各模块pom文件的依赖及编译指令。
应用启动时,会有日志输出,来说明当前启动的情况。当出现如下的段落,说明启动已成功:
[yyyy-MM-dd hh:mm:ss.SSS] [INFO ] [main] [modelengine.fitframework.runtime.direct.DirectFitRuntime] Prepare to start FIT application...
[yyyy-MM-dd hh:mm:ss.SSS] [INFO ] [main] [modelengine.fitframework.runtime.direct.DirectFitRuntime] FIT application started.
[yyyy-MM-dd hh:mm:ss.SSS] [INFO ] [netty-http-server-thread-0] [modelengine.fit.http.server.netty.NettyHttpClassicServer] Start netty http server successfully. [port=8080]
服务顺利启动后,可以通过地址 http://localhost:8080/weather 访问资源。访问成功后,如果使用的是 default-weather 插件,会出现如下的响应:
Default weather plugin is working.
如果使用的是 other-weather 插件,会出现如下的响应:
Other weather plugin is working.
本指南引导您基于 FIT 编程框架打造插件式的应用系统。通过插件式的开发,可以打造逻辑可编排、实现多态的乐高式演进系统,且部署更加灵活(包括单进程部署、集群型微服务化部署)。