場景:功能要求管理者可以通過在pc端web頁面通過背景,給連接配接背景的一些裝置設定定時開關。
背景和裝置直接使用tcp保持長連接配接,并使用約定的格式編碼資料,這不是重點。
為了滿足上面的需求,使用了WebAsyncTask進行處理背景與裝置之間的互動,互動完成後,背景再将互動結果回報給前端,告知管理者。
這部分順便貼下關鍵代碼:
@RequestMapping("/")
public WebAsyncTask<BaseResult> testActionRecord() {
Callable<BaseResult> callable=new Callable<BaseResult>() {
@Override
@ActionRecord(async = true, description = "什麼都不是", action = "/test")
public BaseResult call() throws Exception {
System.err.println("test()");
Test1 test1 = new Test1();
test1.setAction("11");
mapper.insertSelective(test1);
BaseResult baseResult = new BaseResult();
baseResult.setStatu(Status.STATU_SUCCESS);
baseResult.setMsg(Status.MSG_SUCCESS);
return baseResult;
}
};
return new WebAsyncTask<>(callable);
}
上面的代碼直接簡單模拟下了異步任務如何使用,其實為了與背景互動還需要用到回調函數。
tcp端使用mina,每個用戶端有專門的連接配接IoSession,全部通過ip和IoSession的key--value格式儲存到本地Map。
回調函數通過IoSession.setAttribute方法以一個屬性的形式綁定到連接配接IoSession上。在接口處使用thread.wait暫停主線程,然後等tcp那邊處理完畢後調用回調函數通知這邊主線程調用notify喚醒,然後将結果告知客戶。
這也不是重點。
重點是要添加記錄檔,記錄使用者行為,網上一搜一大堆,spring + aop +自定義注解實作。不多說。
上面代碼中@ActionRecord注解就是我自己實作的注解,需要記錄記錄檔的接口方法上隻需要添加這個注解,裡面的屬性也是自定義的。
然而,對于那些失敗的操作,我們是沒必要記錄日志的,是以,在注解業務裡面涉及到了擷取接口傳回狀态的操作,也不難,網上一搜一大堆。
現在碰到了上面這種異步的傳回,如果在注解業務裡面做的話,通過
ProceedingJoinPoint 的 proceed方法,隻能拿到WebAsyncTask這個對象,還要用這個對象去執行 getCallable().call()才能拿到結果。
這麼一來,異步任務相當于執行了兩次。
是以,對于這種異步任務要記錄記錄檔,就不能在接口上面加記錄記錄檔的自定義注解了,而是像上面貼出的代碼那樣,寫到call()方法上。
另:上面的自定義屬性async,當時就是為了區分普通接口和異步執行接口的,現在也沒必要留着了。