2019.05.26 周日--【技術(shù)文章】《阿里巴巴 Java 開發(fā)手冊》精華摘要

一、寫在開頭

? ? Java作為一個編程界最流行的語言之一,有著很強(qiáng)的生命力。代碼的編寫規(guī)范也是不容忽視的择克,今天,我就把自己閱讀的國內(nèi)的互聯(lián)網(wǎng)巨頭阿里巴巴的《阿里巴巴 Java 開發(fā)手冊》一些精彩內(nèi)容摘錄如下前普。以饗讀者肚邢。《阿里巴巴Java開發(fā)手冊 終極版v1.3.0.pdf》 下載地址


《阿里巴巴Java開發(fā)手冊 終極版v1.3.0.pdf》?

二、精彩摘錄

? ??4.1)【命名風(fēng)格】


【01 強(qiáng)制】抽象類命名使用 Abstract 或 Base 開頭拭卿;異常類命名使用 Exception 結(jié)尾骡湖;測試類 命名以它要測試的類的名稱開始,以 Test 結(jié)尾峻厚。

?【02 強(qiáng)制】中括號是數(shù)組類型的一部分响蕴,數(shù)組定義如下:String[] args; 反例:使用 String args[]的方式來定義。

【03強(qiáng)制】POJO 類中布爾類型的變量惠桃,都不要加 is浦夷,否則部分框架解析會引起序列化錯誤。?

==反例:定義為基本數(shù)據(jù)類型 Boolean isDeleted辜王;的屬性劈狐,它的方法也是 isDeleted(), 框架在反向解析的時候呐馆,“以為”對應(yīng)的屬性名稱是 deleted肥缔,導(dǎo)致屬性獲取不到,進(jìn)而拋出異 常摹恰。

【04 強(qiáng)制】包名統(tǒng)一使用小寫辫继,點(diǎn)分隔符之間有且僅有一個自然語義的英語單詞。包名統(tǒng)一使用 單數(shù)形式俗慈,但是類名如果有復(fù)數(shù)含義,類名可以使用復(fù)數(shù)形式遣耍。 正例: 應(yīng)用工具類包名為 com.alibaba.open.util闺阱、類名為 MessageUtils(此規(guī)則參考 spring 的框架結(jié)構(gòu))

【05 推薦】如果模塊、接口舵变、類酣溃、方法使用了設(shè)計(jì)模式瘦穆,在命名時體現(xiàn)出具體模式

【06 推薦】接口類中的方法和屬性不要加任何修飾符號(public 也不要加),保持代碼的簡潔 性赊豌,并加上有效的 Javadoc 注釋扛或。盡量不要在接口里定義變量,如果一定要定義變量碘饼,肯定是 與接口方法相關(guān)熙兔,并且是整個應(yīng)用的基礎(chǔ)常量。 正例:接口方法簽名:void f(); 接口基礎(chǔ)常量表示:String COMPANY = "alibaba"; 反例:接口方法定義:public abstract void f(); 說明:JDK8 中接口允許有默認(rèn)實(shí)現(xiàn)艾恼,那么這個 default 方法住涉,是對所有實(shí)現(xiàn)類都有價(jià)值的默 認(rèn)實(shí)現(xiàn)。

【不是很理解--todo】接口和實(shí)現(xiàn)類的命名有兩套規(guī)則:

1)【強(qiáng)制】對于 Service 和 DAO 類钠绍,基于 SOA 的理念舆声,暴露出來的服務(wù)一定是接口,內(nèi)部 的實(shí)現(xiàn)類用 Impl 的后綴與接口區(qū)別柳爽。 正例:CacheServiceImpl 實(shí)現(xiàn) CacheService 接口媳握。?

2)【推薦】如果是形容能力的接口名稱,取對應(yīng)的形容詞做接口名(通常是–able 的形式)磷脯。 正例:AbstractTranslator 實(shí)現(xiàn) Translatable蛾找。

4.2)【常量定義】


【不是很理解--todo】【強(qiáng)制】不允許任何魔法值(即未經(jīng)定義的常量)直接出現(xiàn)在代碼中。 反例:String key = "Id#taobao_" + tradeId; cache.put(key, value);

4.3)【代碼格式】


【01 強(qiáng)制】大括號的使用約定争拐。如果是大括號內(nèi)為空腋粥,則簡潔地寫成{}即可,不需要換行架曹;如果 是非空代碼塊則: 1) 左大括號前不換行隘冲。 2) 左大括號后換行。 3) 右大括號前換行绑雄。 4) 右大括號后還有 else 等代碼則不換行展辞;表示終止的右大括號后必須換行。

?【02 強(qiáng)制】if/for/while/switch/do 等保留字與括號之間都必須加空格万牺。

?【03 強(qiáng)制】任何二目罗珍、三目運(yùn)算符的左右兩邊都需要加一個空格。 說明:運(yùn)算符包括賦值運(yùn)算符=脚粟、邏輯運(yùn)算符&&覆旱、加減乘除符號等。

【04 強(qiáng)制】注釋的雙斜線與注釋內(nèi)容之間有且僅有一個空格核无。 正例:// 注釋內(nèi)容扣唱,注意在//和注釋內(nèi)容之間有一個空格。

4.4)【OOP規(guī)約】


【01 強(qiáng)制】Object 的 equals 方法容易拋空指針異常,應(yīng)使用常量或確定有值的對象來調(diào)用 equals噪沙。?

==正例:"test".equals(object); 反例:object.equals("test"); 說明:推薦使用 java.util.Objects#equals(JDK7 引入的工具類)

【02 強(qiáng)制】所有的相同類型的包裝類對象之間值的比較炼彪,全部使用 equals 方法比較。

說明:對于 Integer var = ? 在-128 至 127 范圍內(nèi)的賦值正歼,Integer 對象是在 IntegerCache.cache 產(chǎn)生辐马,會復(fù)用已有對象,這個區(qū)間內(nèi)的 Integer 值可以直接使用==進(jìn)行 判斷局义,但是這個區(qū)間之外的所有數(shù)據(jù)喜爷,都會在堆上產(chǎn)生,并不會復(fù)用已有對象旭咽,這是一個大坑贞奋, 推薦使用 equals 方法進(jìn)行判斷。

關(guān)于基本數(shù)據(jù)類型與包裝數(shù)據(jù)類型的使用標(biāo)準(zhǔn)如下:?

1) 【強(qiáng)制】所有的 POJO 類屬性必須使用包裝數(shù)據(jù)類型穷绵。?

2) 【強(qiáng)制】RPC 方法的返回值和參數(shù)必須使用包裝數(shù)據(jù)類型轿塔。?

3) 【推薦】所有的局部變量使用基本數(shù)據(jù)類型。?

==說明:POJO 類屬性沒有初值是提醒使用者在需要使用時仲墨,必須自己顯式地進(jìn)行賦值勾缭,任何 NPE (即空指針異常)問題,或者入庫檢查目养,都由使用者來保證俩由。?

==正例:數(shù)據(jù)庫的查詢結(jié)果可能是 null,因?yàn)樽詣硬鹣浒┮希没緮?shù)據(jù)類型接收有 NPE 風(fēng)險(xiǎn)幻梯。?

==反例:比如顯示成交總額漲跌情況,即正負(fù) x%努释,x 為基本數(shù)據(jù)類型碘梢,調(diào)用的 RPC 服務(wù),調(diào)用 不成功時伐蒂,返回的是默認(rèn)值煞躬,頁面顯示為 0%,這是不合理的逸邦,應(yīng)該顯示成中劃線恩沛。所以包裝 數(shù)據(jù)類型的 null 值,能夠表示額外的信息缕减,如:遠(yuǎn)程調(diào)用失敗雷客,異常退出。

參考:Java中基本數(shù)據(jù)類型和包裝類

【03 強(qiáng)制】序列化類新增屬性時桥狡,請不要修改 serialVersionUID 字段佛纫,避免反序列失敿司帧飞蚓;如 果完全不兼容升級猪钮,避免反序列化混亂秘血,那么請修改 serialVersionUID 值。 說明:注意 serialVersionUID 不一致會拋出序列化運(yùn)行時異常甥啄。

【04 強(qiáng)制】POJO 類必須寫 toString 方法。使用 IDE 的中工具:source> generate toString 時炬搭,如果繼承了另一個 POJO 類蜈漓,注意在前面加一下 super.toString。 說明:在方法執(zhí)行拋出異常時宫盔,可以直接調(diào)用 POJO 的 toString()方法打印其屬性值融虽,便于排 查問題。

【05 推薦】當(dāng)一個類有多個構(gòu)造方法灼芭,或者多個同名方法有额,這些方法應(yīng)該按順序放置在一起, 便于閱讀彼绷,

【06 推薦】 類內(nèi)方法定義順序依次是:公有方法或保護(hù)方法 > 私有方法 > getter/setter 方法巍佑。

【07 推薦】循環(huán)體內(nèi),字符串的連接方式寄悯,使用 StringBuilder 的 append 方法進(jìn)行擴(kuò)展萤衰。?

==說明:反編譯出的字節(jié)碼文件顯示每次循環(huán)都會 new 出一個 StringBuilder 對象,然后進(jìn)行 append 操作猜旬,最后通過 toString 方法返回 String 對象脆栋,造成內(nèi)存資源浪費(fèi)。?

==反例: String str = "start"; for (int i = 0; i < 100; i++) { str = str + "hello"; }

【08 推薦】類成員與方法訪問控制從嚴(yán):?

1) 如果不允許外部直接通過 new 來創(chuàng)建對象洒擦,那么構(gòu)造方法必須是 private椿争。

2) 工具類不允許有 public 或 default 構(gòu)造方法。

3) 類非 static 成員變量并且與子類共享秘遏,必須是 protected丘薛。?

4) 類非 static 成員變量并且僅在本類使用,必須是 private邦危。

5) 類 static 成員變量如果僅在本類使用洋侨,必須是 private。

6) 若是 static 成員變量倦蚪,必須考慮是否為 final希坚。

7) 類成員方法只供類內(nèi)部調(diào)用,必須是 private陵且。?

8) 類成員方法只對繼承類公開裁僧,那么限制為 protected个束。?

==說明:任何類、方法聊疲、參數(shù)茬底、變量,嚴(yán)控訪問范圍获洲。過于寬泛的訪問范圍阱表,不利于模塊解耦。 思考:如果是一個 private 的方法贡珊,想刪除就刪除最爬,可是一個 public 的 service 方法,或者 一個 public 的成員變量门岔,刪除一下爱致,不得手心冒點(diǎn)汗嗎?變量像自己的小孩寒随,盡量在自己的 視線內(nèi)糠悯,變量作用域太大,無限制的到處跑牢裳,那么你會擔(dān)心的逢防。

4.5)【集合處理】


【01 強(qiáng)制】關(guān)于 hashCode 和 equals 的處理,遵循如下規(guī)則:

1) 只要重寫 equals蒲讯,就必須重寫 hashCode忘朝。

2) 因?yàn)?Set 存儲的是不重復(fù)的對象,依據(jù) hashCode 和 equals 進(jìn)行判斷判帮,所以 Set 存儲的 對象必須重寫這兩個方法局嘁。

3) 如果自定義對象做為 Map 的鍵,那么必須重寫 hashCode 和 equals晦墙。 說明:String 重寫了 hashCode 和 equals 方法悦昵,所以我們可以非常愉快地使用 String 對象 作為 key 來使用。

【02 強(qiáng)制】ArrayList的subList結(jié)果不可強(qiáng)轉(zhuǎn)成ArrayList晌畅,否則會拋出ClassCastException 異常但指,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList.?

==說明:subList 返回的是 ArrayList 的內(nèi)部類 SubList,并不是 ArrayList 抗楔,而是 ArrayList 的一個視圖棋凳,對于 SubList 子列表的所有操作最終會反映到原列表上。

== 例子:https://blog.csdn.net/qq_15118961/article/details/80893780

【03 強(qiáng)制】在 subList 場景中连躏,高度注意對原集合元素個數(shù)的修改剩岳,會導(dǎo)致子列表的遍歷、增加入热、 刪除均會產(chǎn)生 ConcurrentModificationException 異常拍棕。

【04 強(qiáng)制】使用集合轉(zhuǎn)數(shù)組的方法晓铆,必須使用集合的 toArray(T[] array),傳入的是類型完全 一樣的數(shù)組绰播,大小就是 list.size()骄噪。

【05 強(qiáng)制】使用工具類 Arrays.asList()把數(shù)組轉(zhuǎn)換成集合時,不能使用其修改集合相關(guān)的方 法幅垮,它的 add/remove/clear 方法會拋出 UnsupportedOperationException 異常腰池。

== 說明:asList 的返回對象是一個 Arrays 內(nèi)部類,并沒有實(shí)現(xiàn)集合的修改方法忙芒。Arrays.asList 體現(xiàn)的是適配器模式,只是轉(zhuǎn)換接口讳侨,后臺的數(shù)據(jù)仍是數(shù)組呵萨。?

==String[] str = new String[] { "you", "wu" }; List list = Arrays.asList(str); 第一種情況:list.add("yangguanbao"); 運(yùn)行時異常。 第二種情況:str[0] = "gujin"; 那么 list.get(0)也會隨之修改跨跨。

【06 強(qiáng)制】泛型通配符來接收返回的數(shù)據(jù)潮峦,此寫法的泛型集合不能使用 add 方 法,而不能使用 get 方法勇婴,做為接口調(diào)用賦值時易出錯忱嘹。?

==說明:擴(kuò)展說一下 PECS(Producer Extends Consumer Super)原則:第一、頻繁往外讀取內(nèi) 容的耕渴,適合用<? extends T>拘悦。第二、經(jīng)常往里插入的橱脸,適合用<? super T>础米。

【07 強(qiáng)制】c。remove 元素請使用 Iterator 方式添诉,如果并發(fā)操作屁桑,需要對 Iterator 對象加鎖。

【08 強(qiáng)制】 在 JDK7 版本及以上栏赴,Comparator 要滿足如下三個條件蘑斧,不然 Arrays.sort, Collections.sort 會報(bào) IllegalArgumentException 異常须眷。

== 說明:三個條件如下 1) x竖瘾,y 的比較結(jié)果和 y,x 的比較結(jié)果相反柒爸。 2) x>y准浴,y>z,則 x>z捎稚。 3) x=y乐横,則 x求橄,z 比較結(jié)果和 y,z 比較結(jié)果相同葡公。

== 參考資料:https://www.cnblogs.com/shizhijie/p/7657049.html?: JAVA Comparator 接口排序用法

【09 推薦】集合初始化時罐农,指定集合初始值大小。

==說明:HashMap 使用 HashMap(int initialCapacity) 初始化催什,?

==正例:initialCapacity = (需要存儲的元素個數(shù) / 負(fù)載因子) + 1涵亏。注意負(fù)載因子(即 loader factor)默認(rèn)為 0.75,如果暫時無法確定初始值大小蒲凶,請?jiān)O(shè)置為 16(即默認(rèn)值)气筋。

== 反例:HashMap 需要放置 1024 個元素,由于沒有設(shè)置容量初始大小旋圆,隨著元素不斷增加宠默,容 量 7 次被迫擴(kuò)大,resize 需要重建 hash 表灵巧,嚴(yán)重影響性能搀矫。

【10 推薦】使用 entrySet 遍歷 Map 類集合 KV,而不是 keySet 方式進(jìn)行遍歷刻肄。

==說明:keySet 其實(shí)是遍歷了 2 次瓤球,一次是轉(zhuǎn)為 Iterator 對象,另一次是從 hashMap 中取出 key 所對應(yīng)的 value敏弃。而 entrySet 只是遍歷了一次就把 key 和 value 都放到了 entry 中卦羡,效 率更高。如果是 JDK8权她,使用 Map.foreach 方法虹茶。 正例:values()返回的是 V 值集合,是一個 list 集合對象隅要;keySet()返回的是 K 值集合蝴罪,是 一個 Set 集合對象;entrySet()返回的是 K-V 值組合集合步清。

== 網(wǎng)絡(luò)例子:?https://blog.csdn.net/lisiben/article/details/84855030

【11 推薦】高度注意 Map 類集合 K/V 能不能存儲 null 值的情況要门,如下表格:

4.6)【集合處理】


【強(qiáng)制】獲取單例對象需要保證線程安全,其中的方法也要保證線程安全廓啊。 說明:資源驅(qū)動類欢搜、工具類、單例工廠類都需要注意谴轮。

4.7)【控制語句】


【01 強(qiáng)制】在一個 switch 塊內(nèi)炒瘟,每個 case 要么通過 break/return 等來終止,要么注釋說明程 序?qū)⒗^續(xù)執(zhí)行到哪一個 case 為止第步;在一個 switch 塊內(nèi)疮装,都必須包含一個 default 語句并且 放在最后缘琅,即使它什么代碼也沒有。

?【02 強(qiáng)制】在 if/else/for/while/do 語句中必須使用大括號廓推。即使只有一行代碼刷袍,避免采用 單行的編碼方式:if (condition) statements;

【03 推薦】表達(dá)異常的分支時,少用 if-else 方式樊展,這種方式可以改寫成: if (condition) { ... return obj; } // 接著寫 else 的業(yè)務(wù)邏輯代碼;

==正例:超過 3 層的 if-else 的邏輯判斷代碼可以使用衛(wèi)語句呻纹、策略模式、狀態(tài)模式等來實(shí)現(xiàn)专缠,

== 參考:?https://www.cnblogs.com/didiaoxiong/p/9125940.html

【04 推薦】循環(huán)體中的語句要考量性能雷酪,以下操作盡量移至循環(huán)體外處理,如定義對象藤肢、變量太闺、 獲取數(shù)據(jù)庫連接,進(jìn)行不必要的 try-catch 操作(這個 try-catch 是否可以移至循環(huán)體外)嘁圈。


4.8)【注釋規(guī)約】


【01 強(qiáng)制】類、類屬性蟀淮、類方法的注釋必須使用 Javadoc 規(guī)范最住,使用/**內(nèi)容*/格式,不得使用 // xxx 方式怠惶。

【02 強(qiáng)制】所有的類都必須添加創(chuàng)建者和創(chuàng)建日期涨缚。

【03 強(qiáng)制】方法內(nèi)部單行注釋,在被注釋語句上方另起一行策治,使用//注釋脓魏。方法內(nèi)部多行注釋 使用/* */注釋,注意與代碼對齊通惫。

【04 參考】特殊注釋標(biāo)記茂翔,請注明標(biāo)記人與標(biāo)記時間。注意及時處理這些標(biāo)記履腋,通過標(biāo)記掃描珊燎, 經(jīng)常清理此類標(biāo)記。線上故障有時候就是來源于這些標(biāo)記處的代碼遵湖。

== 1) 待辦事宜(TODO):( 標(biāo)記人悔政,標(biāo)記時間,[預(yù)計(jì)處理時間]) 表示需要實(shí)現(xiàn)延旧,但目前還未實(shí)現(xiàn)的功能谋国。這實(shí)際上是一個 Javadoc 的標(biāo)簽,目前的 Javadoc 還沒有實(shí)現(xiàn)迁沫,但已經(jīng)被廣泛使用芦瘾。只能應(yīng)用于類捌蚊,接口和方法(因?yàn)樗且粋€ Javadoc 標(biāo)簽)。

== 2) 錯誤旅急,不能工作(FIXME):(標(biāo)記人逢勾,標(biāo)記時間,[預(yù)計(jì)處理時間]) 在注釋中用 FIXME 標(biāo)記某代碼是錯誤的藐吮,而且不能工作溺拱,需要及時糾正的情況。

4.9)【其他】


【01 強(qiáng)制】后臺輸送給頁面的變量必須加$!{var}——中間的感嘆號谣辞。 說明:如果 var=null 或者不存在迫摔,那么${var}會直接顯示在頁面上。

【02 強(qiáng)制】注意 Math.random() 這個方法返回是 double 類型泥从,注意取值的范圍 0≤x<1(能夠 取到零值句占,注意除零異常),如果想獲取整數(shù)類型的隨機(jī)數(shù)躯嫉,不要將 x 放大 10 的若干倍然后 取整纱烘,直接使用 Random 對象的 nextInt 或者 nextLong 方法。

【03 強(qiáng)制】獲取當(dāng)前毫秒數(shù) System.currentTimeMillis(); 而不是 new Date().getTime(); 說明:如果想獲取更加精確的納秒級時間值祈餐,使用 System.nanoTime()的方式擂啥。在 JDK8 中, 針對統(tǒng)計(jì)時間等場景帆阳,推薦使用 Instant 類哺壶。

【04 推薦】任何數(shù)據(jù)結(jié)構(gòu)的構(gòu)造或初始化,都應(yīng)指定大小蜒谤,避免數(shù)據(jù)結(jié)構(gòu)無限增長吃光內(nèi)存山宾。

【05 推薦】及時清理不再使用的代碼段或配置信息。 說明:對于垃圾代碼或過時配置鳍徽,堅(jiān)決清理干凈资锰,避免程序過度臃腫,代碼冗余旬盯。

== 正例:對于暫時被注釋掉台妆,后續(xù)可能恢復(fù)使用的代碼片斷,在注釋代碼上方胖翰,統(tǒng)一規(guī)定使用三 個斜杠(///)來說明注釋掉代碼的理由接剩。


4.10)【異常處理】


【01 強(qiáng)制】對大段代碼進(jìn)行 try-catch,這是不負(fù)責(zé)任的表現(xiàn)萨咳。catch 時請分清穩(wěn)定代碼和非穩(wěn) 定代碼懊缺,穩(wěn)定代碼指的是無論如何不會出錯的代碼。對于非穩(wěn)定代碼的 catch 盡可能進(jìn)行區(qū)分 異常類型,再做對應(yīng)的異常處理鹃两。

【02 參考】在代碼中使用“拋異骋抛”還是“返回錯誤碼”,對于公司外的 http/api 開放接口必須 使用“錯誤碼”俊扳;而應(yīng)用內(nèi)部推薦異常拋出途蒋;跨應(yīng)用間 RPC 調(diào)用優(yōu)先考慮使用 Result 方式,封 裝 isSuccess()方法馋记、“錯誤碼”号坡、“錯誤簡短信息”。

== 說明:關(guān)于 RPC 方法返回方式使用 Result 方式的理由: 1)使用拋異常返回方式梯醒,調(diào)用方如果沒有捕獲到就會產(chǎn)生運(yùn)行時錯誤宽堆。 2)如果不加棧信息,只是 new 自定義異常茸习,加入自己的理解的 error message畜隶,對于調(diào)用 端解決問題的幫助不會太多。如果加了棧信息号胚,在頻繁調(diào)用出錯的情況下籽慢,數(shù)據(jù)序列化和傳輸 的性能損耗也是問題。


4.11)【日志規(guī)約】


【強(qiáng)制】應(yīng)用中不可直接使用日志系統(tǒng)(Log4j猫胁、Logback)中的 API嗡综,而應(yīng)依賴使用日志框架 SLF4J 中的 API,使用門面模式的日志框架杜漠,有利于維護(hù)和各個類的日志處理方式統(tǒng)一。

【推薦】謹(jǐn)慎地記錄日志察净。生產(chǎn)環(huán)境禁止輸出 debug 日志驾茴;有選擇地輸出 info 日志;如果使 用 warn 來記錄剛上線時的業(yè)務(wù)行為信息氢卡,一定要注意日志輸出量的問題锈至,避免把服務(wù)器磁盤 撐爆,并記得及時刪除這些觀察日志译秦。

4.12)【單元測試】


【01 強(qiáng)制】好的單元測試必須遵守 AIR 原則峡捡。 說明:單元測試在線上運(yùn)行時,感覺像空氣(AIR)一樣并不存在筑悴,但在測試質(zhì)量的保障上们拙, 卻是非常關(guān)鍵的。好的單元測試宏觀上來說阁吝,具有自動化砚婆、獨(dú)立性、可重復(fù)執(zhí)行的特點(diǎn)突勇。

? A:Automatic(自動化) ? I:Independent(獨(dú)立性) ? R:Repeatable(可重復(fù))

【02 強(qiáng)制】保持單元測試的獨(dú)立性装盯。為了保證單元測試穩(wěn)定可靠且便于維護(hù)坷虑,單元測試用例之間 決不能互相調(diào)用,也不能依賴執(zhí)行的先后次序埂奈。

== 反例:method2 需要依賴 method1 的執(zhí)行迄损,將執(zhí)行結(jié)果做為 method2 的輸入。

【03 強(qiáng)制】對于單元測試账磺,要保證測試粒度足夠小芹敌,有助于精確定位問題。單測粒度至多是類級 別绑谣,一般是方法級別党窜。

【04 推薦】單元測試的基本目標(biāo):語句覆蓋率達(dá)到 70%;核心模塊的語句覆蓋率和分支覆蓋率都 要達(dá)到 100%

【05 推薦】對于數(shù)據(jù)庫相關(guān)的查詢借宵,更新幌衣,刪除等操作,不能假設(shè)數(shù)據(jù)庫里的數(shù)據(jù)是存在的壤玫, 或者直接操作數(shù)據(jù)庫把數(shù)據(jù)插入進(jìn)去豁护,請使用程序插入或者導(dǎo)入數(shù)據(jù)的方式來準(zhǔn)備數(shù)據(jù)。

【06 推薦】單元測試作為一種質(zhì)量保障手段欲间,不建議項(xiàng)目發(fā)布后補(bǔ)充單元測試用例楚里,建議在項(xiàng) 目提測前完成單元測試。


4.13)【安全規(guī)約】


【01 強(qiáng)制】用戶請求傳入的任何參數(shù)必須做有效性驗(yàn)證猎贴。

== 說明:忽略參數(shù)校驗(yàn)可能導(dǎo)致:

? page size 過大導(dǎo)致內(nèi)存溢出

? 惡意 order by 導(dǎo)致數(shù)據(jù)庫慢查詢?

? 任意重定向?

? SQL 注入

? 反序列化注入?

? 正則輸入源串拒絕服務(wù) ReDoS?

==說明:Java 代碼用正則來驗(yàn)證客戶端的輸入班缎,有些正則寫法驗(yàn)證普通用戶輸入沒有問題, 但是如果攻擊人員使用的是特殊構(gòu)造的字符串來驗(yàn)證她渴,有可能導(dǎo)致死循環(huán)的結(jié)果达址。

【02 強(qiáng)制】在使用平臺資源,譬如短信趁耗、郵件沉唠、電話、下單苛败、支付满葛,必須實(shí)現(xiàn)正確的防重放限制, 如數(shù)量限制罢屈、疲勞度控制嘀韧、驗(yàn)證碼校驗(yàn),避免被濫刷儡遮、資損乳蛾。 說明:如注冊時發(fā)送驗(yàn)證碼到手機(jī),如果沒有限制次數(shù)和頻率,那么可以利用此功能騷擾到其 它用戶肃叶,并造成短信平臺資源浪費(fèi)蹂随。

【03 推薦】發(fā)貼、評論因惭、發(fā)送即時消息等用戶生成內(nèi)容的場景必須實(shí)現(xiàn)防刷岳锁、文本內(nèi)容違禁詞過 濾等風(fēng)控策略。

4.14)【MySQL數(shù)據(jù)庫】


【01 強(qiáng)制】主鍵索引名為 pk_字段名蹦魔;唯一索引名為 uk_字段名激率;普通索引名則為 idx_字段名。 說明:pk_ 即 primary key勿决;uk_ 即 unique key乒躺;idx_ 即 index 的簡稱。

【02 強(qiáng)制】小數(shù)類型為 decimal低缩,禁止使用 float 和 double嘉冒。

==說明:float 和 double 在存儲的時候,存在精度損失的問題咆繁,很可能在值的比較時讳推,得到不 正確的結(jié)果。如果存儲的數(shù)據(jù)范圍超過 decimal 的范圍玩般,建議將數(shù)據(jù)拆成整數(shù)和小數(shù)分開存儲银觅。

【03 強(qiáng)制】varchar 是可變長字符串,不預(yù)先分配存儲空間坏为,長度不要超過 5000究驴,如果存儲長 度大于此值,定義字段類型為 text匀伏,獨(dú)立出來一張表纳胧,用主鍵來對應(yīng),避免影響其它字段索 引效率帘撰。

【04 推薦】單表行數(shù)超過 500 萬行或者單表容量超過 2GB,才推薦進(jìn)行分庫分表万皿。 說明:如果預(yù)計(jì)三年后的數(shù)據(jù)量根本達(dá)不到這個級別摧找,請不要在創(chuàng)建表時就分庫分表。

【05 強(qiáng)制】業(yè)務(wù)上具有唯一特性的字段牢硅,即使是多個字段的組合蹬耘,也必須建成唯一索引。

== 說明:不要以為唯一索引影響了 insert 速度减余,這個速度損耗可以忽略综苔,但提高查找速度是明 顯的;另外,即使在應(yīng)用層做了非常完善的校驗(yàn)控制如筛,只要沒有唯一索引堡牡,根據(jù)?墨菲定律,必 然有臟數(shù)據(jù)產(chǎn)生杨刨。

【06 強(qiáng)制】在 varchar 字段上建立索引時晤柄,必須指定索引長度,沒必要對全字段建立索引妖胀,根據(jù) 實(shí)際文本區(qū)分度決定索引長度即可芥颈。 說明:索引的長度與區(qū)分度是一對矛盾體,一般對字符串類型數(shù)據(jù)赚抡,長度為 20 的索引爬坑,區(qū)分度會高達(dá) 90%以上,可以使用 count(distinct left(列名, 索引長度))/count(*)的區(qū)分度 來確定涂臣。

【07 推薦】如果有 order by 的場景盾计,請注意利用索引的有序性。order by 最后的字段是組合 索引的一部分肉康,并且放在索引組合順序的最后闯估,避免出現(xiàn) file_sort 的情況,影響查詢性能吼和。 正例:where a=? and b=? order by c; 索引:a_b_c 反例:索引中有范圍查找涨薪,那么索引有序性無法利用,如:WHERE a>10 ORDER BY b; 索引 a_b 無法排序炫乓。

【08 推薦】利用延遲關(guān)聯(lián)或者子查詢優(yōu)化超多分頁場景刚夺。

==說明:MySQL 并不是跳過 offset 行,而是取 offset+N 行末捣,然后返回放棄前 offset 行侠姑,返回 N 行,那當(dāng) offset 特別大的時候箩做,效率就非常的低下莽红,要么控制返回的總頁數(shù),要么對超過 特定閾值的頁數(shù)進(jìn)行 SQL 改寫邦邦。

==?正例:先快速定位需要獲取的 id 段安吁,然后再關(guān)聯(lián): SELECT a.* FROM 表 1 a, (select id from 表 1 where 條件 LIMIT 100000,20 ) b where?a.id=b.id

【09 推薦】建組合索引的時候,區(qū)分度最高的在最左邊燃辖。

==正例:如果 where a=? and b=? 鬼店,a 列的幾乎接近于唯一值,那么只需要單建 idx_a 索引即 可黔龟。

== 說明:存在非等號和等號混合判斷條件時妇智,在建索引時滥玷,請把等號條件的列前置。如:where a>? and b=? 那么即使 a 的區(qū)分度更高巍棱,也必須把 b 放在索引的最前列惑畴。

【10 推薦】防止因字段類型不同造成的隱式轉(zhuǎn)換,導(dǎo)致索引失效拉盾。

【11 參考】創(chuàng)建索引時避免有如下極端誤解: 1)寧濫勿缺桨菜。認(rèn)為一個查詢就需要建一個索引。 2)寧缺勿濫捉偏。認(rèn)為索引會消耗空間倒得、嚴(yán)重拖慢更新和新增速度。 3)抵制惟一索引夭禽。認(rèn)為業(yè)務(wù)的惟一性一律需要在應(yīng)用層通過“先查后插”方式解決

【12 強(qiáng)制】不要使用 count(列名)或 count(常量)來替代 count(*)霞掺,count(*)是 SQL92 定義的 標(biāo)準(zhǔn)統(tǒng)計(jì)行數(shù)的語法,跟數(shù)據(jù)庫無關(guān)讹躯,跟 NULL 和非 NULL 無關(guān)菩彬。 說明:count(*)會統(tǒng)計(jì)值為 NULL 的行,而 count(列名)不會統(tǒng)計(jì)此列為 NULL 值的行潮梯。

【13 強(qiáng)制】count(distinct col) 計(jì)算該列除 NULL 之外的不重復(fù)行數(shù)骗灶,注意 count(distinct col1, col2) 如果其中一列全為 NULL,那么即使另一列有不同的值秉馏,也返回為 0耙旦。

【14 強(qiáng)制】使用 ISNULL()來判斷是否為 NULL 值。?

==說明:NULL 與任何值的直接比較都為 NULL萝究。 1) NULL<>NULL 的返回結(jié)果是 NULL免都,而不是 false。 2) NULL=NULL 的返回結(jié)果是 NULL帆竹,而不是 true绕娘。 3) NULL<>1 的返回結(jié)果是 NULL,而不是 true栽连。

【15 參考】TRUNCATE TABLE 比 DELETE 速度快险领,且使用的系統(tǒng)和事務(wù)日志資源少,但 TRUNCATE 無事務(wù)且不觸發(fā) trigger秒紧,有可能造成事故舷暮,故不建議在開發(fā)代碼中使用此語句。?說明:TRUNCATE TABLE 在功能上與不帶 WHERE 子句的 DELETE 語句相同噩茄。


4.15)【ORM映射】


【01 推薦】不要寫一個大而全的數(shù)據(jù)更新接口。傳入為 POJO 類复颈,不管是不是自己的目標(biāo)更新字 段绩聘,都進(jìn)行 update table setc1=value1,c2=value2,c3=value3; 這是不對的沥割。執(zhí)行 SQL 時,不要更新無改動的字段凿菩,一是易出錯机杜;二是效率低;三是增加 binlog 存儲衅谷。

【02 參考】中的 compareValue 是與屬性值對比的常量椒拗,一般是數(shù)字,表示相等時帶 上此條件获黔;表示不為空且不為 null 時執(zhí)行蚀苛;表示不為 null 值時 執(zhí)行。?

三玷氏、番外--Git的使用

? ? 【01 常見Git命令】 ? ?


#【001】

統(tǒng)一概念:工作區(qū):改動(增刪文件和內(nèi)容)

暫存區(qū):輸入命令:git add 改動的文件名堵未,此次改動就放到了 ‘暫存區(qū)’

本地倉庫(簡稱:本地):輸入命令:git commit 此次修改的描述,此次改動就放到了 ’本地倉庫’盏触,每個 commit渗蟹,我叫它為一個 ‘版本’。

遠(yuǎn)程倉庫(簡稱:遠(yuǎn)程):輸入命令:git push 遠(yuǎn)程倉庫赞辩,此次改動就放到了 ‘遠(yuǎn)程倉庫’(GitHub 等)

commit-id:輸出命令:git log雌芽,最上面那行 commit xxxxxx,后面的字符串就是 commit-id

#【002】

#編輯修改等

git show # 顯示某次提交的內(nèi)容 git show $id

git checkout <file-name> #放棄工作區(qū)的修改 辨嗽,類似于 svn revert

git revert <commit-id> #以新增一個 commit 的方式還原某一個 commit 的修改

#比較diff

git diff <branch1>..<branch2> # 在兩個分支之間比較

git diff --staged # 比較暫存區(qū)和版本庫差異

git diff --cached # 比較暫存區(qū)和版本庫差異

git whatchanged --since='2 weeks ago' #查看兩個星期內(nèi)的改動

git diff --word-diff #詳細(xì)展示一行中的修改

#查看提交記錄

git log -p -2 # 查看最近兩次詳細(xì)修改內(nèi)容的diff

git blame <file-name> #查看某段代碼是誰寫的, blame 的意思為‘責(zé)怪’世落,你懂的。

git reflog #顯示本地更新過 HEAD 的 git 命令記錄 ,類似 shell的 history

git log --all --grep='<given-text>' #在 commit log 中查找相關(guān)內(nèi)容

#Git 本地分支管理

git branch -r # 查看遠(yuǎn)程分支

git branch <new_branch> # 創(chuàng)建新的分支

git co <branch> # 切換到某個分支

git co $id # 把某次歷史提交記錄checkout出來召庞,但無分支信息岛心,切換到其他分支會自動刪除

git branch -d <branch> # 刪除某個分支

git branch -vv 展示本地分支關(guān)聯(lián)遠(yuǎn)程倉庫的情況

git merge <branch> # 將branch分支合并到當(dāng)前分支

#Git暫存管理

git stash # 暫存

git stash list # 列所有stash

git stash apply # 恢復(fù)暫存的內(nèi)容

git stash drop # 刪除暫存區(qū)

#Git遠(yuǎn)程分支管理

git pull --no-ff # 抓取遠(yuǎn)程倉庫所有分支更新并合并到本地,不要快進(jìn)合并

git push # push所有分支-- 要慎用篮灼,還是要push具體的分支好一點(diǎn) https://www.cnblogs.com/djiankuo/p/6492533.html

git push -u origin develop # 首次將本地develop分支提交到遠(yuǎn)程develop分支忘古,并且track

git push origin master # 將本地主分支推到遠(yuǎn)程主分支

git push origin dev_20190513_registrationpath #我們的java項(xiàng)目 數(shù)據(jù)統(tǒng)計(jì)的Git push命令

#Git遠(yuǎn)程倉庫管理

git remote -v # 查看遠(yuǎn)程服務(wù)器地址和倉庫名稱

git remote show origin # 查看遠(yuǎn)程服務(wù)器倉庫狀態(tài)

【02 】本地倉庫“三棵樹” ? ?


本地倉庫由 git 維護(hù)的三棵“樹”組成。

1)【圖01】本地倉庫git 三棵樹

本地倉庫git 三棵樹

2)【圖02】git本地三棵樹的相互轉(zhuǎn)化命令:https://josh-persistence.iteye.com/blog/2215214


git本地三棵樹的相互轉(zhuǎn)化命令

3)三棵樹的更詳細(xì)的命令示意圖

三棵樹的更詳細(xì)的命令示意圖


git commit的時候诅诱,只是提交的 緩存區(qū)內(nèi)的內(nèi)容(如果你git add過髓堪,否則也等同你本地工作區(qū)內(nèi)容的提交)

== git add可以實(shí)現(xiàn)我之前在 云主機(jī)上保存臨時文件的tmpdjp的操作

==git diff 對比的是工作區(qū)和 緩存區(qū)的區(qū)別

==git diff --cached 對比是 緩沖區(qū)和本地的 head版本庫的對比

另外需要指出來的是 git stash 不在上面的“三顆樹”里,git stash 是暫存區(qū)娘荡,區(qū)別于 緩存區(qū)“stage”?

git stash的用法見?https://www.cnblogs.com/tocy/p/git-stash-reference.html

四干旁、寫在最后

? ? 簡單的摘錄,見仁見智炮沐,希望喜歡Java開發(fā)的同學(xué)能從中收益争群。

????歡迎關(guān)注我的微信公眾號哈 “ 程序員的文娛情懷” http://t.cn/RotyZtu ??

歡迎關(guān)注我的微信公眾號哈 “ 程序員的文娛情懷”
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市大年,隨后出現(xiàn)的幾起案子换薄,更是在濱河造成了極大的恐慌玉雾,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轻要,死亡現(xiàn)場離奇詭異复旬,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)冲泥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門驹碍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凡恍,你說我怎么就攤上這事志秃。” “怎么了咳焚?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵洽损,是天一觀的道長。 經(jīng)常有香客問我革半,道長碑定,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任又官,我火速辦了婚禮延刘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘六敬。我一直安慰自己碘赖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布外构。 她就那樣靜靜地躺著普泡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪审编。 梳的紋絲不亂的頭發(fā)上撼班,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機(jī)與錄音垒酬,去河邊找鬼砰嘁。 笑死,一個胖子當(dāng)著我的面吹牛勘究,可吹牛的內(nèi)容都是我干的矮湘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼口糕,長吁一口氣:“原來是場噩夢啊……” “哼缅阳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起景描,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤十办,失蹤者是張志新(化名)和其女友劉穎孤里,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體橘洞,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年说搅,在試婚紗的時候發(fā)現(xiàn)自己被綠了炸枣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡弄唧,死狀恐怖适肠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情候引,我是刑警寧澤侯养,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站澄干,受9級特大地震影響逛揩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜麸俘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一辩稽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧从媚,春花似錦宫纬、人聲如沸年枕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽剃允。三九已至,卻和暖如春结笨,著一層夾襖步出監(jiān)牢的瞬間签夭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工稻励, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留父阻,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓望抽,卻偏偏與公主長得像加矛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子煤篙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容