貼一份我之前整理的 JAVA開發規范:
JAVA開發規范
luo@leader.cn
代碼整體風格
- Controller類,不要直接使用Map,HttpServletRequest request,HttpServletResponse response 作為參數,不要使用 Servlet API的接口
- 一個service類不應該引用其他service類,但是可以引用多個dao層對象
- mapper類應該盡量輕量級,不要過多的自定義sql
- 使用BeanUtil,而不是setXxx(info.getXxx)
- 避免重復代碼,代碼段出現過3次,一定要提取更多的公共代碼到基礎層, 比如mint
- 方法不超過200行,一個類不超過1000
- 看到丑陋代碼, 重構它!時不時 重構!
- 使用設計模式!
- 代碼要 提高 復用, 但是不能復制,復制一時爽,但是並不能提高 復用性!~
- 對自己做的模塊負責, 對其業務邏輯要一清二楚! 否則就 不合格~@!
- 面向對象編程,更重要的是 面向接口
- 同一個含義的枚舉, 全局應該只出現一次,而不是每個模塊一次, 否則改起來還是很麻煩!避免枚舉類泛濫
- 不要動不動就mq,避免消息泛濫
- 不超過3層 if else
- 專業術語的 英文名字要統一,簡寫也要統一
- 一般情況下,方法簽名不要拋出異常,除非涉及資源的工具類 !
- 不應該使用 硬編碼
- 提高 內聚, 降低耦合! 不要一個Service就一個方法, 不要引用太多其他的Service, 分得太散了就會 導致 太松散,內聚性太差! 看代碼,調試都會很痛苦!
- 杜絕代碼壞味道!啰嗦 / 低級 / 重復代碼, 一概拒絕!
- 能夠提取的, 一定要提取到公共位置, 杜絕 復制黏貼, 杜絕丑陋代碼!
- 代碼保持簡單,靈活,復用性,獨立,高內聚,低耦合
- 每個方法要 邏輯十分清晰, 一目了然
- 代碼應該清晰可讀,盡量保持簡單易讀
- 統一的code style
- 不要為了 微服務而 微服務 !
大家使用統一的規范,方便交流,減少維護成本
服務分層、命名規范
服務名\服務名-api\src\main\java\com\wisdom\服務名\
service 所有的服務接口,統一前綴為I,后綴為 Service
子模塊名x
IXxxService
子模塊名y
IXxxService
IMainXxx1Service 不要出現 XxxParam、 XxxSearch
IMainXxx2Service
IMainXxx3Service
bank other service
dto 所有的前后端交互對象,統一后綴為 DTO
exception 所有的自定義異常,應該繼承於運行時異常,統一后綴為Exception
服務名\服務名-provider\src\main\java\com\wisdom\服務名\
common 所有全局的共享東西:所有的常量、枚舉、靜態類,包括各種工具類,redis、mq訪問工具類
Constants 當前服務共用的常量類
XxxUtil 當前服務共用的工具類
XxxBaseService 當前服務共用的服務類
XxxRedisUtil 當前服務共用的redis工具類
XxxRabbitMqUtil 當前服務共用的mq工具類
XxxConfig 示例:com.wisdom.jasmine.mvc.CheckLoginInterceptor
XxxHandler 示例:com.wisdom.jasmine.mvc.GlobalExceptionHandler
XxxException 特有的異常類
service 處理業務邏輯,所有的服務接口實現類,統一后綴為 ServiceImpl,如有必要,下面還可以創建一層package,表明子模塊名,但是package不宜太深
子模塊名x
XxxServiceImpl
子模塊名y
YyyServiceImpl
MainXxx1ServiceImpl
MainXxx2ServiceImpl
MainXxx3ServiceImpl
mapper 所有的數據庫訪問類,統一后綴為Mapper
XxxMapper
YyyMapper 只有復雜的 查詢sql, 不應該有修改、新增、刪除sql
model 所有的數據庫實體映射類,統一后綴為Model
XxxModel
YyyModel
message 后端和mq 交互的pojo,盡量少使用,應該使用DTO
Web層就是controller層,直接前端對接項目,服務名一定要有一個 web 后綴
服務名\服務名-web\src\main\java\com\wisdom\服務名\
controller 處理視圖,所有的Controller類,統一后綴為 Controller
XxxController
api 服務的dto,provider服務的model 應該不相同,否則考慮是否服務沒定義 / 划分好。
每個表對應一個model,一個mapper。但不需要每一個model 一個service,比如一些關聯表的查詢/新增/修改/刪除操作,直接在主表對於的service完成。
每個service應該有對應的一個主表。但有時候也可能有多個。
一般情況下,service和mapper和model和數據庫表 同名。
XxxParam、 XxxSearch、XxxMessage 不能忘文知義,增加溝通成本,而且轉換起來很麻煩。
為什么Service層不能調用其它Service?
比較清晰的單向關聯:
N向關聯(可能存在循環依賴):
一般命名規范
Controller層 |
Service層 |
DAO層 |
|
query/page |
getOne |
selectOne |
獲取單個實體,參數就是實體本身 |
getByYyy |
selectById |
按照ID獲取單個實體 |
|
list Page
|
selectByXxx |
按照某條件獲取單個實體,參數就是實體某個字段 |
|
|
按照某條件,獲取實體的list集合 |
||
listAll |
selectAll |
返回所有行 |
|
add |
add |
insert |
新增單個實體。不存在 insertByXxx 方法 |
modify |
modify |
update |
更新單個實體 |
updateByXxx |
這個情況少見, 一般是通過id 進行更新 |
||
save |
save |
|
新增或修改, 不需要saveOrUpdate 方法名 |
業務方法 |
相同 業務方法 |
相同或不需要 |
|
Service 層:
list獲取實體的list集合
page 分頁查詢,統一返回, PageInfo<實體Model>
數據流轉:
數據庫層命名規范
字段使用要統一, state、status、 統一 status
表: 表的業務含義應該清晰明確, 不宜使用過多字段。< 30 ..
princ inter
不要這樣引起誤會的縮寫,
要么就不使用縮寫,而是全寫,要么使用通用的縮寫,
pom 規范
pom 提取公共配置 commons
使用最少的dependency,盡量從parent中繼承
依賴應該盡量簡化
需要仔細考慮每一個dependency 是否是必須的
注釋規范
每個類寫明 用途、注釋、作者、關聯
每次修改 寫明原因、作者、時間
/**
* 這個類是為了做什么,主要用途是abc
*
* @author LK(lk@qq.com)
* @Time 2018-12-29
*/
javadoc 注釋標簽語法
@author 對類的說明 標明開發該類模塊的作者
@version 對類的說明 標明該類模塊的版本
@see 對類、屬性、方法的說明 參考轉向,也就是相關主題
@param 對方法的說明 對方法中某參數的說明
@return 對方法的說明 對方法返回值的說明
@exception 對方法的說明 對方法可能拋出的異常進行說明
日志規范
理解和使用 debug、info、warn、error 各個級別,一般日志使用info基本,捕捉到錯誤如果要記錄異常,必須使用 error 級別。
異常處理規范
- Controller 做主要的參數檢驗,空指針檢查。不做具體的異常處理, 異常處理統一到MVC的ExceptionHandler
- Service層捕捉所有的已知異常(受檢異常),對系統異常封裝返回,對業務異常返回錯誤碼和錯誤信息,空指針檢查。(處理已知異常,運行時異常不用管)
- dao/mapper 不捕捉異常
盡量不要try catch(Exception e) 這個由統一的MVC的ExceptionHandler 來做
不合理的示例
mapper.AttachmentMapper#deleteAttachmentByObject 方法是不是可以簡化為 delete ?
mapper.AttachmentMapper#queryByObject queryByObject -> query
provider.RepayOverdueProvider#insertOrUpdateCommit 奇怪的命名
provider.CreditorAdvanceProvider provider 是什么? service 還是Dao?
lock.LockKeys lock 一個package 只有一個類, 是不是放到 constants 更好?
invite.enums.QueryDateTypeEnum enums 是不是放到 constants 更好?
invite.utils.ActivityInviteUtil 不需要單獨建立util 包
product.utils.UploadUtils UploadUtils 並不是 product 才有的一個工具類
product.service.impl.ProductServiceImpl provider 服務 使用service 還是 service.impl ? 至少應該是統一
domain.custom.CollectionCalendarView
search.CreditorAdvanceSearch
com.wisdom.daffodil.model.bank.BindCardReq 不要搞特殊化,統一使用DTO就好
阿里巴巴規范
【強制】POJO 類中布爾類型的變量,都不要加 is ,否則部分框架解析會引起序列化錯誤。
【強制】不要使用一個常量類維護所有常量,應該按常量功能進行歸類,分開維護
【強制】所有的覆寫方法,必須加@ Override 注解。
【強制】所有的相同類型的包裝類對象之間值的比較,全部使用 equals 方法比較。
【強制】關於基本數據類型與包裝數據類型的使用標准如下:
1 ) 所有的 POJO 類屬性必須使用包裝數據類型。
2 ) RPC 方法的返回值和參數必須使用包裝數據類型。
3 ) 所有的局部變量【推薦】使用基本數據類型。
【強制】定義 DO / DTO / VO 等 POJO 類時,不要設定任何屬性默認值。
【強制】 POJO 類必須寫 toString 方法。使用 IDE 的中工具: source > generate ,toString時,如果繼承了另一個 POJO 類,注意在前面加一下 super.toString 。
【強制】關於 hashCode 和 equals 的處理,遵循如下規則:
1) 只要重寫 equals ,就必須重寫 hashCode 。
2) 因為 Set 存儲的是不重復的對象,依據 hashCode 和 equals 進行判斷,所以 Set 存儲的對象必須重寫這兩個方法。
3) 如果自定義對象做為 Map 的鍵,那么必須重寫 hashCode 和 equals 。
【強制】 ArrayList 的 subList 結果不可強轉成 ArrayList , 否則會拋出 ClassCastException異常: java . util . RandomAccessSubList cannot be cast to java . util . ArrayList ;
【強制】 在 subList 場景中,高度注意對原集合元素個數的修改,會導致子列表的遍歷、增加、刪除均產生 ConcurrentModificationException 異常。
【強制】使用工具類 Arrays . asList() 把數組轉換成集合時,不能使用其修改集合相關的方法,它的 add / remove / clear 方法會拋出UnsupportedOperationException 異常。
【強制】線程資源必須通過線程池提供,不允許在應用中自行顯式創建線程。
【強制】線程池不允許使用 Executors 去創建,而是通過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同學更加明確線程池的運行規則,規避資源耗盡的風險。
【強制】 SimpleDateFormat 是線程不安全的類,一般不要定義為 static 變量,如果定義為
static ,必須加鎖,或者使用 DateUtils 工具類。
【強制】對多個資源、數據庫表、對象同時加鎖時,需要保持一致的加鎖順序,否則可能會造成死鎖。
【強制】多線程並行處理定時任務時, Timer 運行多個 TimeTask 時,只要其中之一沒有捕獲拋出的異常,其它任務便會自動終止運行,使用 ScheduledExecutorService 則沒有這個問題。
【強制】在一個 switch 塊內,每個 case 要么通過 break / return 等來終止,要么注釋說明程序將繼續執行到哪一個 case 為止 ; 在一個 switch 塊內,都必須包含一個 default 語句並且放在最后,即使它什么代碼也沒有。
【強制】不要捕獲 Java 類庫中定義的繼承自 RuntimeException 的運行時異常類,如:
IndexOutOfBoundsException / NullPointerException,這類異常由程序員預檢查
來規避,保證程序健壯性。
【強制】異常不要用來做流程控制,條件控制,因為異常的處理效率比條件分支低。
【強制】對大段代碼進行try-catch,這是不負責任的表現。catch時請分清穩定代碼和非穩定代碼,穩定代碼指的是無論如何不會出錯的代碼。對於非穩定代碼的catch盡可能進行區分異常類型,再做對應的異常處理。
【強制】捕獲異常是為了處理它,不要捕獲了卻什么都不處理而拋棄之,如果不想處理它,請將該異常拋給它的調用者。最外層的業務使用者,必須處理異常,將其轉化為用戶可以理解的內容。
【參考】在代碼中使用“拋異常”還是“返回錯誤碼”,對於公司外的http/api開放接口必須使用“錯誤碼”;而應用內部推薦異常拋出;跨應用間RPC調用優先考慮使用Result方式,封裝isSuccess()方法、“錯誤碼”、“錯誤簡短信息”。
文件是:
https://files.cnblogs.com/files/FlyAway2013/2018-JAVA%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83.rar