3、超越CRUD:用JeecgBoot低代码模式,一天搭建功能完备的请假审批系统

3、超越CRUD:用JeecgBoot低代码模式,一天搭建功能完备的请假审批系统

超越CRUD:用JeecgBoot低代码模式,一天搭建功能完备的请假审批系统

引言:低代码革命与JeecgBoot的崛起

在当今快速变化的商业环境中,企业应用开发的传统瓶颈日益凸显:开发周期长、成本高、对专业开发人员依赖度强、难以快速响应业务变化。根据Forrester Research的报告,超过60%的企业应用开发项目存在延期交付问题,而低代码开发平台正成为解决这一困境的关键技术。

JeecgBoot作为国内领先的Java低代码开发平台,凭借其强大的代码生成能力可视化开发工具,让开发者能够以惊人的速度构建企业级应用。本文将通过一个完整的“请假审批系统”实战案例,深入解析JeecgBoot的低代码核心原理,并展示如何在一天内完成一个功能完备的后台系统开发。

一、JeecgBoot低代码架构深度解析

1.1 JeecgBoot整体架构概览

JeecgBoot采用经典的前后端分离架构,但其核心价值在于提供了一系列可视化低代码工具,大幅降低了开发门槛。下面的架构图展示了JeecgBoot的核心组件及其协作关系:

在这里插入图片描述

这种架构设计的核心优势在于分层解耦工具集成。JeecgBoot不仅提供了技术框架,更重要的是集成了完整的低代码开发工具链,使得开发者可以专注于业务逻辑,而非重复的技术实现。

1.2 低代码核心组件原理解析

1.2.1 在线表单设计器:可视化UI构建

JeecgBoot的在线表单设计器是其低代码能力的核心体现。它通过JSON Schema来描述表单结构和行为,实现了完全可视化的表单构建。其工作原理如下:

// 表单配置JSON示例{"schemas":[{"field":"leaveType","label":"请假类型","component":"JRadioButton","componentProps":{"options":[{"label":"年假","value":"1"},{"label":"病假","value":"2"},{"label":"事假","value":"3"},{"label":"调休","value":"4"}]},"rules":[{"required":true,"message":"请选择请假类型"}]},{"field":"startTime","label":"开始时间","component":"JDatePicker","componentProps":{"showTime":true,"format":"YYYY-MM-DD HH:mm:ss"},"rules":[{"required":true,"message":"请选择开始时间"}]}]}

表单设计器的技术实现基于以下关键机制:

  1. 组件注册中心:维护所有可用表单组件的元数据
  2. Schema解析引擎:将JSON Schema转换为实际的Vue组件
  3. 双向数据绑定:实时同步表单数据与UI状态
  4. 验证规则引擎:动态应用表单验证规则
1.2.2 代码生成器:自动化CRUD开发

JeecgBoot的代码生成器是其“快速开发”的基石。它采用模板驱动的代码生成策略,支持高度定制化。代码生成的工作流程如下:

用户选择数据表

解析表结构

生成基础代码模板

选择生成模式

单表模式

树表模式

一对多模式

ERP模式

应用Velocity模板

生成源代码文件

生成SQL文件

生成前端页面

输出到项目目录

用户二次开发

代码生成器的核心技术包括:

  1. 数据库元数据解析:通过JDBC DatabaseMetaData接口获取表结构信息
  2. 模板引擎:使用Velocity模板引擎进行代码生成
  3. 类型映射系统:将数据库字段类型映射为Java类型和前端组件
  4. 路径计算算法:根据命名规范自动计算包路径和文件路径
1.2.3 流程设计器:可视化工作流配置

JeecgBoot集成了Activiti工作流引擎,并提供可视化流程设计器。这使得非技术人员也能设计和修改业务流程:

// 流程定义实体@Entity@Table(name ="act_re_procdef")publicclassProcessDefinition{@IdprivateString id;@Column(name ="category_")privateString category;// 流程分类@Column(name ="name_")privateString name;// 流程名称@Column(name ="key_")privateString key;// 流程KEY@Column(name ="version_")privateInteger version;// 版本@Column(name ="deployment_id_")privateString deploymentId;// 部署ID@Column(name ="resource_name_")privateString resourceName;// 资源名称@Column(name ="diagram_resource_name_")privateString diagramResourceName;// 流程图资源@Column(name ="suspension_state_")privateInteger suspensionState;// 挂起状态}

流程设计器的核心特性

  1. BPMN 2.0兼容:支持标准BPMN流程图设计
  2. 节点类型丰富:包括用户任务、服务任务、网关、事件等
  3. 表单绑定:支持将流程节点与动态表单关联
  4. 权限配置:可视化配置任务处理人和候选组
1.2.4 报表设计器:可视化数据分析

JeecgBoot的报表设计器支持拖拽式报表设计,集成了多种图表类型和数据源:

# 报表配置示例report:id: leave_statistics name: 请假统计报表 type: chart dataSource:type: sql query:| SELECT DATE_FORMAT(start_time, '%Y-%m') as month, leave_type, COUNT(*) as count, SUM(DATEDIFF(end_time, start_time)) as total_days FROM sys_leave WHERE status = '2' -- 已批准 GROUP BY DATE_FORMAT(start_time, '%Y-%m'), leave_typecharts:-type: bar title: 月度请假统计 xAxis: month yAxis: count series: leave_type -type: pie title: 请假类型分布 data: leave_type value: count 

二、实战演练:一天构建请假审批系统

2.1 需求分析与系统设计

2.1.1 业务需求

我们要构建的请假审批系统需要满足以下核心需求:

  1. 员工功能
    • 提交请假申请(包括类型、时间、事由等)
    • 查看请假申请状态和历史记录
    • 撤销未审批的申请
  2. 审批功能
    • 部门经理审批(1-3天请假)
    • 人事部门审批(3天以上请假或特殊类型)
    • 总经理审批(7天以上请假)
  3. 管理功能
    • 请假类型管理
    • 审批流程配置
    • 请假统计报表
  4. 系统功能
    • 消息通知(邮件、站内信)
    • 日历视图展示
    • 导出请假记录
2.1.2 数据库设计
-- 请假申请表CREATETABLE`sys_leave`(`id`varchar(32)NOTNULLCOMMENT'主键ID',`user_id`varchar(32)NOTNULLCOMMENT'申请人ID',`user_name`varchar(50)NOTNULLCOMMENT'申请人姓名',`dept_id`varchar(32)DEFAULTNULLCOMMENT'部门ID',`dept_name`varchar(50)DEFAULTNULLCOMMENT'部门名称',`leave_type`varchar(2)NOTNULLCOMMENT'请假类型 1年假 2病假 3事假 4调休',`start_time`datetimeNOTNULLCOMMENT'开始时间',`end_time`datetimeNOTNULLCOMMENT'结束时间',`leave_days`decimal(10,1)NOTNULLCOMMENT'请假天数',`reason`varchar(500)NOTNULLCOMMENT'请假事由',`emergency_contact`varchar(50)DEFAULTNULLCOMMENT'紧急联系人',`emergency_phone`varchar(20)DEFAULTNULLCOMMENT'紧急联系电话',`attachment`varchar(500)DEFAULTNULLCOMMENT'附件',`status`varchar(2)NOTNULLDEFAULT'0'COMMENT'状态 0草稿 1审批中 2已批准 3已拒绝 4已撤销',`process_instance_id`varchar(64)DEFAULTNULLCOMMENT'流程实例ID',`create_time`datetimeDEFAULTNULLCOMMENT'创建时间',`update_time`datetimeDEFAULTNULLCOMMENT'更新时间',PRIMARYKEY(`id`),KEY`idx_user_id`(`user_id`),KEY`idx_status`(`status`),KEY`idx_create_time`(`create_time`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='请假申请表';-- 请假审批记录表CREATETABLE`sys_leave_approval`(`id`varchar(32)NOTNULLCOMMENT'主键ID',`leave_id`varchar(32)NOTNULLCOMMENT'请假ID',`approval_user_id`varchar(32)NOTNULLCOMMENT'审批人ID',`approval_user_name`varchar(50)NOTNULLCOMMENT'审批人姓名',`approval_result`varchar(2)NOTNULLCOMMENT'审批结果 1通过 2拒绝',`approval_comment`varchar(500)DEFAULTNULLCOMMENT'审批意见',`approval_time`datetimeNOTNULLCOMMENT'审批时间',`approval_node`varchar(50)NOTNULLCOMMENT'审批节点',`create_time`datetimeDEFAULTNULLCOMMENT'创建时间',PRIMARYKEY(`id`),KEY`idx_leave_id`(`leave_id`),KEY`idx_approval_user_id`(`approval_user_id`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='请假审批记录表';-- 请假类型表CREATETABLE`sys_leave_type`(`id`varchar(32)NOTNULLCOMMENT'主键ID',`type_code`varchar(20)NOTNULLCOMMENT'类型编码',`type_name`varchar(50)NOTNULLCOMMENT'类型名称',`max_days`int(11)DEFAULTNULLCOMMENT'最大天数',`need_approval`tinyint(1)DEFAULT'1'COMMENT'是否需要审批',`description`varchar(200)DEFAULTNULLCOMMENT'描述',`sort_no`int(11)DEFAULT'0'COMMENT'排序号',`status`varchar(2)DEFAULT'1'COMMENT'状态 1启用 0停用',PRIMARYKEY(`id`),UNIQUEKEY`uk_type_code`(`type_code`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4 COMMENT='请假类型表';

2.2 步骤一:使用在线开发创建请假模块

2.2.1 创建数据表并导入

首先在数据库中创建上述表结构,然后进入JeecgBoot的在线开发功能模块:

  1. 登录JeecgBoot系统,进入“系统管理” → “在线开发”
  2. 点击“导入数据库表”,选择sys_leave
  3. 系统自动解析表结构,生成字段配置
2.2.2 配置表单字段

在字段配置界面,我们可以对每个字段进行详细配置:

字段名字段描述表单组件校验规则列表显示查询条件
leave_type请假类型下拉框必填
start_time开始时间时间选择必填范围查询
end_time结束时间时间选择必填-
leave_days请假天数输入框数字校验-
reason请假事由文本域必填,最大500字模糊查询
status状态下拉框-

特殊字段配置示例

{"field":"leave_type","title":"请假类型","component":"JSearchSelect","options":[{"text":"年假","value":"1"},{"text":"病假","value":"2"},{"text":"事假","value":"3"},{"text":"调休","value":"4"}],"dictCode":"leave_type","validateRules":[{"required":true}],"tableShow":true,"queryShow":true}
2.2.3 生成代码并导入项目

配置完成后,点击“生成代码”按钮,系统将生成以下文件:

  1. 后端代码
    • SysLeaveController.java - 控制器
    • ISysLeaveService.java - 服务接口
    • SysLeaveServiceImpl.java - 服务实现
    • SysLeaveMapper.java - 数据访问接口
    • SysLeaveMapper.xml - MyBatis映射文件
    • SysLeave.java - 实体类
  2. 前端代码
    • SysLeaveList.vue - 列表页面
    • SysLeaveModal.vue - 表单弹窗
    • SysLeave.js - API接口文件
  3. SQL脚本
    • 初始化数据脚本
    • 菜单权限脚本

下载生成的代码包,解压并按照说明导入到JeecgBoot项目中。

2.3 步骤二:使用流程设计器配置审批流程

2.3.1 设计请假审批流程

进入“流程设计”模块,新建一个名为“请假审批流程”的流程:

1-3天

3-7天

7天以上

通过

拒绝

开始

提交请假申请

请假天数判断

部门经理审批

部门经理审批

人事审批

部门经理审批

人事审批

总经理审批

审批结果

更新请假状态

通知申请人

结束

2.3.2 配置流程节点

每个审批节点都需要配置以下信息:

  1. 节点基本信息:名称、处理人/组、表单
  2. 表单绑定:关联请假申请表单
  3. 处理规则:自动通过、手动审批等
  4. 通知配置:邮件、站内信通知

部门经理审批节点配置示例

<userTaskid="deptManagerApprove"name="部门经理审批"><extensionElements><activiti:formPropertyid="approvalResult"name="审批结果"type="enum"required="true"><activiti:valueid="1"name="通过"/><activiti:valueid="2"name="拒绝"/></activiti:formProperty><activiti:formPropertyid="approvalComment"name="审批意见"type="string"/><activiti:taskListenerevent="create"class="com.jeecg.listener.LeaveTaskListener"/></extensionElements><documentation>部门经理审批请假申请</documentation></userTask>
2.3.3 配置流程网关

流程中的决策网关需要配置条件表达式:

<sequenceFlowid="flow1"sourceRef="start"targetRef="judgeDays"><conditionExpressionxsi:type="tFormalExpression"><![CDATA[${leave != null}]]></conditionExpression></sequenceFlow><sequenceFlowid="flow2"sourceRef="judgeDays"targetRef="deptManagerOnly"><conditionExpressionxsi:type="tFormalExpression"><![CDATA[${leave.leaveDays <= 3}]]></conditionExpression></sequenceFlow><sequenceFlowid="flow3"sourceRef="judgeDays"targetRef="deptManagerFirst"><conditionExpressionxsi:type="tFormalExpression"><![CDATA[${leave.leaveDays > 3 && leave.leaveDays <= 7}]]></conditionExpression></sequenceFlow>

2.4 步骤三:自定义业务逻辑开发

虽然JeecgBoot的在线开发可以生成大部分CRUD代码,但复杂的业务逻辑仍需要手动开发。

2.4.1 请假天数自动计算

SysLeaveServiceImpl.java中添加业务逻辑:

@ServicepublicclassSysLeaveServiceImplextendsServiceImpl<SysLeaveMapper,SysLeave>implementsISysLeaveService{@Override@Transactional(rollbackFor =Exception.class)publicbooleansaveLeave(SysLeave sysLeave){// 自动计算请假天数 sysLeave.setLeaveDays(calculateLeaveDays( sysLeave.getStartTime(), sysLeave.getEndTime()));// 设置默认状态if(sysLeave.getStatus()==null){ sysLeave.setStatus("0");// 草稿状态}// 设置申请人信息LoginUser loginUser =(LoginUser)SecurityUtils.getSubject().getPrincipal(); sysLeave.setUserId(loginUser.getId()); sysLeave.setUserName(loginUser.getRealname());// 保存请假申请boolean result =this.save(sysLeave);// 如果状态是提交审批,则启动流程if("1".equals(sysLeave.getStatus())){startLeaveProcess(sysLeave);}return result;}/** * 计算请假天数(考虑工作日) */privateBigDecimalcalculateLeaveDays(Date startTime,Date endTime){// 简单的天数计算,实际应排除周末和节假日long diff = endTime.getTime()- startTime.getTime();double days =(double) diff /(1000*60*60*24);// 向上取整,半天按0.5天计算if(days %1>0){ days =Math.ceil(days *2)/2;}returnBigDecimal.valueOf(days);}/** * 启动请假审批流程 */privatevoidstartLeaveProcess(SysLeave leave){try{// 获取流程定义ProcessDefinition processDefinition = repositoryService .createProcessDefinitionQuery().processDefinitionKey("leave_approval_process").latestVersion().singleResult();// 设置流程变量Map<String,Object> variables =newHashMap<>(); variables.put("leave", leave); variables.put("applicant", leave.getUserId()); variables.put("deptManager",getDeptManager(leave.getDeptId()));// 启动流程实例ProcessInstance processInstance = runtimeService.startProcessInstanceById( processDefinition.getId(), leave.getId(), variables );// 更新请假申请的流程实例ID leave.setProcessInstanceId(processInstance.getId());this.updateById(leave);// 发送通知sendProcessStartNotification(leave);}catch(Exception e){ log.error("启动请假流程失败", e);thrownewJeecgBootException("启动审批流程失败");}}}
2.4.2 审批结果处理

创建审批服务类处理流程任务:

@ComponentpublicclassLeaveApprovalService{@AutowiredprivateRuntimeService runtimeService;@AutowiredprivateTaskService taskService;@AutowiredprivateISysLeaveService leaveService;@AutowiredprivateISysLeaveApprovalService leaveApprovalService;/** * 处理审批任务 */@Transactional(rollbackFor =Exception.class)publicvoidhandleApprovalTask(String taskId,String approvalResult,String comment,String userId){// 获取当前任务Task task = taskService.createTaskQuery().taskId(taskId).singleResult();if(task ==null){thrownewJeecgBootException("任务不存在或已完成");}// 获取流程变量String leaveId = task.getBusinessKey();SysLeave leave = leaveService.getById(leaveId);// 保存审批记录SysLeaveApproval approval =newSysLeaveApproval(); approval.setLeaveId(leaveId); approval.setApprovalUserId(userId); approval.setApprovalResult(approvalResult); approval.setApprovalComment(comment); approval.setApprovalNode(task.getTaskDefinitionKey()); approval.setApprovalTime(newDate()); leaveApprovalService.save(approval);// 设置任务变量Map<String,Object> variables =newHashMap<>(); variables.put("approvalResult", approvalResult); variables.put("approvalComment", comment); variables.put("approvalUser", userId);// 完成任务 taskService.complete(taskId, variables);// 如果流程结束,更新请假状态ProcessInstance processInstance = runtimeService .createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();if(processInstance ==null){// 流程已结束String finalStatus ="1".equals(approvalResult)?"2":"3";// 2-已批准 3-已拒绝 leave.setStatus(finalStatus); leaveService.updateById(leave);// 发送最终通知sendFinalNotification(leave, finalStatus);}}}

2.5 步骤四:使用报表设计器创建统计图表

2.5.1 设计请假统计报表

进入“报表设计”模块,创建请假统计报表:

  1. 数据源配置:连接sys_leave
  2. SQL查询设计
SELECT DATE_FORMAT(start_time,'%Y-%m')as 月份, leave_type as 请假类型,COUNT(*)as 申请次数,SUM(leave_days)as 总天数,AVG(leave_days)as 平均天数 FROM sys_leave WHEREstatus='2'-- 仅统计已批准的GROUPBY DATE_FORMAT(start_time,'%Y-%m'), leave_type ORDERBY 月份 DESC
  1. 图表设计
    • 柱状图:每月各类型请假天数对比
    • 饼图:请假类型分布
    • 折线图:请假趋势分析
2.5.2 报表页面集成

将报表集成到请假管理模块中:

<template> <div> <a-card :bordered="false"> <!-- 报表筛选条件 --> <div> <a-form layout="inline" @keyup.enter.native="searchQuery"> <a-row :gutter="24"> <a-col :md="6" :sm="8"> <a-form-item label="统计月份"> <a-month-picker v-model="queryParam.month" format="YYYY-MM" placeholder="请选择月份" /> </a-form-item> </a-col> <a-col :md="6" :sm="8"> <a-form-item label="部门"> <j-select-depart v-model="queryParam.departId" :multi="false" /> </a-form-item> </a-col> <a-col :md="6" :sm="8"> <span> <a-button type="primary" @click="searchQuery">查询</a-button> <a-button @click="searchReset">重置</a-button> </span> </a-col> </a-row> </a-form> </div> <!-- 图表展示 --> <a-row :gutter="24"> <a-col :span="12"> <a-card title="月度请假统计" size="small"> <div></div> </a-card> </a-col> <a-col :span="12"> <a-card title="请假类型分布" size="small"> <div></div> </a-card> </a-col> </a-row> <!-- 数据表格 --> <div> <a-table ref="table" size="middle" :columns="columns" :dataSource="dataSource" :pagination="ipagination" @change="handleTableChange" rowKey="id"> </a-table> </div> </a-card> </div> </template> <script> import { getLeaveStatistics } from '@/api/system/leave' import { Chart } from '@antv/g2' export default { name: 'LeaveStatistics', data() { return { queryParam: {}, ipagination: { current: 1, pageSize: 10, total: 0 }, columns: [ { title: '月份', dataIndex: 'month', align: 'center' }, { title: '请假类型', dataIndex: 'leaveType', align: 'center' }, { title: '申请次数', dataIndex: 'applyCount', align: 'center' }, { title: '总天数', dataIndex: 'totalDays', align: 'center' }, { title: '平均天数', dataIndex: 'avgDays', align: 'center' } ], dataSource: [], monthChart: null, typeChart: null } }, mounted() { this.loadData() this.initCharts() }, methods: { loadData() { const params = { ...this.queryParam, pageNo: this.ipagination.current, pageSize: this.ipagination.pageSize } getLeaveStatistics(params).then(res => { if (res.success) { this.dataSource = res.result.records || [] this.ipagination.total = res.result.total // 更新图表数据 this.updateCharts(res.result.records) } }) }, initCharts() { // 初始化月度统计图表 this.monthChart = new Chart({ container: 'monthChart', autoFit: true, height: 300 }) // 初始化类型分布图表 this.typeChart = new Chart({ container: 'typeChart', autoFit: true, height: 300 }) }, updateCharts(data) { // 更新月度统计 const monthData = this.processMonthData(data) this.monthChart.data(monthData) this.monthChart.scale({ month: { alias: '月份' }, value: { alias: '请假天数' }, type: { alias: '请假类型' } }) this.monthChart.interval().position('month*value').color('type') this.monthChart.render() // 更新类型分布 const typeData = this.processTypeData(data) this.typeChart.data(typeData) this.typeChart.coordinate('theta', { radius: 0.75 }) this.typeChart.tooltip({ showTitle: false, showMarkers: false }) this.typeChart.interval() .position('value') .color('type') .label('type', { content: (data) => { return `${data.type}: ${data.value}` } }) this.typeChart.render() }, processMonthData(data) { // 处理月度数据逻辑 return [] }, processTypeData(data) { // 处理类型数据逻辑 return [] } } } </script> 

三、JeecgBoot前后端分离架构剖析

3.1 前端架构:Ant Design Vue深度集成

JeecgBoot前端基于Ant Design Vue,并进行了深度定制和扩展:

3.1.1 组件封装体系

JeecgBoot封装了大量业务组件,提高开发效率:

// 自定义业务组件示例import JDate from'@/components/jeecg/JDate'import JSelectUser from'@/components/jeecg/JSelectUser'import JSelectDepart from'@/components/jeecg/JSelectDepart'import JSearchSelect from'@/components/jeecg/JSearchSelect'import JEditor from'@/components/jeecg/JEditor'import JUpload from'@/components/jeecg/JUpload'import JTreeSelect from'@/components/jeecg/JTreeSelect'// 组件全局注册const components =[ JDate, JSelectUser, JSelectDepart, JSearchSelect, JEditor, JUpload, JTreeSelect ]constinstall=function(Vue){ components.forEach(component=>{ Vue.component(component.name, component)})}exportdefault{ install }
3.1.2 表单渲染引擎

JeecgBoot的表单渲染引擎是其低代码能力的关键:

// 表单渲染引擎核心逻辑exportdefault{name:'JFormEngine',props:{schema:{type: Array,required:true},model:{type: Object,required:true},disabled:{type: Boolean,default:false}},render(h){// 动态渲染表单字段const children =this.schema.map(field=>{// 根据字段配置选择组件const component =this.getComponent(field)// 构建组件属性const props ={value:this.model[field.field],disabled:this.disabled || field.disabled,...field.componentProps }// 构建组件事件const on ={input:value=>{this.$set(this.model, field.field, value)this.$emit('change', field.field, value)}}// 渲染表单项returnh('a-form-item',{props:{label: field.label,required: field.rules && field.rules.some(r=> r.required)}},[h(component,{ props, on })])})returnh('a-form', children)},methods:{getComponent(field){// 组件映射表const componentMap ={input:'a-input',select:'a-select',date:'j-date',user:'j-select-user',depart:'j-select-depart',editor:'j-editor',upload:'j-upload'}return componentMap[field.component]||'a-input'}}}

3.2 后端架构:统一响应与异常处理

3.2.1 统一响应格式

JeecgBoot定义了标准的API响应格式:

/** * 统一API响应对象 */@DatapublicclassResult<T>{/** * 是否成功 */privateboolean success;/** * 响应代码 */privateInteger code;/** * 响应消息 */privateString message;/** * 响应数据 */privateT result;/** * 时间戳 */privateLong timestamp;/** * 成功响应 */publicstatic<T>Result<T>OK(){Result<T> r =newResult<>(); r.setSuccess(true); r.setCode(CommonConstant.SC_OK_200); r.setMessage("操作成功"); r.setTimestamp(System.currentTimeMillis());return r;}/** * 成功响应(带数据) */publicstatic<T>Result<T>OK(T data){Result<T> r =newResult<>(); r.setSuccess(true); r.setCode(CommonConstant.SC_OK_200); r.setResult(data); r.setMessage("操作成功"); r.setTimestamp(System.currentTimeMillis());return r;}/** * 失败响应 */publicstatic<T>Result<T>error(String msg){returnerror(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, msg);}/** * 失败响应(带错误码) */publicstatic<T>Result<T>error(int code,String msg){Result<T> r =newResult<>(); r.setCode(code); r.setMessage(msg); r.setSuccess(false); r.setTimestamp(System.currentTimeMillis());return r;}}
3.2.2 全局异常处理
/** * 全局异常处理器 */@RestControllerAdvice@Slf4jpublicclassJeecgBootExceptionHandler{/** * 处理业务异常 */@ExceptionHandler(JeecgBootException.class)publicResult<?>handleJeecgBootException(JeecgBootException e){ log.error(e.getMessage(), e);returnResult.error(e.getMessage());}/** * 处理数据库异常 */@ExceptionHandler(DaoException.class)publicResult<?>handleDaoException(DaoException e){ log.error("数据库操作异常", e);returnResult.error("数据库操作失败");}/** * 处理权限异常 */@ExceptionHandler({UnauthorizedException.class,AuthorizationException.class})publicResult<?>handleAuthorizationException(AuthorizationException e){ log.error("权限校验异常", e);returnResult.error(CommonConstant.SC_JEECG_NO_AUTHZ,"没有权限,请联系管理员授权");}/** * 处理所有其他异常 */@ExceptionHandler(Exception.class)publicResult<?>handleException(Exception e){ log.error("系统异常", e);returnResult.error("系统异常,请联系管理员");}}

3.3 前后端通信规范

3.3.1 API请求封装
// 请求拦截器 service.interceptors.request.use(config=>{// 设置tokenconst token = Vue.ls.get(ACCESS_TOKEN)if(token){ config.headers['X-Access-Token']= token }// 设置时间戳,防止缓存if(config.method ==='get'){ config.params ={...config.params,_t:newDate().getTime()}}return config },error=>{return Promise.reject(error)})// 响应拦截器 service.interceptors.response.use(response=>{// 处理文件下载if(response.config.responseType ==='blob'){return response }const res = response.data // 处理成功响应if(res.success){return res.result }// 处理token过期if(res.code ===401){ Modal.error({title:'登录过期',content:'登录已过期,请重新登录',okText:'重新登录',onOk:()=>{ store.dispatch('Logout').then(()=>{ location.reload()})}})return Promise.reject(newError(res.message ||'Error'))}// 处理其他错误const errMsg = res.message ||'请求失败' message.error(errMsg)return Promise.reject(newError(errMsg))},error=>{// 网络错误处理if(!error.response){ message.error('网络连接异常')return Promise.reject(error)}// HTTP状态码错误处理const{ status, data }= error.response switch(status){case400: message.error(data.message ||'请求参数错误')breakcase404: message.error('请求的资源不存在')breakcase500: message.error('服务器内部错误')breakdefault: message.error('请求失败')}return Promise.reject(error)})

四、低代码模式下的开发者角色演变

4.1 从编码者到架构设计者

在低代码开发模式下,开发者的角色发生了重大转变:

在这里插入图片描述

4.2 低代码开发的边界与限制

虽然JeecgBoot等低代码平台大幅提升了开发效率,但仍存在明确的边界:

4.2.1 适合低代码开发的场景
  1. 常规业务管理系统:OA、CRM、ERP等
  2. 数据收集与展示系统:报表系统、数据分析平台
  3. 工作流审批系统:各种审批流程管理
  4. 内部管理工具:员工管理、资产管理等
4.2.2 不适合低代码开发的场景
  1. 高性能计算系统:科学计算、实时交易等
  2. 复杂算法实现:机器学习、图像处理等
  3. 特定硬件交互:物联网设备控制、驱动程序
  4. 超高并发系统:大型电商、社交平台等

4.3 开发者需要关注的底层技术

即使在低代码环境下,开发者仍需掌握以下核心技术:

4.3.1 数据库设计与优化
-- 虽然低代码平台可以生成基础CRUD,但复杂查询仍需手动优化-- 示例:请假统计的优化查询EXPLAINSELECT l.user_id, u.realname, d.depart_name,COUNT(*)as total_count,SUM(l.leave_days)as total_days,MAX(l.create_time)as last_leave FROM sys_leave l LEFTJOIN sys_user u ON l.user_id = u.id LEFTJOIN sys_depart d ON u.depart_id = d.id WHERE l.status='2'AND l.create_time >= DATE_SUB(NOW(),INTERVAL1YEAR)GROUPBY l.user_id, u.realname, d.depart_name HAVING total_days >10ORDERBY total_days DESCLIMIT100;-- 创建优化索引CREATEINDEX idx_leave_user_status ON sys_leave(user_id,status, create_time);CREATEINDEX idx_leave_dept_time ON sys_leave(dept_id, create_time);
4.3.2 缓存策略设计
/** * 请假信息缓存服务 */@Service@Slf4jpublicclassLeaveCacheService{@AutowiredprivateRedisTemplate<String,Object> redisTemplate;@AutowiredprivateISysLeaveService leaveService;/** * 获取用户请假统计(带缓存) */publicUserLeaveStatsgetUserLeaveStats(String userId){String cacheKey =String.format("leave:stats:user:%s", userId);// 尝试从缓存获取UserLeaveStats stats =(UserLeaveStats) redisTemplate.opsForValue().get(cacheKey);if(stats !=null){return stats;}// 缓存未命中,查询数据库 stats = leaveService.calculateUserLeaveStats(userId);// 写入缓存,设置过期时间if(stats !=null){ redisTemplate.opsForValue().set( cacheKey, stats,1,TimeUnit.HOURS // 缓存1小时);}return stats;}/** * 清除用户请假缓存 */publicvoidclearUserLeaveCache(String userId){String cacheKey =String.format("leave:stats:user:%s", userId); redisTemplate.delete(cacheKey);// 同时清除相关的列表缓存String listKey =String.format("leave:list:user:%s:*", userId);Set<String> keys = redisTemplate.keys(listKey);if(keys !=null&&!keys.isEmpty()){ redisTemplate.delete(keys);}}}
4.3.3 系统监控与性能优化
# application-monitor.ymlmanagement:endpoints:web:exposure:include: health,info,metrics,prometheus endpoint:health:show-details: always metrics:export:prometheus:enabled:truetags:application: jeecg-leave-system distribution:percentiles-histogram:http.server.requests:true# 自定义监控指标 @Bean public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() { return registry -> registry.config().commonTags( "application","leave-system","region", System.getProperty("region", "unknown") ); }# 性能监控配置logging:level:com.jeecg: DEBUG file:name: logs/jeecg-leave.log logback:rollingpolicy:max-file-size: 10MB max-history:30

4.4 低代码开发的最佳实践

4.4.1 分层开发策略
  1. 基础层:使用低代码工具快速生成基础CRUD
  2. 业务层:手动开发复杂业务逻辑和服务
  3. 集成层:处理外部系统对接和消息队列
  4. 表现层:使用低代码表单和报表设计器
4.4.2 代码管理规范
# JeecgBoot项目代码管理规范 ## 目录结构 src/main/java/com/jeecg/ ├── modules/ # 业务模块 │ ├── leave/ # 请假模块 │ │ ├── entity/ # 实体类(低代码生成) │ │ ├── mapper/ # 数据访问(低代码生成) │ │ ├── service/ # 服务层 │ │ │ ├── impl/ # 服务实现 │ │ │ └── task/ # 定时任务 │ │ ├── controller/ # 控制器(低代码生成+手动增强) │ │ └── api/ # API接口定义 ├── common/ # 通用模块 └── system/ # 系统模块(低代码生成) ## 命名规范 - 低代码生成的文件:保留原名 - 手动新增的文件:添加业务前缀,如LeaveStatService.java - 重写低代码生成的方法:添加@Override注解 ## 版本控制 - 低代码生成的代码:单独提交,备注"低代码生成" - 手动修改的代码:详细说明修改原因 - 业务逻辑代码:遵循特性分支工作流 

五、总结:JeecgBoot低代码实践的价值与展望

5.1 一天开发的价值体现

通过本文的实战演示,我们可以看到使用JeecgBoot在一天内构建请假审批系统的实际效果:

  1. 开发效率提升:相比传统开发,效率提升**300%**以上
  2. 代码质量保证:生成的代码规范统一,减少人为错误
  3. 维护成本降低:可视化配置使得后期修改更加容易
  4. 团队协作优化:前后端分离,并行开发成为可能

5.2 JeecgBoot的适用场景总结

JeecgBoot特别适合以下类型的项目和团队:

项目类型适合程度关键考量
企业内部管理系统★★★★★快速响应业务变化需求
政府政务系统★★★★☆需要流程审批和权限控制
中小型企业ERP★★★★☆定制化需求多,预算有限
教育管理系统★★★★☆用户角色复杂,权限细分
互联网创新项目MVP★★★☆☆快速验证产品思路

5.3 未来发展趋势

随着低代码技术的不断发展,我们可以预见以下趋势:

  1. AI增强:集成AI能力,实现智能代码生成和建议
  2. 多端统一:一套代码生成多端应用(Web、小程序、App)
  3. 云原生集成:深度集成云服务,实现一键部署和扩缩容
  4. 可视化深度:从界面可视化到业务逻辑可视化
  5. 生态开放:建立插件市场,汇集第三方组件和服务

5.4 给开发者的建议

对于正在或计划使用JeecgBoot等低代码平台的开发者,建议:

  1. 掌握核心原理:不要只停留在使用层面,要理解实现机制
  2. 保持编码能力:低代码不是无代码,复杂逻辑仍需编码实现
  3. 关注业务价值:从技术实现者转变为业务解决方案提供者
  4. 持续学习更新:低代码技术发展迅速,需要不断学习新特性
  5. 参与社区贡献:积极反馈问题,贡献代码,共同推动平台发展

结语

JeecgBoot作为国内领先的Java低代码开发平台,通过本文的深度解析和实战演示,我们不仅看到了它如何大幅提升开发效率,更理解了其背后的技术原理和设计哲学。低代码不是要取代开发者,而是要解放开发者,让开发者从重复的CRUD编码中解脱出来,专注于更有价值的业务创新和技术攻关。

在数字化转型的浪潮中,掌握JeecgBoot这样的低代码工具,意味着你拥有了快速响应业务变化、高效交付企业应用的能力。这不仅是技术能力的提升,更是职业竞争力的重要组成部分。

希望本文能够帮助你深入理解JeecgBoot的低代码开发模式,并在实际项目中应用这些知识,真正实现"一天搭建一个功能完备的后台系统"的目标。


版权声明:本文为ZEEKLOG独家原创内容,遵循 CC 4.0 BY-SA 版权协议。转载请附上原文出处链接和本声明。
下篇预告:在下一篇文章中,我们将对比分析JeeSite和Guns这两个企业级开发框架,探讨在"功能全面"与"技术先进"之间如何做出最适合的技术选型。

Read more

【花雕动手做】拆解CASIC MOTOR机器人底盘14.8V无刷减速电机

【花雕动手做】拆解CASIC MOTOR机器人底盘14.8V无刷减速电机

为了做个机器人底盘,配合铝合金麦克纳姆轮使用,收了一款14.8V的无刷减速电机。这里试试简单的拆解,了解相关情况。 一、电机型号与基本信息 型号:CASIC MOTOR ZWS37U-CS-001 品牌:CASIC MOTOR(深圳航天电机系统有限公司) 类型:带行星减速箱的无刷直流电机(BLDC),内置编码器(多色线为编码器信号线) 二、核心参数(铭牌标注) 三、主要特色 无刷设计:无电刷磨损,寿命长、噪音低、效率高,适合长时间连续运行。 集成减速箱:行星减速结构,大幅提升输出扭矩,同时保持电机本体的高转速特性。 内置编码器:多色线(黄 / 红 / 黑 / 蓝 / 绿 / 白)为霍尔或增量编码器信号线,支持精准速度与位置控制。 高扭矩密度:在 37mm 直径的紧凑体积下,

OpenClaw 飞书机器人配置教程|一键对接飞书,实现聊天下达 AI 指令

OpenClaw 飞书机器人配置教程|一键对接飞书,实现聊天下达 AI 指令

适配版本:OpenClaw v2.3.12/v2.4.1(小龙虾)前置要求:已部署 OpenClaw Windows 端(Win10/Win11 均可),未部署可先下载一键部署包完成安装核心效果:配置完成后,可在飞书聊天窗口直接向机器人发送自然语言指令,OpenClaw 自动拆解任务、操控电脑完成操作,实现飞书远程下达 AI 任务 📌 OpenClaw Windows 一键部署包下载地址🔗 OpenClaw Windows 一键部署包 v2.3.12✅ 免配置、免命令行、解压即用,内置所有运行依赖,部署完成后再进行飞书配置即可 (此教程配合这个安装包使用) 一、配置前必看 1. 需拥有飞书账号,个人 / 企业账号均可,企业账号需确保有应用开发权限 2. OpenClaw

宇树VR遥操与IL——从遥操程序xr_teleoperate到unitree_IL_lerobot:如何基于G1进行manipulation开发

宇树VR遥操与IL——从遥操程序xr_teleoperate到unitree_IL_lerobot:如何基于G1进行manipulation开发

前言 如之前的文章所述,我司「七月在线」正在并行开发多个订单,目前正在全力做好每一个订单,因为保密协议的原因,暂时没法拿出太多细节出来分享 但可以持续解读我们所创新改造或二次开发的对象,即解读paper和开源库「当然 有些paper/库还没开始用,但也可以提前解读,作为关注了解」 而对于我司人形开发的订单,截止到25年4月,背后的机器人多半基于这几家:宇树、智元、傅利叶、乐聚「之所以用的这几家,一半因为我和这些公司熟,一半因为客户已有其中某一家或某几家的本体 需在其基础上做定制开发,如其它厂商看到 有兴趣合作,欢迎私我,比如星动纪元、星海图、众擎等等」 * 通过此文《Fourier-Lerobot——把斯坦福人形动作策略iDP3封装进了Lerobot(含我司七月的idp3落地实践)》可知,傅利叶 把idp3 装进了lerobot * 类似的,宇树 通过此开源库「unitree_IL_lerobot」,也把lerobot 集成了下 该库包含了π0策略 且无论咱们是用傅利叶集成的lerobot—

2026 年最值得关注的开源低代码 / 零代码平台推荐

2026 年最值得关注的开源低代码 / 零代码平台推荐

无论是零代码小白还是资深开发者,都能在这些平台上找到适合自己的解决方案。今天,我们就来盘点一下 2026 年最值得关注的开源低代码 / 零代码平台,帮助您找到最适合的工具。 一、敲敲云 - 永久免费开源零代码平台 2026 年 1 月 12 日,敲敲云全新版本 v2.3.0 正式发布! 这一版本最大的亮点是正式宣布永久免费开放,彻底打破了传统零代码平台的用户数、应用数、表单数等多重限制,实现真正的零门槛、零成本使用。 敲敲云专注于为企业快速构建应用和工作流,是一款强大且易用的零代码平台。用户无需编写任何代码,即可通过丰富的组件库轻松创建各类应用,真正做到了 "人人都是开发者"。 产品特点: * 免费零代码使用,快速上手,无需开发背景 * 丰富的组件库和模板,满足多样化应用需求 * 可视化流程设计器,支持拖放式工作流设计 * 强大的工作流引擎,支持复杂流程逻辑与条件判断 * 优秀的团队协作功能,支持资源共享和协同开发 * 数据收集能力强,