# lowCode
**Repository Path**: xprj-Co_Ltd/lowCode
## Basic Information
- **Project Name**: lowCode
- **Description**: 这是一个低代码甚至是零代码的Java 后端快速开发框架,基于jdk25 Spring Boot + MyBatis Plus 构建,提供自动化 CRUD、动态 Join 查询、数据钩子(DataHook)等能力,定位为"低代码/敏捷开发"基础设施。通过灵活的页面设计器,以及可视化的表结构维护页面,快速构建一个满足基础CRUD功能的页面,完全可以做到零代码开发
- **Primary Language**: Java
- **License**: AGPL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2026-03-03
- **Last Updated**: 2026-03-09
## Categories & Tags
**Categories**: Uncategorized
**Tags**: 低代码, 零代码
## README
# HT Platform 恒泰数字化快速开发平台
[](https://openjdk.java.net/)
[](https://spring.io/projects/spring-boot)
[](https://vuejs.org/)
[](https://www.typescriptlang.org/)
[](https://baomidou.com/)
[](LICENSE)
🚀 **零代码 · 低代码 · 高并发 · 企业级**
[首页](#-关于项目) | [特性](#-核心特性) | [快速开始](#-快速开始) | [文档](#-文档) | [演示](#-在线演示) | [贡献](#-贡献指南)
---
## 📖 关于项目
HT Platform 是一个基于 **JDK 25** + **Spring Boot 3.5.6** + **Vue 3.5.22** 构建的企业级快速开发平台。平台以"**零代码优先,低代码补充
**"为设计理念,通过可视化配置和强大的扩展能力,帮助开发者**减少 80% 的重复工作**,专注于业务创新。
本系统旨在构建一个减少重复工作的的快速开发平台,提升开发效率,并减少开发过程中重复工作。本系统基于jdk25构建,使用MyBatis-Plus作为数据库操作框架,
使用Caffeine + Redis构建起多级缓存框架,以适应高并发场景,
使用Druid作为数据库连接池,使用 knife4j作为接口文档生成工具,使用Lombok作为代码生成工具,使用spring security作为系统的权限认证架构,
自定义token生成算法,是的token简洁,减少数据传输,提高数据传输效率,token仅作为权限标识,不承载数据的传输。系统中基于mybatis-plus自定义
实现了常用的join查询,解决了mybatis-plus在需要使用join的情况下需要自己写sql的问题,完美的将sql降到最低,从而提升编码效率,开发者只需关注自己的
业务实现即可。
1. 平台提供了初始的前端模版,可以通过页面设计器配置化的方式来配置复杂的页面,页面结构通过树形结构展示与配置(暂不支持拖放组件),页面个组件都支持独立配置,达到直观与简洁的效果,可以配置出复杂的页面的结构。
2. 页面提供了动态SQL模板,通过配置化方式来配置动态SQL,从而达到动态SQL的配置化。将配置好的sql名称,填写到对应的页面组件数据源中,页面在读取数据的时候将从配置的sql中读取,简化sql,提高可维护性
3. 页面提供了可视化的表结构配置,可以定义表字段、索引、表关联登高级功能,可以直接从表结构生成想要的页面,例如单表格页面、单表单页面,或者表格与表单同时存在的页面。
4. 用户建立好了表结构,根据表结构配置出相关页面后,即可直接使用基础的增删改查功能,真正做到了零代码。如果与复杂的功能需求,系统定义了钩子函数,只需要在对应的钩子函数中添加自己的逻辑即可。大大减少了开发量。
5. 系统省去了传统的service层,使用钩子函数代替,但是如果有功能需要服务,建议保留service层。
### 核心价值
- ⚡ **极速开发**:可视化页面设计器 + 自动化代码生成,开发效率提升 5-10 倍
- 🎯 **零代码实现**:90% 的常规业务需求无需编码,配置即可用
- 🔧 **灵活扩展**:钩子函数机制 + 完整的 API 体系,满足复杂业务场景
- 🛡️ **企业级安全**:国密算法加密 + Spring Security + 自定义 Token,保障数据安全
- 🚀 **高性能架构**:Caffeine + Redis 多级缓存,轻松应对高并发场景
---
## ✨ 核心特性
### 🔥 后端核心能力
系统支持国密加密操作,所有数据传输均通过加密后传输,数据密钥key随机生成,刷新页面会改变密钥,保证数据安全,以满足等保测评要求。密钥也采用了双向多重加密机制,确保密钥安全
#### 平台配置
``` java
ht:
config:
signature-filter: # 簽名过滤配置
enabled: false # 是否开启签名过滤
enabled-encrypt: # 是否开启数据加密
enabled: false # 是否开启签名过滤
ignore-paths: # 忽略放行的白名單
- /api/v1/user/login
white-path: # 配置白名单
- /api/v1/user/login
- /api/v1/user/logout
```
#### 钩子函数
无侵入式的业务扩展点,覆盖数据操作全生命周期:系统中定了常用的增删改查以及通用的逻辑处理,如果需要自定义对应的逻辑,例如添加用户时,需要同步处理用户的角色、部门登信息,此时需要自定义实现钩子函数。实现钩子函数需要继承实现org.ht.mybatis.hook.DataHook类,
由于低代码逻辑与常见的接口实体代码有些差别,因此钩子函数在低代码和常见接口代码中有细微差异。
1. 常见的接口中的钩子函数,需要有一个实体类,这个实体类对应的是数据库表对应,需要有对应的数据库操作的mapper,可以直接在钩子函数中使用其mapper无需单独注入,例如
``` java
@Component
public class TableObjectHook extends DataHook {
@Resource
private TableColumnsMapper tableColumnsMapper;
@Override
public void beforeInsert(TableObject data) {
// 检查表是否重复
TableObject one = baseMapper.selectOne(new QueryWrapper().lambda().eq(TableObject::getTableName, data.getTableName()));
if (one != null) {
// 如果修改的数据与原始数据不一致,则不允许修改
throw new BusinessRunTimeException("表已存在,不可创建相同的表");
}
data.setDelFlag(YorN.N.name());
data.setOperationType("ADD");
}
@Override
public void afterInsert(TableObject data) {
// 同步创建默认字段列
List cols = new ArrayList<>();
// id主键列
TableColumns col = new TableColumns();
col.setTableName(data.getTableName());
col.setTableId(data.getId());
col.setColumnCode("id");
col.setColumnName("主键");
col.setNotNull(YorN.Y.name());
col.setColumnType("bigint");
col.setShowPage(YorN.N.name());
col.setPersistentFlag(YorN.Y.name());
col.setApplyEdit(YorN.N.name());
col.setDelFlag(YorN.N.name());
cols.add(col);
tableColumnsMapper.insert(cols);
}
@Override
public void addBatch(List data) {
}
@Override
public void beforeUpdate(TableObject data) {
// 检查表是否重复
TableObject one = baseMapper.selectOne(new QueryWrapper().lambda().eq(TableObject::getTableName, data.getTableName()));
if (!data.getId().equals(one.getId())) {
// 如果修改的数据与原始数据不一致,则不允许修改
throw new BusinessRunTimeException("表已存在,不可创建相同的表");
}
// 这里控制不能修改表属性、例如持久化、是否视图等
if (!one.getIsPersistence().equals(data.getIsPersistence())) {
throw new BusinessRunTimeException("表属性不允许修改");
}
if (!one.getIsView().equals(data.getIsView())) {
throw new BusinessRunTimeException("表属性不允许修改");
}
// 不允许直接修改旧表名称
if (!data.getOldName().equals(data.getTableName())) {
data.setOldName(one.getOldName());
}
data.setDelFlag(YorN.N.name());
data.setOperationType("EDIT");
}
@Override
public void afterUpdate(TableObject data) {
}
@Override
public void beforeDelete(TableObject data) {
throw new BusinessRunTimeException("不允许删除表结构");
}
@Override
public void updateBatch(List data) {
}
@Override
public void afterDelete(TableObject data) {
}
@Override
public void beforeDelete(List data) {
}
@Override
public void afterDelete(List data) {
}
}
```
2. 低代码的钩子函数与普通接口代码的钩子函数有细微差异,在写法上无区别,仅仅只需要在钩子函数上加上一个自定义注解@LowCodeHook,需要指定一个参数pageId,此参数需要与页面设计器中的应用名称保持一致,
统一需要继承自DataHook,固定泛型为DynamicEntity动态实体类。其他函数方法、写法与普通接口钩子函数一致,无区别,例如:
```java
@Component
@LowCodeHook(pageId = "role-page")
public class RolePageHook extends DataHook {
@Resource
private RoleMenuMapper roleMenuMapper;
@Resource
private MenuMapper menuMapper;
@Override
public DynamicEntity afterQueryOne(DynamicEntity result) {
Long id = result.getLong("id");
List roleMenus = roleMenuMapper.selectList(
new QueryWrapper()
.lambda()
.eq(RoleMenu::getRoleId, id)
);
List list = roleMenus.stream().map(x -> x.getMenuId().toString()).toList();
result.put("roleMenu", list);
return result;
}
@Override
public void beforeInsert(DynamicEntity data) {
}
@Override
public void afterInsert(DynamicEntity data) {
}
@Override
public void addBatch(List data) {
}
@Override
public void beforeUpdate(DynamicEntity data) {
}
@Override
public void afterUpdate(DynamicEntity data) {
String roleMenu = data.getString("roleMenu");
if (StringUtils.isNotBlank(roleMenu)) {
String[] split = roleMenu.split(",");
// 转换为List
List menuIds = new ArrayList<>();
for (String s : split) {
menuIds.add(Long.parseLong(s));
}
// 查询菜单的父级,确保菜单层级完整
List