Create a Business Project Based on app-scaffold-starter
This guide explains how to create a production-ready backend project based on cn.geelato:geelato-app-scaffold-starter, and how to use the built-in baseline capabilities.
1. Create a new project
You can either:
- copy the runnable sample
geelato-hello-example/geelato-app-scaffold, then change Maven coordinates / package name / configs - or create an empty Spring Boot project and add the starter dependency
Minimal pom.xml snippet:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.geelato</groupId>
<artifactId>geelato-framework-bom</artifactId>
<version>${geelato.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.geelato</groupId>
<artifactId>geelato-app-scaffold-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
2. Bootstrap class
Use cn.geelato.web.platform.boot.BootApplication as the base class and make sure your business package is included in scanning:
@SpringBootApplication(scanBasePackages = {"cn.geelato", "com.acme.order"})
public class AcmeOrderApplication extends BootApplication {}
3. application.properties (minimal)
spring.application.name=acme-order-center
server.port=8088
spring.datasource.primary.name=primary
spring.datasource.primary.jdbc-url=${GEELATO_PRIMARY_JDBCURL:jdbc:mysql://localhost:3306/acme_order_center?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true}
spring.datasource.primary.username=${GEELATO_PRIMARY_JDBCUSER:acme_user}
spring.datasource.primary.password=${GEELATO_PRIMARY_JDBCPASSWORD:acme@psd}
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
geelato.orm.dao-bean-name=dynamicDao
geelato.datasource.dynamic.enable-jta-transaction=false
geelato.datasource.dynamic.enable-seata-proxy=false
geelato.app.scaffold.enabled=true
geelato.app.scaffold.auto-init-tables=true
geelato.app.scaffold.strict=true
geelato.app.scaffold.capabilities=login,mql,organization,user,dictionary,upload
springdoc.api-docs.enabled=true
springdoc.api-docs.path=/v3/api-docs
geelato.app.scaffold.openapi-enabled=true
geelato.app.scaffold.openapi-expose-in-prod=false
# OSS (optional)
# enable /api/oss/* only when the config is complete
# geelato.oss.accessKeyId=***
# geelato.oss.accessKeySecret=***
# geelato.oss.endPoint=oss-cn-xxx.aliyuncs.com
# geelato.oss.bucketName=your-bucket
# geelato.oss.region=cn-xxx
geelato.meta.scan-package-names=cn.geelato,com.acme.order
geelato.graal.scan-package-names=cn.geelato,com.acme.order
4. Verify starter readiness
GET /api/scaffold/ready
5. How to use baseline capabilities
5.1 Authentication (JWT + OAuth2)
- JWT login:
POST /api/user/login(no Authorization required)- subsequent calls:
Authorization: JWTBearer {token}
- subsequent calls:
- OAuth2 login:
POST /api/oauth2/login- refresh:
POST /api/oauth2/refreshToken - subsequent calls:
Authorization: Bearer {accessToken}
- refresh:
5.2 File upload / download (OSS optional)
- Upload:
POST /api/upload/file
Upload example (the response is an Attachment, keep the returned id for later view/download):
curl -X POST "http://localhost:8088/api/upload/file" \
-H "Tenant-Code: geelato" \
-H "Authorization: JWTBearer {token}" \
-F "file=@D:/tmp/demo.png"
How to view after upload:
- View attachment metadata:
GET /api/attach/get/{id} - Preview / download file:
GET /api/resources/file?id={id}&isPreview=true
Download file: GET /api/resources/file
- Download JSON config:
GET /api/resources/json?fileName=... - OSS management (only when OSS enabled):
/api/oss/*
5.3 MQL (generic CRUD)
POST /api/meta/listPOST /api/meta/save/{biz}POST /api/meta/delete/{biz}/{id}
5.4 ORM Fluent DSL (backend code)
Use MetaFactory in your business services. See ORM / Fluent DSL docs in this site.
5.5 Dictionary
The scaffold initializes a demo dictionary when auto-init-tables=true (so you can verify the baseline data quickly):
- dictCode:
demo_status - fetch:
GET /api/dictionary/demo_status
How to add a dictionary:
- Create or update dictionary:
POST /api/dict/createOrUpdate
curl -X POST "http://localhost:8088/api/dict/createOrUpdate" \
-H "Content-Type: application/json" \
-H "Tenant-Code: geelato" \
-H "Authorization: JWTBearer {token}" \
--data "{\"dictCode\":\"order_status\",\"dictName\":\"Order Status\",\"enableStatus\":1,\"tenantCode\":\"geelato\"}"
How to add dictionary items:
- Create or update dictionary item:
POST /api/dict/item/createOrUpdate
curl -X POST "http://localhost:8088/api/dict/item/createOrUpdate" \
-H "Content-Type: application/json" \
-H "Tenant-Code: geelato" \
-H "Authorization: JWTBearer {token}" \
--data "{\"dictId\":\"{dictId}\",\"itemCode\":\"PAID\",\"itemName\":\"Paid\",\"seqNo\":1,\"enableStatus\":1,\"tenantCode\":\"geelato\"}"
How to verify:
- Fetch items by dict code (tree):
GET /api/dict/item/queryItemByDictCode/{dictCode} - Fetch by code (lightweight API):
GET /api/dictionary/{code}
5.6 Organization / User / RBAC
- Org:
/api/security/org/* - User:
/api/security/user/* - Role:
/api/security/role/* - Permission:
/api/security/permission/*
The scaffold initializes a demo organization and binds the bootstrap user gl_user to it (default org):
- orgId:
9000000000000000101 - orgName:
示例组织
How to add an org:
POST /api/security/org/createOrUpdate
curl -X POST "http://localhost:8088/api/security/org/createOrUpdate" \
-H "Content-Type: application/json" \
-H "Tenant-Code: geelato" \
-H "Authorization: JWTBearer {token}" \
--data "{\"pid\":\"9000000000000000101\",\"code\":\"DEV\",\"name\":\"R&D\",\"type\":\"department\",\"category\":\"inside\",\"tenantCode\":\"geelato\"}"
How to add a user:
POST /api/security/user/createOrUpdate(returnsplainPasswordfor first login)
curl -X POST "http://localhost:8088/api/security/user/createOrUpdate" \
-H "Content-Type: application/json" \
-H "Tenant-Code: geelato" \
-H "Authorization: JWTBearer {token}" \
--data "{\"loginName\":\"tom\",\"name\":\"Tom\",\"orgId\":\"{orgId}\",\"tenantCode\":\"geelato\",\"enableStatus\":1}"
How to grant role to user (minimal RBAC loop):
- Create role:
POST /api/security/role/createOrUpdate - Bind user-role:
POST /api/security/role/user/insert
curl -X POST "http://localhost:8088/api/security/role/user/insert" \
-H "Content-Type: application/json" \
-H "Tenant-Code: geelato" \
-H "Authorization: JWTBearer {token}" \
--data "{\"userId\":\"{userId}\",\"roleId\":\"{roleId}\",\"tenantCode\":\"geelato\"}"
5.7 Swagger (OpenAPI)
/v3/api-docs/swagger-ui/index.html
5.8 Build HTTP services quickly
Create your own controllers/services in your business package. Prefer using @ApiRestController so the /api prefix applies consistently.