給開(kāi)源項(xiàng)目尤其是Spring這種知名度高的項(xiàng)目貢獻(xiàn)代碼是比較難的,起碼胖哥是這么認(rèn)為的。有些時(shí)候我們的靈感未必契合作者的設(shè)計(jì)意圖,即使你的代碼十分優(yōu)雅。
我曾經(jīng)給Spring Security提交了一個(gè)我認(rèn)為非常重要的一項(xiàng)優(yōu)化,和作者溝通了幾十個(gè)來(lái)回?zé)o法說(shuō)服他。人家說(shuō)留了抽象接口,你覺(jué)得不對(duì)自己實(shí)現(xiàn)一個(gè)就是了,默認(rèn)的就是能用而已,無(wú)奈我就放棄了這個(gè)PR。
想不到在Spring Authorization Server中我抓住了一個(gè)能夠絕對(duì)被接受的機(jī)會(huì),經(jīng)過(guò)一個(gè)多月的等待,最終我的PR被接受了。

我在編寫(xiě)Spring Authorization Server相關(guān)教程中,調(diào)用授權(quán)服務(wù)器元信息端點(diǎn)時(shí)不小心后面帶了個(gè)錨點(diǎn)符號(hào)#,類(lèi)似http://issuer.felord.cn/#,報(bào)了一個(gè)請(qǐng)求錯(cuò)誤,在追蹤源碼的時(shí)候我發(fā)現(xiàn)對(duì)這個(gè)url是進(jìn)行過(guò)校驗(yàn)的,出現(xiàn)了這種非預(yù)期的結(jié)果說(shuō)明規(guī)則一定有漏洞。于是我查閱了相關(guān)RFC的定義,找到了依據(jù)RFC8414。
這個(gè)規(guī)范的實(shí)現(xiàn)沒(méi)有什么技術(shù)含量,我如果告訴你,你也能做得到,甚至做得比我好,所以只要實(shí)現(xiàn)了,PR被接受應(yīng)該是跑不了的事情,甚至可以半場(chǎng)開(kāi)香檳。在0.3.0版本中這個(gè)優(yōu)化將會(huì)實(shí)裝。對(duì)這個(gè)過(guò)程,我簡(jiǎn)單總結(jié)了一下分享出來(lái) ,或許對(duì)希望參與開(kāi)源貢獻(xiàn)的你有所幫助。
代碼風(fēng)格
首先是代碼風(fēng)格,開(kāi)源項(xiàng)目都有一些代碼風(fēng)格要求,我之前有很多東西模仿(抄)了Spring的設(shè)計(jì),所以我在實(shí)現(xiàn)規(guī)范的時(shí)候特別注意了這一點(diǎn),命名風(fēng)格、縮進(jìn)等等都反復(fù)推敲。
理解項(xiàng)目的架構(gòu)思想
在整個(gè)PR過(guò)程中,我出現(xiàn)的問(wèn)題主要在這里。雖然我最初的實(shí)現(xiàn)執(zhí)行起來(lái)沒(méi)有問(wèn)題,完全在生命周期之內(nèi),但是顯然它的位置不是最佳。比如參數(shù)的校驗(yàn)?zāi)憧梢詫?xiě)在控制層,也可以寫(xiě)在服務(wù)層,結(jié)果一定是沒(méi)問(wèn)題的,但是過(guò)程可能有問(wèn)題。作者和我溝通了一番,表明了他的設(shè)計(jì)思路,很快我就糾正了這個(gè)問(wèn)題。
單元測(cè)試非常重要
實(shí)現(xiàn)代碼確實(shí)不多,單元測(cè)試的代碼幾乎超過(guò)了其20倍。我們平時(shí)寫(xiě)個(gè)main方法簡(jiǎn)單sout打印一下就完事了,對(duì)于開(kāi)源項(xiàng)目可不一樣。尤其是這種知名開(kāi)源框架,需要你測(cè)試實(shí)現(xiàn)的方方面面。如果你想為開(kāi)源項(xiàng)目貢獻(xiàn)代碼,常用的斷言、Mock插樁都要會(huì),這個(gè)胖哥的博客felord.cn都有相關(guān)的介紹。
Git規(guī)范
Git 提交規(guī)范胖哥也多次強(qiáng)調(diào)了它的重要性,在大型開(kāi)源項(xiàng)目中遵循一些提交規(guī)范也是一個(gè)基本要求。一些Pull Request的規(guī)則、代碼Review流程也要熟悉,這些功夫都在于平時(shí)。Git你得熟練。Spring要求最小功能提交,怎么說(shuō)呢?你的實(shí)現(xiàn)必須是一個(gè)最小粒度的完整單元,你不能在一個(gè)提交中既有增強(qiáng)優(yōu)化(enhance)還有新特性(feature)。而且你的提交必須壓縮到一個(gè)git commit內(nèi),即使被打回去修改。要多用
git commit --amend -m '你的提交信息'
在一些不得已的時(shí)候,git rebase和squash commits或許能幫到你。
但是千萬(wàn)不要去搞什么Git原理底層,把工具用熟練就夠了。
要善于發(fā)現(xiàn),敢做敢為
最重要的一點(diǎn),你要善于發(fā)現(xiàn),比如下面這個(gè)bug(現(xiàn)在還沒(méi)有徹底修復(fù)),如果我說(shuō)它是個(gè)bug,你一定會(huì)大吃一驚,我當(dāng)時(shí)也是一樣的。
public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
if (!filters.isEmpty()) {
logger.info(LogMessage.format("Will not secure %s", requestMatcher));
}
else {
logger.info(LogMessage.format("Will secure %s with %s", requestMatcher, filters));
}
this.requestMatcher = requestMatcher;
this.filters = new ArrayList<>(filters);
}
3.1版本的log邏輯居然錯(cuò)到5.6版本!而修復(fù)它只需要改下位置,這個(gè)bug我媽?xiě)?yīng)該也會(huì)改。但是沒(méi)有人發(fā)現(xiàn)和質(zhì)疑它,直到最近有人提交了修復(fù)(5.7版本會(huì)修復(fù)這個(gè)bug)。
所以你要善于發(fā)現(xiàn)一些問(wèn)題和細(xì)節(jié),同時(shí)也要敢于質(zhì)疑,即使質(zhì)疑錯(cuò)了又不會(huì)損失什么。
要有專(zhuān)長(zhǎng)
我和大家一樣,平常也是什么都學(xué),沒(méi)辦法!做原創(chuàng)技術(shù)博主太容易內(nèi)容焦慮了。但是我刻意保證了一些東西去深入學(xué)習(xí),有些東西必須成為你的獨(dú)門(mén)絕技,要一精多專(zhuān),這樣你在專(zhuān)長(zhǎng)的領(lǐng)域可能有更多的機(jī)會(huì)。
TODO
對(duì)于成為開(kāi)源貢獻(xiàn)者只是一個(gè)開(kāi)始,更多的挑戰(zhàn)還在后面。有人問(wèn)我最近為什么更文少了!這里也講一下我最近在做的事。
首先,因?yàn)橐咔槲冶桓綦x在家辦公了。
其次,還有幾個(gè)開(kāi)源貢獻(xiàn)正在進(jìn)行中。
還有,我正在做一個(gè)基于Spring Authorization Server的開(kāi)源項(xiàng)目Id Server,你可以認(rèn)為是一個(gè)極簡(jiǎn)版的keycloak,甚至最初的功能比較簡(jiǎn)陋,layui都是先學(xué)的,界面我也做不好。放個(gè)截圖吧。

做這個(gè)東西很有挑戰(zhàn),前端真是太難了!目前已經(jīng)初具雛形,不日將放出預(yù)覽版,也歡迎各位同學(xué)參與貢獻(xiàn)。
關(guān)注公眾號(hào):碼農(nóng)小胖哥,獲取更多資訊