Internal API (xlyEntry)
The xlyEntry service hosts the SPA's runtime API. It is the largest of
the three tiers — its controllers compile into the same WAR as the
framework's metadata-driven runtime, and most calls hit one of a handful
of universal endpoints that read or write any module.
This API is not a stable contract for external callers. Endpoint shapes change as the framework changes. External integrations belong on the External API. This page exists for maintainers and SPA-extension authors.
For the request-lifecycle and code-level walkthrough, see the Maintainer runtime chapter. This page is the catalog of HTTP entry points.
The universal CRUD surface — /business/*
| Endpoint | Method | Purpose |
|---|---|---|
/business/getModelBysId/{sModelsId} |
GET | Returns the form layout for a module — the five-key composite (formData, gdsformconst, gdsjurisdiction, billnosetting, report). |
/business/getBusinessDataByFormcustomId/{gdsconfigformmasterId} |
POST | Returns rows of business data for a form, paginated. Branches to getBusinessDataByGroup when sGroupList is set. |
/business/getBusinessDataByIndex |
POST | First / last / next / previous-record navigation. |
/business/addBusinessData |
POST | Single insert. |
/business/addUpdateDelBusinessData |
POST | Bundled add+update+delete in one transactional call. The frontend names the target table directly via sTable. |
/business/getSelectDataBysControlId/{sId} |
POST | Dropdown population for a single control, by control sId. |
/business/getSelectLimit/{sId} |
POST | Paginated variant of the dropdown call. |
/business/addSysLocking |
POST | Optimistic-lock acquisition when a user starts editing a document — inserts a row in the system lock table keyed by (sFormGuid, sUserId). The SPA fires this when entering edit mode so concurrent editors get a conflict warning. Handler: BusinessBaseController.java:400-407. |
/business/doExamine |
POST | Simple "approve" — flips bCheck = 1 on the named row via SQL. Does NOT invoke Activiti; this is xly's lightweight approval path used by every module that doesn't need multi-step workflow. Handler: BusinessBaseController.java:384-391 → BusinessBaseServiceImpl.doExamine → ExamineServiceImpl. See How xly handles workflow without Activiti for when Activiti is used instead. |
/business/getProData |
POST | Generic stored-procedure invocation for a module — alternate path to /procedureCall/doGenericProcedureCall. Handler: BusinessBaseController.java:350-358 → BusinessBaseServiceImpl.getProData. Used by FROUNT for module-level proc reads (the home dashboard /getProData?sModelsId=...&sName= pattern). |
These endpoints are documented in detail by Slice 1
(getModelBysId + grid load + save) and
Slice 3 (the view-backed read variant). The
handler classes are in
xlyEntry/src/main/java/com/xly/web/businessweb/.
Metadata-management endpoints
For builder-side actions (creating modules, defining forms, declaring
virtual tables) there is a parallel surface in
xlyEntry/src/main/java/com/xly/web/systemweb/:
| Endpoint root | Controller | Purpose |
|---|---|---|
/gdsmodule/* |
GdsmoduleController |
Module-tree CRUD, including getModuleTreePro, addGdsmodule, updateGdsmodule. |
/gdsconfigform/* |
GdsconfigformController |
Form-master and form-slave metadata CRUD. |
/gdsconfigtb/* |
GdsconfigtbController |
Virtual-table master/slave metadata CRUD. |
Specialised runtime endpoints
| Endpoint root | Controller | Purpose |
|---|---|---|
/configform/* |
BusinessConfigformController |
Per-user / per-group display customization. |
/treegrid/* |
BusinessTreeGridController |
Tree-grid endpoints (the proc-backed path is implemented in this branch). |
/procedureCall/* |
GenericProcedureCallController |
Generic stored-procedure invocation by name + parameters — see generic procedure dispatch. |
/panel/* |
ConfigformPanelController |
Panel-layout persistence in gdsconfigformpanel. |
/checkflow/* |
CheckFlowController |
Empty shell — returns 404. The class declares the prefix but has zero handler methods. The actual workflow approve/reject/complete URLs come from xlyFlow's CurrencyFlowController (served at xlyEntry's context-path because xlyFlow is a library dep): /currencyFlow/complete/{taskId}/{sBrandsId}/{sSubsidiaryId}/{sUserId}, /currencyFlow/completeerp/{sBrandsId}/{sSubsidiaryId}/{sUserName}, plus /modeler/* (root-mapped) for the BPMN modeler. See Activiti integration. |
/modelCenter/getModelCenter, /modelCenter/getModelCenterCalculation
|
BusinessModelCenterController |
The FROUNT home-page KPI Work Center card (titled KPI监控). Aggregates open tasks across modules tagged gdsmodule.bUnTask=1, partitioned by role and business flow. Not Activiti-driven. See The KPI Work Center. |
Reporting and printing
The print surface lives under xlyEntry/src/main/java/com/xly/web/report/:
-
PrintReportController— current jxls / iText print path. -
PrintReportControllerOld.java— file exists but its class body is fully commented out (and the commented-out class inside is namedPrintReportController, not*Old). It is dead source kept for reference, not an active controller.
The frontend's "打印" / "导出" buttons hit these controllers, which load a
template from sysreport, run the matching view-backed query, and stream
a binary file back. See Slice 3
for the flow.
Authentication
Every controller method that participates in business data is annotated
with @Authorization and receives a resolved UserInfo via
@CurrentUser. The session-to-UserInfo mapping is the framework's
own (cookie + Redis-backed session); see
the multi-tenancy concept page.
A request that reaches a controller without authentication does not
get past @Authorization; if it does (e.g., an unannotated method),
that method also bypasses the universal tenant injection in
RequestAddParamUtil — and is therefore a multi-tenant bug.
BACK builder sidebar (admin surface)
The 10 top-level items in the BACK admin sidebar (login admin/123,
edition 基础版/8s) — each is a metadata-driven screen wired through
the framework primitives above:
| Sidebar | URL fragment | Backing form-master sTbName
|
Owning service |
|---|---|---|---|
| 系统模块配置 (System Module Config) | /xtmkpz |
gdsmodule |
GdsmoduleServiceImpl |
| 数据表内容配置 (Virtual Table Config) | n/a |
gdsconfigtbmaster/slave
|
GdsconfigtbServiceImpl |
| 界面显示内容配置 (Form Definition + Customization) | n/a |
gdsconfigformmaster/slave/customslave/personalize
|
GdsconfigformServiceImpl |
| 接口自定义配置 (API Definition) | /sjbnrpz |
sysapi family |
(xlyApi-side admin) |
| 系统常量配置 (System Constants) | /xtclpz |
gdsformconst |
GdsformconstServiceImpl — Slice 1 anchor |
| 系统权限配置 (Permission Catalog) | n/a | gdsjurisdiction |
GdsjurisdictionServiceImpl |
| 常用操作配置 (Common Operations / Button Groups) | n/a | (no entry in gdsconfigformmaster for this dev DB; the page is rendered as an admin special-case wired directly in the SPA — when extended via metadata, the data lives under the user-defined button-group tier) |
n/a |
| 用户信息配置 (User Info) | n/a |
sftlogininfo family |
GdslogininfoServiceImpl |
| Mysql脚本配置 (SQL Script Authoring) | n/a | (BACK editor over the templesql/ scaffolds) |
SqlScriptsServiceImpl |
| 图表配置 (Chart Config) | (no gdsroute entry; navigated via SPA state) |
gdsconfigcharmaster/slave
|
GdsconfigformServiceImpl (chart subset) |
8 of 10 are framework primitives covered elsewhere in this catalog +
the Maintainer Reference.
常用操作配置 is a SPA-side admin special-case — it appears in the
sidebar without a corresponding gdsconfigformmaster row in the dev
DB, suggesting the page is hardcoded in BACK rather than metadata-
driven. 图表配置 is fully metadata-driven via two
gdsconfigformmaster rows pointing at gdsconfigcharmaster and
gdsconfigcharslave; chart definitions there are consumed by xly's
dashboard rendering elsewhere in the SPA.
Beyond the framework primitives — the rest of xlyEntry's surface
xlyEntry hosts 70 controllers in total. The 18 framework-side
controllers — the universal-runtime ones enumerated explicitly above
plus the seven systemweb/ admin controllers backing the
BACK builder sidebar
(GdsformconstController, GdsjurisdictionController,
GdslogininfoController, GdsparameterController, LicenseController,
LoginController, SysbrandsController) — are where every
metadata-driven form's lifecycle lives. The remaining 52 controllers
exist because the framework's universal CRUD + procedure-dispatch
path wasn't enough for the use case. Each one is, in effect, a
marker for where the data-driven thesis stopped scaling.
That makes them worth enumerating even though they are out of the framework's catalogued surface: they show what xly hardcodes in Java versus what it leaves to metadata. A maintainer reading them gets a direct read on the framework's escape-hatch shape.
Namespace overlap.
BusinessBaseController(/business/*) andQuoquotationController(also@RequestMapping("/business")) share the URL prefix. Spring resolves by method-level path, so/business/addQuotationsheetand/business/getQuoquotationProgresslive onQuoquotationControllerwhile every other/business/*endpoint is onBusinessBaseController. The collision is benign (no method-path overlap) but the convention is a foot-gun: a future contributor adding@PostMapping("/addQuotationsheet")toBusinessBaseControllerwould silently shadow the quotation path.
Form-helper and SPA-extension controllers (22)
Framework-adjacent endpoints — extensions to the universal CRUD path
that didn't fit the form-master / form-slave shape. Most are called
alongside /business/* from the same SPA screen.
| Endpoint root | Controller | Role |
|---|---|---|
/bill/* |
BillController |
Copy-a-document operations (billCopyToCheck, billCopyToCheckWork) — clone a master+slaves row-set into a new document. Not in /business/* because the SPA needs the new sId set returned in a single round-trip, which the universal save endpoint doesn't shape. |
/change/* |
ChangeController |
Generic field-change recompute (changeParam) — the SPA fires this when a field's value triggers a derived recomputation that requires hitting a proc. |
/parameter/* |
BusinessParameterController |
Per-module parameter reads. |
/treeclassify/* |
BusinessTreeClassifyController |
Tree-grouped variant of the form data load — /treeclassify/getTreeClassify/{gdsconfigformmasterId}. Lives outside /business/* because the response shape is a nested tree, not a flat row-set. |
/calcprocedure/* |
CalcProcedureController |
The runtime side of the calculation-formula feature — /calc invokes a named calc proc. |
/calculationFormula/* |
CalculationFormulaController |
Builder-side metadata for calculation formulas. |
/calculationStd/* |
CalculationStdController |
Standard-calc lookup catalog. |
/char/* |
CharController |
Chart-config CRUD for the BACK 图表配置 page — wraps gdsconfigcharmaster/slave. |
/checkModel/* |
CheckmodelController |
Approval-model membership reads (getUserListByModelId/{sCheckModeId}). Used by the lightweight (non-Activiti) approval flow. |
/comparatorTree/* |
ComparatorTreeController |
Comparator-tree reads for filterable hierarchical pickers. |
/excel/* |
ExcelController |
Excel export of a grid — /export/{gdsconfigformmasterId}. Sibling to print, but data instead of report layout. |
/import/* |
ImportExcelController |
Excel import (/checkExcel, then commit). Validates against the form's slaves before inserting. |
/filterTree/* |
FilterTreeController |
Tree-shaped filter dropdown for grids. |
/notClear/* |
NotClearController |
Barcode-scan "not yet cleared" save path (doNotClearSave, getNotClearScanData/{sProcName}/{sId}). Specific to scanner-driven warehouse flows. |
/notice/* |
NoticeController |
In-app notice fetch / mark-read. |
/replaceField/* |
ReplaceFieldController |
Bulk field-replace across rows. |
/searchgroupby/* |
SearchgroupbyController |
Saved-search definitions with group-by. |
/searchupdown/* |
SearchUpDownController |
Previous-/next-record-by-search navigation (variant of /business/getBusinessDataByIndex). |
/syssearch/* |
SyssearchController |
Saved-search definitions CRUD. |
/syssystem/* |
SyssystemController |
Variant of getBusinessDataByFormcustomId for system-table reads (/getSyssystemDataByFormcustomId/{gdsconfigformmasterId}) — bypasses tenant scoping for global metadata reads. |
/sqlfile/* |
SqlFileController |
SQL-file load/save backing the "Mysql脚本配置" admin screen. |
/instruct/* |
InstructController |
Direct SQL execution endpoints (/exesql, /opensql) — the admin-side query console. |
User and permission management (4)
Multiple overlapping controllers for the same concern. The New
suffix and the presence of sftlogininfo and userinfo and
gdslogininfo (in systemweb/) suggest a refactor in progress —
the older path coexists with the new one until callers migrate.
| Endpoint root | Controller | Role |
|---|---|---|
/userinfo/* |
UserInfoController |
Current-user profile + session info. |
/sftlogininfo/* |
SftlogininfoController |
User-account CRUD (newer of two paths). |
/sysjurisdiction/* |
SysjurisdictionController |
Group/user permission reads (getGroupData, getUserData). |
/sysjurisdictionNew/* |
SysjurisdictionNewController |
Newer parallel path (getGroupDataNew, getGroupUserIdNew/{sUserId}). Same concern, different shape. |
Manufacturing / MES (7)
Industry-tier flows whose state machines, multi-table joins, or
hardware integration could not be expressed as gdsconfigformmaster
SQL. These are the framework's largest single concentration of
hardcoded business logic.
| Endpoint root | Controller | Role |
|---|---|---|
/sysworkorder/* |
WorkOrderController |
Work-order CRUD with side effects (/add, /update/{sId}) — a printing-industry work order spans many slaves and proc invocations the universal save can't chain atomically. |
/workOrderFlow/* |
WorkOrderFlowController |
Work-order routing / process-flow reads (getWorkOrderFlow, getSplitWorkOrderData/{sId}). |
/workOrderPlan/* |
WorkOrderPlanController |
Production-plan reads linking work orders to plan rows (getControlProcess/{sProductionPlanId}, getProductionPlanInfo). |
/splitWorkOrder/* |
SplitWorkOrderController |
Splitting a master work order into multiple sub-orders (getSplitWorkOrderData). |
/productionPlan/* |
ProductionPlanController |
Plan-tree reads (getProductionPlanTree). |
/process/* |
ProcessController |
Manufacturing-process catalog reads. |
/oee/* |
OeeController |
Overall Equipment Effectiveness — barcode-scan and MES status callbacks (updateBarcode/{sBarCodeId}/{sBarCode}, doSysMesMsg/{sStatus}/{sMachineId}). |
Sales, inventory, accounting, procurement, HR (9)
| Endpoint root | Controller | Role |
|---|---|---|
/salesorder/* |
SalesOrderController |
Sales-order specifics beyond the universal CRUD. |
/business/addQuotationsheet, /business/getQuoquotationProgress
|
QuoquotationController |
Quotation-sheet creation (long-running, hence the progress endpoint). Note: shares the /business/* prefix with BusinessBaseController — see the namespace-overlap note above. |
/eleMaterialsStock/* |
EleMaterialsStockController |
Raw-material stock reads (getEleMaterialsStock, getEleMaterialsStoreCurrQty). |
/eleProductStock/* |
EleProductStockController |
Finished-product stock reads. |
/costCenter/* |
CostCenterController |
Cost-center data + voucher-import (getCostCenterData, getCosvoucherImportData). |
/sysAccountPeriod/* |
SysAccountPeriodController |
Accounting-period open/close logic. |
/erpOrderProcurement/* |
ErpOrderProcurementController |
Procurement-order specifics. |
/sisproductclassify/* |
SisproductclassifyController |
Product-classification tree. |
/eleteamemployee/* |
EleteamemployeeController |
Team/employee assignment for shop-floor flows. |
Integration and hardware (5)
| Endpoint root | Controller | Role |
|---|---|---|
/file/* |
FileController |
File upload (incl. WeChat mobile variant mobileuploadwechat). |
/plc/* |
PlcController |
PLC-bridge entry points (getplcMachine/{iOrder}/{sParentId}) — see Slice 6. |
/mobilephone/* |
MobliePhoneController |
Mobile-app endpoints. (Typo Moblie is in the class name; the URL is /mobilephone.) |
/sysWebsocket/* |
SysWebSocketController |
WebSocket setup/teardown for push notifications. |
/wechat/* |
WechatController |
WeChat integration (in-app QR, OAuth callback). |
Out-of-scope per the index (5)
Listed for completeness — these are not part of the framework wiki's in-scope surface, but they exist in the WAR.
| Endpoint root | Controller | Status |
|---|---|---|
/ai/* |
AiController |
AI assistant. Out of scope (index.md). |
/robot/* |
ChatGptController |
ChatGPT integration. Out of scope (index.md). |
/test/* |
TestController |
Dev scaffolding (/file, /getDinkToken). |
| (root paths) | TestProcessController |
Dev scaffolding; no class-level @RequestMapping. |
| (commented out) | XsController |
Dead file — @RestController and @RequestMapping are commented out; class exists but registers nothing. |
Reading these as a diagnostic
Three patterns stand out when you scan the list:
-
Long-running or multi-step transactions (
QuoquotationController.getQuoquotationProgress,BillController.billCopyToCheck,SplitWorkOrderController) — the universal save is single-shot; any flow that needs a progress endpoint or a "clone then redirect" semantic needs its own controller. -
Industry-specific state machines (
OeeController, work-order family,SysAccountPeriodController) — when "the next legal state" can't be derived from a single column, the proc-dispatch path isn't enough and the controller wires up the orchestration in Java. -
Hardware or external systems (
PlcController,WechatController,SysWebSocketController,FileController) — anything that isn't "MySQL + HTTP" needs Java glue; metadata can't describe an inbound websocket or a serial-port handshake.
The framework's universal runtime is what's missing from these controllers' jobs.
What this API is not
- Not stable — endpoint shapes change with the framework.
- Not authenticated for outside callers — there is no API-key flow here; cookies/sessions are not what an integrator wants.
- Not documented for self-service — the surface is too large and too generic to publish as an OpenAPI doc. External integrators get the curated External API instead.