Skip to content

Latest commit

 

History

History
755 lines (620 loc) · 26.2 KB

File metadata and controls

755 lines (620 loc) · 26.2 KB

本指南将引导您基于 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 为例:

创建接口模块 weather

创建项目

先在 IDEA 上创建 Maven 项目,项目名为 weather

构建 pom 文件

在系统生成的 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();
}

接口类 Weatherget 方法可以返回具体的插件信息,提供给 assistant 应用使用。@Genericable 注解表示这是个接口方法,该注解也可以用在类上,表示该类的所有方法都是接口方法。@Genericable 注解的 id 属性用来唯一标识接口。

@Genericable注解的id命名仅支持数字、大小写字母以及 '-'、'_'、'*'、'.' 字符且长度在128以内。

创建插件 default-weather

创建项目

先在 IDEA 上创建 Maven 项目,项目名为 default-weather

构建 pom 文件

在系统生成的 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-pluginpackage-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 属性用来唯一标识接口。

创建插件 other-weather

创建项目

先在 IDEA 上创建 Maven 项目,项目名为 other-weather

构建 pom 文件

在系统生成的 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-pluginpackage-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 属性用来唯一标识接口。

创建应用 assistant

创建项目

先在 IDEA 上创建 Maven 项目,项目名为 assistant

构建 pom 文件

在系统生成的 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 编程框架打造插件式的应用系统。通过插件式的开发,可以打造逻辑可编排、实现多态的乐高式演进系统,且部署更加灵活(包括单进程部署、集群型微服务化部署)。