jeecg-boot是什麼?
官方介紹

JeecgBoot 是一款基于代碼生成器的低代碼開發平台,零代碼開發!采用前後端分離架構:SpringBoot2.x,Ant Design&Vue,Mybatis-plus,Shiro,JWT。強大的代碼生成器讓前後端代碼一鍵生成,無需寫任何代碼! JeecgBoot引領新的開發模式(Online Coding模式-> 代碼生成器模式-> 手工MERGE智能開發), 幫助解決Java項目70%的重複工作,讓開發更多關注業務邏輯。既能快速提高開發效率,幫助公司節省成本,同時又不失靈活性!JeecgBoot還獨創線上開發模式(No代碼概念):線上表單配置(表單設計器)、移動配置能力、工作流配置(線上設計流程)、報表配置能力、線上圖表配置、插件能力(可插拔)等等!
JeecgBoot在提高UI能力的同時,降低了前後分離的開發成本,JeecgBoot還獨創線上開發模式(No代碼概念),一系列線上智能開發:線上配置表單、線上配置報表、線上圖表設計、線上設計流程等等。
JEECG宗旨是:簡單功能由Online Coding配置實作(線上配置表單、線上配置報表、線上圖表設計、線上設計流程、線上設計表單),複雜功能由代碼生成器生成進行手工Merge,既保證了智能又兼顧了靈活;
業務流程采用工作流來實作、擴充出任務接口,供開發編寫業務邏輯,表單提供多種解決方案: 表單設計器、online配置表單、編碼表單。同時實作了流程與表單的分離設計(松耦合)、并支援任務節點靈活配置,既保證了公司流程的保密性,又減少了開發人員的工作量。
- 官方網站: http://www.jeecg.com
- 源碼下載下傳: https://github.com/zhangdaiscott/jeecg-boot
- QQ交流群:②769925425、①284271917、③816531124
- 線上示範: http://boot.jeecg.com
- 版本日志: http://www.jeecg.com/doc/log
- 新手指南: 快速入門 | 常見問題| 視訊教程 | 回報問題
技術架構:
後端技術: SpringBoot_2.1.3.RELEASE + Mybatis-plus_3.1.2 + Shiro_1.4.0 + Jwt_3.7.0 + Swagger-ui + Redis 前端技術: Ant-design-vue + Vue + Webpack 其他技術: Druid(資料庫連接配接池)、Logback(日志工具) 、poi(Excel工具)、 Quartz(定時任務)、lombok(簡化代碼) 項目建構: Maven、Jdk8
前端開發必讀文檔:
前端UI元件: Ant Design of Vue
https://www.antdv.com/docs/vue/introduce
報表UI元件:viser-vue
https://viserjs.gitee.io/demo.html#/viser/bar/basic-bar
VUE基礎知識:
https://cn.vuejs.org/v2/guide
Ant Design Vue Pro:
https://pro.loacg.com/docs/getting-started
為什麼要用jeecg-boot?
作為一個後端開發人員,每次在為一家新的公司開發系統的時候,都在想盡快給公司開發出來一套簡單,美觀,好用的背景管理系統,讓後進的開發者注重專注業務,降低技術難度,進而節省人力成本,縮短項目周期,提高軟體安全品質。
既然是想盡快搞出來一套完美的系統,如果靠重新開發,耗費的精力是非常多的。
是以重新開發這條路是行不通的。
是以去開源項目尋找一套現成的系統是一種不錯的捷徑。人生有時候是需要靠捷徑的,站在前人的肩膀之上來成就自己。我們可以少走更多彎路。路走直了,通往勝利的燈塔還遠嗎?
在開源社群裡面,這樣的系統是非常多的。怎麼樣才茫茫項目之中,挑選出來一套适合自己的項目呢?
其實每個公司選擇項目的标準基本都是統一的
1:開源
2:最新技術棧(前後端分離+微服務)
3:ui美觀
4:功能完善
5:簡單上手
6:易于二次開發
看了很多優秀的開源項目,最終選擇了jeectboot這套低代碼快速開發平台。
選擇它的理由,當然最基本的是必須滿足以上6點。
除此之外還有
7:簡化第三方登入和單點登入
8:簡化導出導出功能
9:簡化檔案上傳功能
10:後端代碼生成
11:前端表單生成
改進建議
項目
1:将單體版和微服務版分離開。不要放在同一項目中,不要通過修改代碼的方式實作單體和微服務切換
開發文檔
2:開發文檔分離。将單體版和微服務版開發文檔單獨分開
配置
3:去掉本地host配置
命名規範
4:類名【JeecgFeignService】應以Impl結尾。
對于Service和DAO類,基于SOA的理念,暴露出來的服務一定是接口,内部的實作類用Impl的字尾與接口差別
5:DySmsHelper類中的常量【product】【domain】命名應該全部大寫并以下劃線分隔
常量命名應該全部大寫,單詞間用下劃線隔開,力求語義表達完整清楚,不要嫌名字長
6:FreemarkerParseFactory類中的常量【_tplConfig】【_sqlConfig】【p】命名應該全部大寫并以下劃線分隔
7:JacksonUtil類中的常量【objectMapper】命名應該全部大寫并以下劃線分隔
8:MD5Util類中的常量【hexDigits】命名應該全部大寫并以下劃線分隔
9:MybatisPlusConfig類中的常量【tenant_field】【tenantTable】命名應該全部大寫并以下劃線分隔
10:PasswordUtil類中的常量【Salt】命名應該全部大寫并以下劃線分隔
11:RandImageUtil類中的常量【key】【width】【height】【count】【lineWidth】命名應該全部大寫并以下劃線分隔
12:SqlInjectionUtil類中的常量【xssStr】命名應該全部大寫并以下劃線分隔
13:YouBianCodeUtil類中的常量【zhanweiLength】命名應該全部大寫并以下劃線分隔
14:枚舉【BrowserType】【DySmsEnum】【ExecutorRouteStrategyEnum】【QueryRuleEnum】
【QueryRuleEnum】【TriggerTypeEnum】【UrlMatchEnum】的字段缺少注釋資訊
15:類DateUtils中的【_date】命名不能以_開頭
所有程式設計相關的命名均不能以_或者$開始
16:抽象類【ExecutorRouter】命名應以Abstract或者Base開頭
17:類AutoPoiDictConfig中的變量名【commonAPI】不符合lowerCamelCase命名風格
方法名,參數名,成員變量,局部變量都統一使用lowerCamelCase,必須遵從駝峰形式
18:類BaseAspect方法名【getValueBySpEL】不符合lowerCamelCase命名風格
19:類BaseCommonService變量名【LogContent】不符合lowerCamelCase命名風格
20:類CommonController變量名【sysBaseAPI】【httpURL】和方法名【transitRESTful】不符合lowerCamelCase命名風格
21:類CookieUtil變量名【arr_cookie】不符合lowerCamelCase命名風格
22:類CronExpression變量名【dayOfWSpec】不符合lowerCamelCase命名風格
23:類DataSourceCachePool變量名【commonAPI】不符合lowerCamelCase命名風格
24:類DepartIdModel方法名【getSerialVersionUID】不符合lowerCamelCase命名風格
25:類DistributedLockHandler變量名【valueBySpEL】不符合lowerCamelCase命名風格
26:類DlMockController變量名【tug_status】【dataDB】不符合lowerCamelCase命名風格
27:類EmailSendMsgHandle方法名【SendMsg】變量名【es_receiver】【es_title】【es_content】不符合lowerCamelCase命名風格
28:類ExecutorRouteBusyover變量名【idleBeatResultSB】不符合lowerCamelCase命名風格
29:類ExecutorRouteFailover變量名【beatResultSB】不符合lowerCamelCase命名風格
30:接口ISendMsgHandle方法名【SendMsg】和變量名【es_receiver】【es_title】【es_content】不符合lowerCamelCase命名風格
31:接口ISysBaseAPI方法名【queryAllDSysCategory】不符合lowerCamelCase命名風格
32:類JeecgDataAutorUtils方法名【loadDataSearchConditonSQLString】不符合lowerCamelCase命名風格
33:類JimuReportTokenService變量名【sysBaseAPI】不符合lowerCamelCase命名風格
34:類JobGroupController變量名【list_count】【jobGroupList_all】不符合lowerCamelCase命名風格
35:類JobLogController變量名【jobGroupList_all】【list_count】不符合lowerCamelCase命名風格
36:類JobTriggerPoolHelper變量名【triggerPool_】【minTim_now】不符合lowerCamelCase命名風格
37:類JwtFilter變量名【tenant_id】不符合lowerCamelCase命名風格
38:類LoginController變量名【sysBaseAPI】不符合lowerCamelCase命名風格
39:類MD5Util方法名【MD5Encode】不符合lowerCamelCase命名風格
40:類MinioUtil變量名【file_url】方法名【getObjectURL】不符合lowerCamelCase命名風格
41:類MockController方法名【permission_no_page】不符合lowerCamelCase命名風格
42:類MybatisInterceptor變量名【local_createBy】【local_createDate】【local_sysOrgCode】不符合lowerCamelCase命名風格
43:類MybatisPlusConfig變量名【tenant_id】【sql_lowercase】不符合lowerCamelCase命名風格
44:類PasswordUtil方法名【getPBEKey】不符合lowerCamelCase命名風格
45:類PermissionDataAspect變量名commonAPI不符合lowerCamelCase命名風格
46:類Result方法名【OK】不符合lowerCamelCase命名風格
47:類ShiroRealm變量名【commonAPI】不符合lowerCamelCase命名風格
48:類SmsSendMsgHandle方法名【SendMsg】變量名【es_receiver】【es_title】【es_content】不符合lowerCamelCase命名風格
49:類SysAnnouncementController變量名【sysBaseAPI】【tokenOK】不符合lowerCamelCase命名風格
50:類SysDepartPermissionController變量名【SysDepartRolePermission】不符合lowerCamelCase命名風格
51:類SysDepartTreeModel方法名【getSerialVersionUID】不符合lowerCamelCase命名風格
52:類SysLogServiceImpl變量名【sysBaseAPI】不符合lowerCamelCase命名風格
53:類SysMessageTemplateController變量名【is_sendSuccess】不符合lowerCamelCase命名風格
54:類SystemAPIController變量名【sysBaseAPI】和方法名【queryAllDSysCategory】不符合lowerCamelCase命名風格
55:類SysUploadController變量名【file_url】不符合lowerCamelCase命名風格
56:類SysUserDepartServiceImpl變量名【queryUDep】不符合lowerCamelCase命名風格
57:類ThirdAppController變量名【msg_task_id】不符合lowerCamelCase命名風格
58:類ThirdAppTypeConfig變量名【WECHAT_ENTERPRISE】【DINGTALK】不符合lowerCamelCase命名風格
59:枚舉UrlMatchEnum變量名【match_url】不符合lowerCamelCase命名風格
60:類UserController變量名【list_count】不符合lowerCamelCase命名風格
61:類UUIDGenerator方法名【getJVM】和【getIP】不符合lowerCamelCase命名風格
62:類VxeMockController變量名【tug_status】和【dataDB】不符合lowerCamelCase命名風格
63:類WxSendMsgHandle方法名【SendMsg】和變量名【es_receiver】【es_title】【es_content】不符合lowerCamelCase命名風格
64:類XxlJobExecutor變量名【ip_port_address】不符合lowerCamelCase命名風格
65:類XxlJobTrigger變量名【runResultSB】不符合lowerCamelCase命名風格
線程池
66:JobFailMonitorHelper,JobLosedMonitorHelper,JobRegistryMonitorHelper不要顯示建立顯示建立線程,請使用線程池。
線程資源必須通過線程池提供,不允許在應用中自行顯示建立線程。
魔法值
67:不允許任何魔法值(即未經定義的常量)直接出現在代碼中
比如AdminBizImpl中的魔法值【15000】
AutoLogAspect中的魔法值【"list"】魔法值【"add"】【"edit"】【"delete"】【"import"】【"export"】【"POST"】【"PUT"】【"PATCH"】【"500"】等
事務
68:事務場景中,抛出異常被catch後,如果需要復原,一定要手動復原事務。
1:JeecgDemoServiceImpl方法【testTran】需要在Transactional注解指定rollbackFor或者在方法中顯示的rollback
2:JeecgOrderMainServiceImpl方法【saveMain】【updateMain】【updateCopyMain】【delMain】【delbatchMain】需要在Transactional注解指定rollbackFor或者在方法中顯示的rollback
3:SysAnnouncementServiceImpl方法【saveAnnouncement】【upDateAnnouncement】需要在Transactional注解指定rollbackFor或者在方法中顯示的rollback
4:SysPermissionDataRuleImpl方法【savePermissionDataRule】【deletePermissionDataRule】需要在Transactional注解指定rollbackFor或者在方法中顯示的rollback
5:SysPermissionServiceImpl方法【deletePermission】需要在Transactional注解指定rollbackFor或者在方法中顯示的rollback
6:SysUserServiceImpl方法【addUserWithRole】【editUserWithRole】【addUserWithDepart】需要在Transactional注解指定rollbackFor或者在方法中顯示的rollback
單個方法總行數
單個方法的總行數不超過80行。
1:類JobLogReportHelper中的方法【start】的總行數不要超過80行
2:類JobScheduleHelper中的方法【start】的總行數不要超過80行
3:類MybatisInterceptor中的方法【intercept】的總行數不要超過80行
4:類VxeMockController中的方法【getMockDdjhData】的總行數不要超過80行
垃圾代碼
及時清理不再使用的代碼片段或配置資訊,對于垃圾代碼或者過時的配置,堅決清理幹淨,避免程式過度臃腫,代碼備援。
比如:DynamicRouteLoader類中的這些被注釋掉的代碼
// private void loadRoutesByDataBase() {
// List<GatewayRouteVo> routeList = jdbcTemplate.query(SELECT_ROUTES, new RowMapper<GatewayRouteVo>() {
// @Override
// public GatewayRouteVo mapRow(ResultSet rs, int i) throws SQLException {
// GatewayRouteVo result = new GatewayRouteVo();
// result.setId(rs.getString("id"));
// result.setName(rs.getString("name"));
// result.setUri(rs.getString("uri"));
// result.setStatus(rs.getInt("status"));
// result.setRetryable(rs.getInt("retryable"));
// result.setPredicates(rs.getString("predicates"));
// result.setStripPrefix(rs.getInt("strip_prefix"));
// result.setPersist(rs.getInt("persist"));
// return result;
// }
// });
// if (ObjectUtil.isNotEmpty(routeList)) {
// // 加載路由
// routeList.forEach(route -> {
// RouteDefinition definition = new RouteDefinition();
// List<PredicateDefinition> predicatesList = Lists.newArrayList();
// List<FilterDefinition> filtersList = Lists.newArrayList();
// definition.setId(route.getId());
// String predicates = route.getPredicates();
// String filters = route.getFilters();
// if (StringUtils.isNotEmpty(predicates)) {
// predicatesList = JSON.parseArray(predicates, PredicateDefinition.class);
// definition.setPredicates(predicatesList);
// }
// if (StringUtils.isNotEmpty(filters)) {
// filtersList = JSON.parseArray(filters, FilterDefinition.class);
// definition.setFilters(filtersList);
// }
// URI uri = UriComponentsBuilder.fromUriString(route.getUri()).build().toUri();
// definition.setUri(uri);
// this.repository.save(Mono.just(definition)).subscribe();
// });
// log.info("加載路由:{}==============", routeList.size());
// Mono.empty();
// }
// }
被//注釋的代碼項目中有很多處,此處不再一一列出。
注釋規範
1:所有的抽象方法(包括接口中的方法)必須使用javadoc注釋,除了傳回值,參數,異常說明外,還必須指出該方法做什麼事情,實作什麼功能。
2:所有的類都必須添加創作者資訊
3:方法内部單行注釋,在被注釋語句上方另起一行,使用//注釋。方法内部多行注釋使用/**/注釋。注意與代碼對齊
代碼可讀性
除常用方法(如getXxx/isXxx)等外,不要再條件判斷中執行複雜的語句,将複雜邏輯判斷的結果指派給一個有意義的布爾變量,以提高可讀性
比如:NgAlainServiceImpl中的以下代碼
if(permission.getUrl()!=null&&(permission.getUrl().startsWith("http://")||permission.getUrl().startsWith("https://"))) {
String url= new String(Base64.getUrlEncoder().encode(permission.getUrl().getBytes()));
json.put("path", "/sys/link/" +url.replaceAll("=",""));
}else {
json.put("path", permission.getUrl());
}
和
if(permission.getUrl()!=null&&(permission.getUrl().startsWith("http://")||permission.getUrl().startsWith("https://"))) {
meta.put("url", permission.getUrl());
}
SysCategoryServiceImpl中的如下代碼片段
if((dataList == null || dataList.size()==0) && !Arrays.asList(idArr).contains(metaPid)
&& !sb.toString().contains(metaPid)){
//如果目前節點原本有子節點 現在木有了,更新狀态
sb.append(metaPid).append(",");
}
SysPermissionController中的如下代碼片段
if (url != null && (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("{{"))) {
return true;
}
SysPermissionDataRuleImpl中的如下代碼片段
if(permission!=null && (permission.getRuleFlag()==null || permission.getRuleFlag().equals(CommonConstant.RULE_FLAG_0))) {
permission.setRuleFlag(CommonConstant.RULE_FLAG_1);
sysPermissionMapper.updateById(permission);
}
SysPermissionServiceImpl中的如下代碼片段
if((oConvertUtils.isNotEmpty(pid) && !pid.equals(p.getParentId())) || oConvertUtils.isEmpty(pid)&&oConvertUtils.isNotEmpty(p.getParentId())) {
}
XxlJobServiceImpl類中的如下代碼片段
if (GlueTypeEnum.BEAN==GlueTypeEnum.match(jobInfo.getGlueType()) && (jobInfo.getExecutorHandler()==null || jobInfo.getExecutorHandler().trim().length()==0) ) {
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+"JobHandler") );
}
集合初始化大小
集合初始化時,指定集合初始化值大小
HashMap使用如下構造方法進行初始化,如果暫時無法确定集合大小,那麼指定預設值(16)即可
比如項目中多處用到
Map<String,Object> map = new HashMap<>();
建議更改為
Map<String,Object> map = new HashMap<>(16);