GAF快速开始-功能模块组件扩展开发流程

GAF快速开始-功能模块组件扩展开发流程

上一篇文章《GAF安装部署-微服务架构下的云原生部署》介绍如何安装部署GAF,这篇文章

首先,介绍了如何调用后端接口,用于进行扩展开发时在后端代码调用GAF已有的接口。

然后,介绍了功能组件扩展的流程,包括后端工程创建、前端工程、前后端联调、后端代码生成、构建部署、配置路由、配置菜单,通过一个简单的案例说明。

最后,介绍了在开发后端代码中使用微服务远程调用需要注意的点,以及如何获取用户信息。

阅读对象是哪些人群?

开发人员和运维人员

什么时候应该阅读?

在熟悉了GAF的功能模块后,需要根据业务进行功能模块的开发,开发完成后进行部署并集成到GAF

调用第一个后端接口

在登录GAF后,点击右上角关于,选择api文档

GAF快速开始-功能模块组件扩展开发流程_第1张图片

然后,选择认证组件(gaf-authentication), 个性化设置,在Host输入http://${主机ip}/api并启用。

GAF快速开始-功能模块组件扩展开发流程_第2张图片

然后在token接口,选择账号密码获取token接口,在调试界面输入账户sys_admin和密码123456,获取token。复制返回的"access_token"

GAF快速开始-功能模块组件扩展开发流程_第3张图片

然后,选择系统管理组件(gaf-sys-mgt),在全局参数设置里面新增请求头参数,参数名Authorization,参数值Bearer 上一步复制的token,参数类型header。

GAF快速开始-功能模块组件扩展开发流程_第4张图片

接着,查看个性化设置里面,确认Host 为http://${主机ip}/api并启用。

最后选择字典接口下的查询字典数据所有树节点接口,调试调用该接口

GAF快速开始-功能模块组件扩展开发流程_第5张图片

如何调用后端接口

如果经过网关调用后端微服务接口,则需要加统一前缀api,并且加上请求头Authorization和值Bearer ${申请的token}。直接调用微服务接口,则无需加前缀api。token中包含userid和username,下游微服务可通过token获取用户的userid和username。

申请token接口

GAF快速开始-功能模块组件扩展开发流程_第6张图片

若通过网关调用,则加api前缀。可使用postman调用,如下图。

GAF快速开始-功能模块组件扩展开发流程_第7张图片

功能组件扩展

后端工程创建与说明

在GAF的开发运维菜单下,点击扩展说明,输入应用名称和应用访问路径前缀,得到根据模板生成前后端工程命令。如下图

GAF快速开始-功能模块组件扩展开发流程_第8张图片

linux shell:

mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate \
-DgroupId="com.supermap.extend1" \
-DartifactId="extend1" \
-Dversion="1.0.0-SNAPSHOT" \
-DpackageName="com.supermap.extend1" \
-DgafVersion="3.0.0.pro-alpha-SNAPSHOT" \
-DservicePrefix="extend1" \
-DarchetypeGroupId="com.supermap.gaf.archetype" \
-DarchetypeArtifactId="gaf-spring-rest-archetype" \
-DarchetypeVersion="3.0.0" -DinteractiveMode=false \
-DarchetypeCatalog=https://nexus.gaf.net.cn/repository/maven-public/ \
-Dline.separator=$'\n'

windows power shell:

mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate -DgroupId="com.supermap.extend1" -DartifactId="extend1" -Dversion="1.0.0-SNAPSHOT" -DpackageName="com.supermap.extend1" -DgafVersion="3.0.0.pro-alpha-SNAPSHOT" -DservicePrefix="extend1" -DarchetypeGroupId="com.supermap.gaf.archetype" -DarchetypeArtifactId="gaf-spring-rest-archetype" -DarchetypeVersion="3.0.0" -DinteractiveMode=false -DarchetypeCatalog=https://nexus.gaf.net.cn/repository/maven-public/ -Dline.separator=$'\n'

生成后端工程,结构如下图。

GAF快速开始-功能模块组件扩展开发流程_第9张图片

│  pom.xml                                                   # 微服务相关的依赖和gaf相关的依赖
│
└─src
    └─main
        ├─java
        │  └─com
        │      └─supermap
        │          └─extend1
        │              │  Application.java                    # 启动类,包含一些Bean扫描包路径,以及对服务发现客户端和Feign的开启
        │              │
        │              ├─commontypes
        │              │      AppBean.java
        │              │
        │              ├─controls
        │              │      AppRestController.java
        │              │
        │              └─services
        │                  │  AppService.java
        │                  │
        │                  └─impl
        │                          AppServiceImpl.java
        │
        ├─k8s
        │      docker-entrypoint.sh                          # 将容器的启动命令
        │      Dockerfile                                    # 用于将jar构建为镜像的Dockerfile
        │      gaf-extend-deploy-backend.yaml                # 在iManager K8S上部署的GAF,扩充站点,增加微服务的编排文件
        │
        └─resources
                bootstrap-dev.yml                            # 本地开发环境的配置,包含数据源和mybatis相关配置
                bootstrap-prod.yml                           # 生产环境配置

注意:设置IDE的Line sperator 为 LF,确保文件的行分割符为LF

前端工程创建与说明

使用如下命令生成前端工程

npm config set registry https://nexus.gaf.net.cn/repository/npm-group
yarn global add @gaf/create-gaf-project
create-gaf-project extend1

子应用
extend1
extend1
10200
GAF UI 框架
是
extend1

得到如下工程结构

GAF快速开始-功能模块组件扩展开发流程_第10张图片

前端基于Vue, Ant Design Vue, GAF-UI,微前端qiankun等技术栈,

前后端启动联调

在后端IDE中导入后端工程,启动时设置激活的配置文件为dev

GAF快速开始-功能模块组件扩展开发流程_第11张图片

然后,在Application类中启动SpringBoot程序

GAF快速开始-功能模块组件扩展开发流程_第12张图片

注意1:本地需要提前安装JDK1.8及以上、Maven 3.6.3及以上、配置好后端IDE

在前端工程根目录下,执行如命令

yarn install
yarn serve

注意2:需要提前安装nodejs 16.13.2及以上、安装yarn1.22.5及以上、并配置好yarn和npm的仓库地址为https://nexus.gaf.net.cn/repository/npm-group

接着,http://localhost:10204 查看前端启动情况

GAF快速开始-功能模块组件扩展开发流程_第13张图片

代码生成

在GAF后台界面, 开发运维->组件扩展->代码模板管理,新增默认的模板并上传。http://gaf.net.cn/download/gaf/other-resources/front-back-mvc-vm.zip

GAF快速开始-功能模块组件扩展开发流程_第14张图片

在 开发运维->组件扩展->代码生成菜单下,使用刚才上传的模板,生成单表的前后端代码。步骤如下。

在数据库中创建表event,表示水管巡检维修中的事件,代表维修任务,包含 任务内容、任务类型、详细地址等, 可被分配指派给处理人员。DDL如下。

create table event
(
	id varchar(255) not null constraint event_pkey primary key,
	code varchar(255),
	create_at date,
	src_type varchar(255),
	type varchar(255),
	task_type varchar(255),
	task_type_detail varchar(500),
	report_by varchar(255),
	report_by_phone varchar(255),
	deal_by varchar(255),
	status varchar(255),
	description text,
	addr varchar(600),
	remark text
);

comment on column event.id is '事件id';
comment on column event.code is '事件编号';
comment on column event.create_at is '创建时间';
comment on column event.src_type is '来源类别';
comment on column event.type is '事件类型';
comment on column event.task_type is '任务类别';
comment on column event.task_type_detail is '任务内容';
comment on column event.report_by is '上报人员';
comment on column event.report_by_phone is '联系电话';
comment on column event.deal_by is '处理人员';
comment on column event.status is '事件状态.未分派,未接单,处理中,待审核,无效,正常完成,超时完成';
comment on column event.description is '问题描述';
comment on column event.addr is '详细地址';
comment on column event.remark is '详细备注';

在代码生成页面,填写数据源

GAF快速开始-功能模块组件扩展开发流程_第15张图片

选表event

GAF快速开始-功能模块组件扩展开发流程_第16张图片

配置模板参数

GAF快速开始-功能模块组件扩展开发流程_第17张图片

配置字段

GAF快速开始-功能模块组件扩展开发流程_第18张图片

**注意:**将创建时间的实体类型修改为Date,表单类型修改为日期时间控件

生成下载后,解压压缩包,将后端代码复制到后端工程对应位置。并且注意将mapper文件夹下的EventMapper.xml移动到后端工程的resources的mapper目录下

GAF快速开始-功能模块组件扩展开发流程_第19张图片

将前端代码复制到前端工程对应位置

GAF快速开始-功能模块组件扩展开发流程_第20张图片

并修改前端工程routes目录下的index.js,增加前端页面路由路径/event。

GAF快速开始-功能模块组件扩展开发流程_第21张图片

最后,重新启动前后端。查看 巡检维修的事件管理列表页面,http://localhost:10204/event。可新增编辑事件

GAF快速开始-功能模块组件扩展开发流程_第22张图片

构建部署

在后端工程打包之前,修改bootstrap-prod.yml中数据源的配置为

spring:
  application:
    name: extend1
  datasource:
    driver-class-name: org.postgresql.Driver
    password: '123456'
    # 修改为
    url: jdbc:postgresql://gaf-postgres:5432/gaf
    username: admin

并且在GAF部署的数据库gaf中,新增event表,DDL语句查看代码生成

后端工程mvn clean package 打包为jar包,前端工程yarn build ,生成dist目录并压缩为dist.zip。

后端上传Dockfile、docker-entrypoint.sh、jar包到GAF文件存储目录 imagebuild/extend1_backend

GAF快速开始-功能模块组件扩展开发流程_第23张图片

前端上传Dockfile、default.conf、dist.zip包到文件存储目录imagebuild/extend1_frontend

GAF快速开始-功能模块组件扩展开发流程_第24张图片

在文件存储目录 imagebuild/extend1_backend下,点击镜像构建,构建后端镜像,输入镜像的完整名称registry.cn-hangzhou.aliyuncs.com/supermap-gaf/extend1-backend:1.0。若选择推送,则需要提前准备镜像仓库,然后输入地址及用户名密码。若不推送,则会生成一个tar包,放在文件存储的当前目录下。

GAF快速开始-功能模块组件扩展开发流程_第25张图片

同理,在文件存储目录 imagebuild/extend1_frontend下,点击镜像构建,构建后端镜像,输入镜像的完整名称registry.cn-hangzhou.aliyuncs.com/supermap-gaf/extend1-frontend:1.0。若选择推送,则需要提前准备镜像仓库,然后输入地址及用户名密码。若不推送,则会生成一个tar包,放在文件存储的当前目录下。

GAF快速开始-功能模块组件扩展开发流程_第26张图片

**注意:**若未使用镜像推送,则可在文件存储中将生成的tar下载,并上传到GAF的部署环境中,使用docker load -i xxx.tar ,加载镜像用于后续部署。

目前,已经有前后端的镜像,接下来部署并集成到GAF。

若使用单机linux部署GAF,则找到安装包下的docker-compose.yml文件的services下,增加如下内容

  extend1-backend:
    image: registry.cn-hangzhou.aliyuncs.com/supermap-gaf/extend1-backend:1.0
    networks:
      - gaf-net
    restart: always
    container_name: extend1-backend
  extend1-frontend:
    image: registry.cn-hangzhou.aliyuncs.com/supermap-gaf/extend1-frontend:1.0
    networks:
    - gaf-net
    ports:
    - 31333:80
    restart: always
    container_name: extend1-frontend

然后执行./deploy.sh create extend1-backend./deploy.sh create extend1-frontend,启动前后端。

若基于iManager K8S部署GAF,则分别修改后端工程里面的gaf-extend-deploy-backend.yaml文件中的镜像地址 和 前端工程中的gaf-extend-deploy-frontend.yaml中的镜像地址。 如下

# gaf-extend-deploy-backend.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    type: gaf
  name: extend1-backend
  namespace: ${NAMESPACE}
  annotations:
    addressReg: "${SERVICE_IP}:${NODE_PORT}"
spec:
  ports:
    - port: 8080
      protocol: TCP
      targetPort: 8080
  selector:
    app: extend1-backend
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: extend1-backend
  namespace: ${NAMESPACE}
  labels:
    app: extend1-backend
  annotations:
    scale: unscalable
    console: noconsole
    portExpose: exposable
    description:

    topoProperty: "{'name':'extend1-backend','isPivot':'false'}"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: extend1-backend
  template:
    metadata:
      labels:
        app: extend1-backend
    spec:
      initContainers:
        - name: check-healthy
          image:  registry.cn-hangzhou.aliyuncs.com/supermap-gaf/busybox-curl:v1.0
          command: [ 'sh', '-c', 'until curl -fs http://gaf-microservice-conf:8080/actuator/health; do echo waiting for gaf-microservice-conf; sleep 2; done;' ]
      # 修改image为registry.cn-hangzhou.aliyuncs.com/supermap-gaf/extend1-backend:1.0
      containers:
        - image: registry.cn-hangzhou.aliyuncs.com/supermap-gaf/extend1-backend:1.0 
          imagePullPolicy: ${IMAGE_PULL_POLICY}
          name: extend1-backend
          envFrom:
            - configMapRef:
                name: gaf-env-config
                optional: false
      dnsPolicy: ClusterFirst
      restartPolicy: Always

# gaf-extend-deploy-frontend.yaml
---
apiVersion: v1
kind: Service
metadata:
  labels:
    type: gaf
  name: extend1-frontend
  namespace: ${NAMESPACE}
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: extend1-frontend
  type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
  labels:
    entrance: "true"
    entrance-port: "80"
    type: gaf
  name: extend1-frontend-nodeport
  namespace: ${NAMESPACE}
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80
      nodePort: 31333
  selector:
    app: extend1-frontend
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: extend1-frontend
  namespace: ${NAMESPACE}
  labels:
    app: extend1-frontend
  annotations:
    scale: unscalable
    console: noconsole
    description: 前端扩展组件
    topoProperty: "{'name':'extend1-frontend','isPivot':'false'}"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: extend1-frontend
  template:
    metadata:
      labels:
        app: extend1-frontend
    spec:
      # 修改为 registry.cn-hangzhou.aliyuncs.com/supermap-gaf/extend1-frontend:1.0
      containers:
        - image: registry.cn-hangzhou.aliyuncs.com/supermap-gaf/extend1-frontend:1.0
          imagePullPolicy: ${IMAGE_PULL_POLICY}
          name: extend1-frontend
      dnsPolicy: ClusterFirst
      restartPolicy: Always

然后在iManger后台站点管理下,选择gaf,点击扩展站点,选择上面修改后的文件。

GAF快速开始-功能模块组件扩展开发流程_第27张图片

配置路由

部署完成后,在GAF后台组件扩展菜单下,后端微服务路由配置添加路由,如下图所示。

GAF快速开始-功能模块组件扩展开发流程_第28张图片

前端微应用界面添加路由配置,如下图。注意,微应用入口的ip地址。

GAF快速开始-功能模块组件扩展开发流程_第29张图片

配置菜单

在GAF后台界面,系统设置的菜单管理下,新增菜单扩展示例及其子菜单维修事件管理。

GAF快速开始-功能模块组件扩展开发流程_第30张图片 GAF快速开始-功能模块组件扩展开发流程_第31张图片

最后使用管理员登录查看新增的维修事件菜单。

微服务远程调用

声明式feign

当扩展的后端工程需要调用其他微服务的接口,可以使用feign来调用。GAF提供了一些jar包,里面包含了一些基于feign的声明式接口调用。例如在后端工程pom.xml中引入依赖

        <dependency>
            <groupId>com.supermap.gafgroupId>
            <artifactId>gaf-sys-mgt-clientartifactId>
            <version>3.0.pro-beta-SNAPSHOTversion>
        dependency>

在使用的代码处,注入需要使用的对象,例如字典接口客户端

@Service
public class AppServiceImpl implements AppService {

   @Autowired
   private SysDictClient sysDictClient;
   
   public void getAllDictTreeNode() {
      List<DictDataNode> serviceType = sysDictClient.getAllDictDataTreeNode("ServiceType").checkAndGetData();
      System.out.println("serviceType = " + serviceType);
   }
}

也可以在代码,编写基于feign的声明式接口直接调用GAF的后端接口

拦截器

由于大部分后端接口逻辑需要用户信息,需要在接口调用链路中传递用户信息。由于在GAF网关处使用jwt存储认证后的用户名和用户id ,存放在请求头Authorization中,传递给下游微服务,当下游微服务之间相互调用时,需要通过请求拦截器传递token。

可通过引入依赖,使用里面已经写好的feign拦截器JWTTokenClientFeignInterceptor(已经自动注入)和RestTemplate拦截器RestTemplateInterceptor(需要手动注入)

    <dependency>
      <groupId>com.supermap.gafgroupId>
      <artifactId>gaf-common-rest-feignartifactId>
      <version>3.0.pro-beta-SNAPSHOTversion>
    dependency>

由模板创建的后端工程中,已经引入了gaf-common-rest-feign依赖。

用户信息获取

在后端工程pom.xml中,引入gaf-extend-auth依赖。

		<dependency>
			<groupId>com.supermap.gafgroupId>
			<artifactId>gaf-extend-authartifactId>
			<version>3.0.pro-beta-SNAPSHOTversion>
		dependency>

在需要用户信息的代码处,注入GafUserService对象,如下所示

@RestController
public class AppRestController {

	@Autowired
	private AppService appService;
    // 注入GafUserService对象
	@Autowired
	private GafUserService gafUserService;
// servicePrefix
	@RequestMapping("/hello")
	public AppBean helloApp(@RequestParam(value = "name", defaultValue = "rest server") String name) {
		return appService.helloApp(name);
	}

	@RequestMapping("/user")
	public Map<String, Object> user() {
		Map<String, Object> result = new HashMap<>(16);
		// 获取用户名
		String username = gafUserService.getUserName();
        // 获取租户id
		String tenantId = gafUserService.getTenantId();
        // 获取用户id
		String userId = gafUserService.getUserId();
        // 获取用户信息
		AuthUser authUser = gafUserService.getUserInfo();
		result.put("username", username);
		result.put("tenantId", tenantId);
		result.put("userId", userId);
		result.put("authUser", authUser);
		return result;
	}
}


你可能感兴趣的:(GAF,云原生,java,微服务,gis,前端框架)