配置

角色定义:

  1. proto 定义标准
  2. app 定义应用
  3. ui 定义交互

源泉均来自 proto生成的协议,然后具由此生成应用基础,应用再链接 ui; 所以一般流程:

  1. 编译 proto 生成协议
  2. 通过协议 stub 生成 应用
  3. 生成应用过程中选择是否生成 ui

UI 的生成规则,需要配置给 app, app触发UI生成;

打开 vue 生成标志, {app}/build.gradle:

hopeStub {
    enableFrontVue = true
}

{app}/ui.json:

{
  "projectDir": "../good-app-ui"
}

最后更新: 1.3.9-M2 (2025-05-27 前端架构一致在快速变动,一些变量也在改变,谨慎使用) auto router 移如内置plugin, 不再走 app 走, router 为纯前端工作!

PropertyComment
uiModuleDirUI 模块相对路径
httpVendor../http, useGet/Post 供应
apiDirpackages/service/src, API输出目录(相对uiModuleDir)
requestTypeRequestItem form 类型
requestModule../types form 类型引用路径
responseTypeResponseItem column 类型
responseModule../types column 类型引用路径
pathToUrlimport { pathToUrl } from '../utils' path 路径解析帮助函数
langDirpackages/common/locales/src/langs 国际化输出路径(相对uiModuleDir)
firstLanguagezh-CN 国际化,第一语言
secondLanguageen-US 国际化,第二语言
typesDirsrc/types 类型输出路径(相对uiModuleDir)
authSplit授权分隔符,用来组装树结构, 默认 :
noMergerfalse 预留,未用
alwaysEraseOldfalse 预留,未用

Router

项目内置 plugin 自动扫描页面,按照文件目录结构生成路由规则。

router.json 配置在 {module}-ui 模块下, 用于配置 ui 模块下应用的自动路由生成规则。

支持多模块, 比如 apps 下面有 web1, web2, 可以进行独立配置,互相隔离。

{
  "items": [
      {
          "moduleDir": "apps/web1"
      },{
          "moduleDir": "apps/web2"
      }
  ]
}
PropertyComment
moduleDirui 模块下子模块目录,如 apps/web
pagesDirsrc/pages 该模块页面目录相对路径
pagesPath@/pages 页面module 路径
routerOutDirsrc/router/auto 自动路由输出目录
menuItemMenuItem 菜单类名
menuItemImport./types 菜单类路径
disablefalse 是否disable
firstLanguage第一语言
secondLanguage第二语言
langDirsrc/locales/langs 语言输出目录

编译

普通执行 stub 命令即可生成 UI 内容:

./gradlew.bat {app}:clean stub build -x test -x stubTest

  1. 国际化
  2. Api Stub
  3. Api Model
  4. form/table Stub
  5. type
  6. 其他
├─assets
│....
├─locales
│  │  
│  └─langs
│      ├─en-US
│      │      app.json
│      │
│      └─zh-CN
│              app.json
├─service
│  │  http.ts
│  │  index.ts
│  │  type.ts
│  │  utils.ts
│  │
│  ├─api
│  │      api-example-api.ts
│  │      api-system-system.ts
│  │      index.ts
│  │
│  ├─form
│  │      TemplateExampleRequest.ts
│  │      UploadBookCoverToLocalRequest.ts
│  │
│  ├─model
│  │      api-example-request-example.ts
│  │      api-example-response-example.ts
│  │      index.ts
│  │
│  └─table
│          TemplateExampleResponse.ts
├─types
│      api.d.ts
│      app.d.ts
│      auth.d.ts

运行

由于现代的框架都是SPA(Single Page Application)架构,给前后协同都带来了挑战,ApiHug试图减少多人在前后协同带来的理解难度,和同步的滞后性。 所以采用了:

  1. 前后项目在同工程中不同子模块
  2. 工具链上融合, gradle + vite, 无缝集成,互相可以调用任务
  3. 运行时,java application 静态代理 + vue 端 proxy

以实现前后端人员协同最大化,上下文切换最低化,开发效率最大化!

App Build Hook

打包资源依赖 UI 项目打包,同时copy UI 资源 dist 到运行时静态文件目录:

    //Really Static resource of the UI to Output Dir
    tasks.register('copyUIResources', Copy) {
        dependsOn project(':good-app-ui').tasks.named('build')
        from project(':good-app-ui').layout.projectDirectory.dir('dist')
        into "${layout.buildDirectory.get()}/resources/main/static"
    }

    tasks.named('processResources') {
        dependsOn 'copyUIResources'
    }

SPA Filter

hope.open.api.spa 标志是否开启:

  1. hope.common.spring.api.spa.wbmvc.SpaMvcConfigurationSERVLET 模式下控制 SPA 配置
  2. hope.common.spring.api.spa.webflux.SpaFluxConfigurationREACTIVE 模式下控制 SPA 配置

URL 反向代理规则配置在 SpaPathChecker 中:

SpaPathChecker DEFAULT =
      path ->
          !path.startsWith("/api")
              && !path.startsWith("/management")
              && !path.startsWith("/v3/api-docs")
              && !path.startsWith("/hope/meta")
              && !path.startsWith("/h2-console")
              && !path.contains(".")
              && path.matches("/(.*)");

if (checker.passToSpa(path)) {
      request.getRequestDispatcher("/index.html").forward(request, response);
      return;
}

默认规则:

  1. 不以 /api 开头
  2. 不以 /management 开头
  3. 不以 /v3/api-docs 开头
  4. 不以 /h2-console 开头
  5. 路径中不包含点号(.
  6. 匹配表达式 ”/(.*)

举个例子:

  1. 如果有人访问 /api/users → 请求会转发到后端
  2. 如果有人访问 /about → 请求会被转发到 index.html
  3. 如果有人访问 /static/image.jpg → 请求将直接由服务器返回文件内容

然后你就可以尽情享受和前端一样丝滑的便捷和体验!