基于SpringBoot的WebAPI開發(fā)框架(二)

上文
d1.framework.webapi 庫(kù)是基礎(chǔ)封裝炭序,每個(gè) webapi 項(xiàng)目都必須使用,里面包含功能很多粘室。

1. BaseApplication

所有業(yè)務(wù)項(xiàng)目的主入口 Application 類都需繼承此類

@SpringBootApplication
public class DemoApplication extends BaseApplication{

}

這個(gè)類主要是增加幾個(gè)缺省注解,比如激活 Swagger圣蝎,確保對(duì)包進(jìn)行掃描是從 d1 開始触幼。

所以約定我們所有的業(yè)務(wù)項(xiàng)目的 package 都是 d1 開頭,比如d1.project.xxxx

@EnableSwagger2
@ComponentScan("d1")
@EntityScan("d1")
@EnableJpaRepositories("d1")
public class BaseApplication {
}
2. 封裝 webapi 接口的返回 Result

所有 controller 返回的值都是一個(gè) Result 對(duì)象瞳抓,基本結(jié)構(gòu)是

{
    "code": 1,
    "msg": "返回的消息,通常是字符串",
    "data": "返回的數(shù)據(jù),通常又是一個(gè)json對(duì)象"
}

使用方式:

return ResultUtil.result(10001,"自定義的消息",數(shù)據(jù)對(duì)象);
return ResultUtil.fail("自定義的消息",數(shù)據(jù)對(duì)象);
return ResultUtil.success("自定義的消息",數(shù)據(jù)對(duì)象);
3. ControllerAdvice

利用注解 @ControllerAdvice 實(shí)現(xiàn)統(tǒng)一攔截處理所有 controller 沒(méi)有 catch 的錯(cuò)誤

@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public Result all(Exception e) {
  return ResultUtil.result(ResultCode.UN_CATCH_ERROR.code, e.getMessage(), e);
}
4. 封裝Swagger自動(dòng)生成API文檔

只需要在 application.properties 配置文件里添加以下幾個(gè)配置伏恐,業(yè)務(wù)項(xiàng)目的 API 文檔就可以自動(dòng)生成并以服務(wù)的方式來(lái)訪問(wèn)孩哑,訪問(wèn)的url是http://域名或地址/swagger-ui.html#/

#application.properties
d1.framework.webapi.swagger.enable=true #生產(chǎn)環(huán)境下通常改成false
d1.framework.webapi.swagger.title=項(xiàng)目的標(biāo)題
d1.framework.webapi.swagger.desc=項(xiàng)目的描述
d1.framework.webapi.swagger.version=項(xiàng)目API的版本
d1.framework.webapi.swagger.host=www.xxxx.com:8089

在 contorller 里使用注解標(biāo)記 API 的方法參考文檔

4. 跨域設(shè)置

只需要在 application.properties 配置文件里添加以下配置,業(yè)務(wù)項(xiàng)目的前端頁(yè)面可以實(shí)現(xiàn)跨域訪問(wèn)翠桦,當(dāng)然生產(chǎn)環(huán)境的時(shí)候需要嚴(yán)格控制可跨域的域名横蜒。

#application.properties
#生成環(huán)境需要把*換成真實(shí)的域名胳蛮,多個(gè)域名可以用逗號(hào)隔開
d1.framework.webapi.cors=*
5. BaseEntity

這是所有 Entity 的基類,主要是強(qiáng)行設(shè)置一個(gè)字段叫 Id丛晌,這個(gè) Id 缺省是32位 uuid仅炊,在業(yè)務(wù)系統(tǒng)上建議所有 entity 都繼承它。

6. User相關(guān)封裝

DoUserBaseEntity 定義了用戶表的常用字段澎蛛,業(yè)務(wù)系統(tǒng)直接繼承做一些擴(kuò)展就可以了抚垄。
DoUserServiceImplBase 實(shí)現(xiàn)用戶相關(guān)的 service,主要是創(chuàng)建 token谋逻,登錄驗(yàn)證 token呆馁,缺省 token 都是用 d1.framework.cache 來(lái)緩存。

7. Auth相關(guān)

這里也是基于團(tuán)隊(duì)內(nèi)部的一個(gè)約定毁兆,所有 webapi 接口如果需要驗(yàn)證權(quán)限浙滤,都需要在 http 請(qǐng)求的 header 里設(shè)置 Authorization 屬性,屬性的值有2種情況:
Authorization = token xxxxxxx 表示是通過(guò)用戶登錄后返回的 token 來(lái)驗(yàn)證
Authorization = sign xxxxxxx 表示服務(wù)間通過(guò) HMAC 簽名來(lái)校驗(yàn)

定義AuthFilter(繼承Filter)來(lái)驗(yàn)證用戶的請(qǐng)求Header里的Authoriztion對(duì)應(yīng)的值如果是token的話气堕,從d1.framework.cache里對(duì)應(yīng)的緩存里查詢token是否存在并是否沒(méi)有過(guò)期纺腊。
另外通過(guò)定義一個(gè)自定義的注解Auth來(lái)設(shè)定web api接口是屬于某種特定的用戶。

@Auth("webadmin")
@RestController
@RequestMapping("/webadmin/user")
@Api(value = "/webadmin/user", description = "管理用戶管理")
public class WebAdminUserController extends DoBaseController<WebAdminUser> {
......
}

@Auth("webadmin")標(biāo)識(shí)這個(gè)controller里所有方法都必須是webadmin用戶登錄后才可以訪問(wèn)茎芭,這個(gè)注解也可以單獨(dú)給特定方法使用

8. DestroyEhcacheBean

JVM 退出時(shí)先 shutdown ehcache摹菠,確保內(nèi)存里的 cache 內(nèi)容正確寫入本地文件

public class DestroyEhcacheBean implements DisposableBean, ExitCodeGenerator {
    ......
    @Override
    public void destroy() throws Exception {
        if (cache != null)
            cache.shutDown();
    }
}
9. DoServiceImpBase

包含 service 常用方法,其它 service 都繼承這個(gè)方法,里面主要包括基本的增刪改查骗爆,這是一個(gè) abstract 方法,最主要是需要子類繼承的時(shí)候返回一個(gè)實(shí)際的 dao 類蔽介。
這個(gè)基類還實(shí)現(xiàn)了根據(jù) token 查詢對(duì)應(yīng)的用戶對(duì)象摘投。

public abstract class DoServiceImpBase<T> {
......
    protected abstract JpaRepository<T, String> getDao();
......
}
10. DoBaseController類

controller 基類,封裝了最基本的增刪改查虹蓄,子類只需要繼承犀呼,常見的接口都已定義。

11. 日志

在項(xiàng)目的resource下有一個(gè) logback.xml薇组,沒(méi)有特殊的需求的話外臂,所有業(yè)務(wù)系統(tǒng)都可以用這個(gè)默認(rèn)的日志配置。
另外定義了一個(gè) LoggerController 實(shí)現(xiàn)通過(guò) webapi 接口查看日志和下載日志文件律胀,這樣遠(yuǎn)程就可以查看日志宋光。

12. HMACSignService

添加HMAC校驗(yàn)簽名的基類service, 實(shí)現(xiàn)了服務(wù)間HMAC接口驗(yàn)證方式,規(guī)則參考微信的服務(wù)校驗(yàn)

13. SignInRetryLimitService

封裝用戶登錄重試次數(shù)校驗(yàn)炭菌,超過(guò)一定次數(shù)將被鎖住不能再試了罪佳。
需要在application.properties里添加2個(gè)配置:

#登錄密碼錯(cuò)誤重試的次數(shù),沒(méi)有這個(gè)值或值為0表示不限制
d1.framework.webapi.sign-in.retry-count=5
#登錄密碼錯(cuò)誤重試到一定次數(shù)后黑低,鎖住用戶一段時(shí)間赘艳,單位是分鐘
d1.framework.webapi.sign-in.lock-period=60

使用這個(gè)服務(wù)通過(guò)3個(gè)函數(shù):

if (user == null) throw new Exception("用戶:" + username + "不存在");
if (retryService.verifyIsLocked(username)) throw new Exception("用戶重試錯(cuò)誤密碼多次,導(dǎo)致用戶被鎖");
if (!user.getPassword().equals(password)) {
    retryService.signInWithWrongPwd(username);
    throw new Exception("密碼不對(duì)");
}
retryService.signInSuccess(username);

以上是 d1.framework.webapi 的基本功能,很多功能都是在開發(fā)實(shí)際項(xiàng)目的過(guò)程中逐漸添加上去的蕾管,包含的功能是雜七雜八的需求枷踏。
其它庫(kù)都是針對(duì)特定的功能,這里不一一詳述了掰曾。大家可以參考github旭蠕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市婴梧,隨后出現(xiàn)的幾起案子下梢,更是在濱河造成了極大的恐慌,老刑警劉巖塞蹭,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孽江,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡番电,警方通過(guò)查閱死者的電腦和手機(jī)岗屏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)漱办,“玉大人这刷,你說(shuō)我怎么就攤上這事∶渚” “怎么了暇屋?”我有些...
    開封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)洞辣。 經(jīng)常有香客問(wèn)我咐刨,道長(zhǎng),這世上最難降的妖魔是什么扬霜? 我笑而不...
    開封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任定鸟,我火速辦了婚禮,結(jié)果婚禮上著瓶,老公的妹妹穿的比我還像新娘联予。我一直安慰自己,他們只是感情好材原,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開白布沸久。 她就那樣靜靜地躺著,像睡著了一般余蟹。 火紅的嫁衣襯著肌膚如雪麦向。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天客叉,我揣著相機(jī)與錄音诵竭,去河邊找鬼话告。 笑死,一個(gè)胖子當(dāng)著我的面吹牛卵慰,可吹牛的內(nèi)容都是我干的沙郭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼裳朋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼病线!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起鲤嫡,我...
    開封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤送挑,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后暖眼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惕耕,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年诫肠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了司澎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡栋豫,死狀恐怖挤安,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情丧鸯,我是刑警寧澤蛤铜,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站丛肢,受9級(jí)特大地震影響昂羡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜摔踱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望怨愤。 院中可真熱鬧派敷,春花似錦、人聲如沸撰洗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)差导。三九已至试躏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間设褐,已是汗流浹背颠蕴。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工泣刹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人犀被。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓椅您,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親寡键。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掀泳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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