工欲善其事,必先利其器。
一年前,我接到爲團隊落地一個快速開發腳手架
的任務。javascript
在月底這節骨眼上,時間緊,任務急,有想本身擼一個腳手架的人都趕忙把這想法收起來吧!這勞民又傷身的事咱確定是不能幹的!前端
因而,我將目光放在了 Gitee Star
比較靠前的開源項目上,這是當時調研的數據 Java Web 開發腳手架調研。vue
其中MCMS、lenosp、bootdo等項目,咱們甚至已經有過項目落地經驗,但最終咱們仍是選擇了jeecg-boot,選擇它的理由咱們有這幾點:java
[x] 先後分離架構webpack
[x] 熱門技術棧git
Spring Boot + Mybatis Plus
,能更專一理解需求與業務邏輯Vue + Ant Design Vue
,既能快速開發業務,還有時間對頁面性能優化作研究Ant Design
組件庫設計資源,統一了設計風格[x] 基於角色的訪問控制體系github
[x] 完善的開發文檔web
[x] 活躍的社區生態redis
1300+
20000+
正是基於這些點,咱們選擇相信 jeecg-boot!<img src="https://img-blog.csdnimg.cn/20200827115123583.png" width="100px"/>spring
通過一年多,咱們見證了 jeecg-boot 在 github 從 star 2000+
到如今的 star 14.7k
,
而咱們團隊也已經有 5 個服務是基於 jeecg-boot 2.0.0 進行開發,並有 4 個服務已投入生產使用。
相比咱們使用的 2.0.0 版本,jeecg-boot 2.2.1
在功能上已經很是完善,且已經造成了穩定的代碼風格,在代碼分層的工做上也細化了不少。
可是,在分層領域模型
方面,始終是使用Entity
貫穿各層,若是能將分層領域模型
落地,jeecg-boot 必定會更加優秀。
咱們在分層領域模型規約的一些實踐: 遵循 JAVA開發手冊
# 對象模型 Model (接口入參 表單驗證 swagger註解) VO (返回頁面對象) View Object BO (業務層對象) DO (數據庫返回結果集) DTO (遠程調用傳輸對象) 實體類 (與數據表一一對應) # 接口入參接收對象:XXXModel 【推薦】不包含`id、updateBy、updateTime、createBy、createTime`等屬性,經過sql攔截注入這一系列字段 【推薦】必傳字段校驗 【推薦】字段長度校驗 【推薦】格式校驗 【推薦】時間格式轉換 `@DateTimeFormat` (入參格式化,將字符串時間格式化爲Date對象) # 接口返回值:XXXVO 【強制】不包含敏感字段(手機號、密碼、郵箱、身份證號) 【強制】包含敏感字段時對數據加密 【推薦】使用`@JsonView`註解控制返回值的字段可見性 【推薦】字典字段轉換 如,`@Dict(dicCode = "sex")` 【推薦】時間格式轉換 `@JsonFormat` (出參格式化,將Date對象時間格式化爲字符串)
這裏之因此有這個建議,是由於咱們安所有門的同窗找了開發同窗好幾回麻煩,最後咱們將 token 的存儲作了一些改造。
方案一:
username_token
的形式,使用 username_UUID
。ShiroRealm#doGetAuthenticationInfo
邏輯,先使用 token 從 redis 獲取 jwt token 。JwtUtil.getUsername(token)
以前須要先從 redis 獲取 jwt token 。方案二:
固然,還能夠將 jwt token 進行加密,向前端返回加密後的 token,然後端只需增長一個對被加密的token
進行解密
的過濾器。
既可知足不將 jwt token 返回給前端,又不會對原有邏輯進行調整,知足開閉原則
。
這也是安所有門同窗找開發同窗談過話的案例!<img src="https://img-blog.csdnimg.cn/20200827114603322.png" width="50px"/>
咱們的實踐方案:
使用 redis 對單位時間內(咱們是 5 分鐘)的用戶登陸失敗次數進行計數。
失敗次數達到 5 次後,將對該帳戶進行凍結(5 分鐘),5 分鐘後 redis key 過時,該用戶便可正常登陸。
JeecgPorperties.java
對前綴爲jeecg
的配置進行管理,避免使用@Value
獲取屬性值的行爲。spring-boot-configuration-processor
依賴,爲已聲明的配置項增長提示。.env.*
配置文件,將配置與環境隔離目前 jeecg-boot 的前端,一直使用的是 window._CONFIG
來掛載相關全局變量,它有一個缺點就是沒有將配置與環境隔離
。
好比:
在開發環境下window._CONFIG['domianURL'] = 'http://127.0.0.1:8080/jeecg-boot'
在測試環境下window._CONFIG['domianURL'] = 'http://test.product.com:8080/jeecg-boot'
在生產環境下window._CONFIG['domianURL'] = 'http://prod.product.com:8080/jeecg-boot'
打包不一樣的環境,都須要人爲的去改動這些配置,對CI/CD
極不友好。
咱們的實踐方案:
分環境提供配置,並在package.json
增長相應打包腳本,提升部署效率。
相似於後端項目中的:
application.yml application-dev.yml application-prod.yml application-test.yml
咱們能夠看到initDictConfig
是一個空方法,它就是一個勾子函數,子組件若是重寫了該方法,則會在執行created生命週期函數
時,執行子組件中重寫的邏輯。
因此,咱們能夠向JeecgListMixin
的賦能更多勾子函數,知足更多場景,提升靈活性,提升開發效率。
咱們的實踐方案:
// created生命週期函數中執行 應用場景:加載異步詞典項等 initDictConfig() {} // 搜索以前執行 應用場景:對 queryParam 對象內的數據,作一些數據轉換工做等 beforeSearch() {} // 重置以前執行 應用場景:重置一些沒有綁定在 queryParam 對象內的數據等 beforeReset() {} // loadData加載數據成功以後執行 應用場景:須要在該時機下作一些數據的轉換工做等 afterLoadDataSuccess() {} // 在 loadData 內執行 應用場景:自定義數據加載邏輯 // 執行 loadData 時,會先判斷是否重寫了 customLoadData 方法 customLoadData() {}
刷新時會觸發兩次路由守衛的beforeEach函數
當前 jeecg-boot 2.2.1 是一次性加載全部資源,不管是開發仍是生產階段都是不利的!
對於開發階段,開發同窗每次刷新頁面須要等待 3 ~ 4 秒,
對於生產階段,就會涉及到首屏加載
這個指標的考驗。
對資源作按需加載/縮減資源體積
能極大的優化加載性能,也是一件頗有意義的事。
咱們能夠對 jeecg-boot 前端作的一些優化:
component:() => import(/* webpackChunkName: "component" */ component.vue)
splitChunks
對依賴的第三方資源拆包固然,還有更多 jeecg-boot 用戶能夠作的優化
在業務開發過程當中,一個頁面可能有不少Modal / Drwaer
,就須要咱們加一些響應式變量和方法去控制這些Modal / Drawer
的 顯示/關閉,而這些工做每每都是重複的。
那麼,咱們能不能抽象一下這些重複的工做,將更多的精力放在組件的邏輯上去呢?
咱們的實踐方案:
Modal / Drawer 的父組件引入@/mixins/ModalParentMixin
,並在mounted
生命週期函數中使用register
方法對 ref 的值進行註冊
<template> <div> <a-button type="primary" @click="showModal('addModal')">新增</a-button> <a-button type="primary" @click="showModal('editModal')">編輯</a-button> <a-button type="primary" @click="showModal('detailModal')">詳情</a-button> <!--新增--> <modal-add ref="addModal" @ok="searchReset"/> <!--編輯--> <modal-edit ref="editModal" @ok="searchReset"/> <!--詳情--> <!--條件渲染,將v-if="isShow('detailModal')" @close="closeModal"一塊兒使用便可--> <modal-detail ref="detailModal" @ok="searchReset" v-if="isShow('detailModal')" @close="closeModal"/> </div> </template> <script> import ModalParentMixin from '@/mixins/ModalParentMixin' export default { mixins: [ ModalParentMixin], mounted() { // 註冊當前頁面有哪些modal this.register(['addModal', 'editModal', 'detailModal']) }, } </script>
@/mixins/ModalMixin
如今咱們控制頁面上全部的 Modal / Drawer 是否是要輕鬆不少了呢?
不再用聲明各類不一樣的 xxxVisible
來控制這些子組件的顯示/關閉
。
這個本應該去 Ant Design Vue 提 issue 的,可是跟了好幾個版本以後,他們並無作修復,獲得的答案彷佛是:設計如此
!
既然這樣,咱們就本身來作一些處理,去規避掉這個 BUG。
{ total: 11, current: 2, pageSize: 10 }
。{ total: 10, current: 2, pageSize: 10 }
,顯示暫無數據
。
JeecgListMixin.js
的handleDelete
、batchDel
等方法,在操做成功後,對current
進行從新計算。{ total: 11, current: 2, pageSize: 10 }
。{ total: 10, current: 1, pageSize: 10 }
,正常顯示第一頁的數據。更新計劃
菜單能方便你們瞭解到 JEECG團隊 對新版本的迭代方向,增長用戶粘度。
關於這個建議已經有 issue,相信在近期內就會看到這個菜單!
不少社區的朋友都有反應這個問題。確實,當咱們的業務代碼與 jeecg-boot 的源碼融合在一塊兒的時候,作版本升級是比較頭疼的。
特別是大版本的升級,除了源碼的變更,可能還有數據庫表的變動,升級會不會對咱們的業務產生影響,誰也說不清楚!
咱們的實踐方案:
依賴 jeecg-spring-boot-starter,解決業務代碼與 jeecg-boot 源碼融合的在一塊兒的窘境。
適用人羣
有興趣的同窗,能夠去 github 瞭解它 https://github.com/tanpenggood/jeecg-spring-boot-starter。
最後,但願 jeecg-boot 的代碼質量更加優秀,但願 jeecg-boot 成爲2020最最最最受歡迎的開源項目!