背景:存在A系統(tǒng)和N系統(tǒng)疙渣。N系統(tǒng)是一個公共系統(tǒng)匙奴,目前暫時只接入A系統(tǒng),將來還會接入B系統(tǒng)妄荔,C系統(tǒng)等泼菌。
N系統(tǒng)分成眾多子項目,現在其中的基礎模塊需要為其他模塊提供日志插入功能啦租,除此之外還需要將日志接入外部的A哗伯,B等系統(tǒng)提供。為什么要記錄2份日志呢篷角?emmm,原因我就不描述了焊刹,因為對理解這個文章不是很有必要,總之是研發(fā)和產品一堆人溝通下來的結果恳蹲。
一虐块,設計思路:
基礎模塊提供一個切面,以及一個自定義的Annotation嘉蕾,其他模塊在需要記錄日志的接口加上這個Annotation贺奠。基礎模塊除了在自身保存一份日志荆针,還需要為A系統(tǒng)等外部系統(tǒng)保存敞嗡,考慮到拓展性,為外部系統(tǒng)保存日志的時候航背,采用工廠模式喉悴。
二,基礎模塊日志具體實現(這里僅描述對外提供的jar包):
1,annotation
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD, ElementType.TYPE })
public @interface OperateLogAnnotation {
}
2,切面類
@Aspect
public class ControllerOperateLogAspect
{
//調用外部系統(tǒng)的工廠類
@Autowired
private OperationLogFactory operationLogFactory;
//省略其他玖媚。箕肃。。今魔。勺像。
/**
* 對有@LogOperation標記的方法,記錄其執(zhí)行參數及返回結果.
*/
@Pointcut("@annotation(com.xxx.base.annotation.OperateLogAnnotation)")
public void methodPointcut()
{
}
@Around("methodPointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable
{
Object obj = pjp.proceed();
try
{
//省略判斷,只有調用成功才記錄日志
// 成功后記錄操作日志错森,記錄在基礎模塊的日志
insertOperateLog();
// 插入外部系統(tǒng)日志
insertExternalOperationLog();
}
catch (Throwable e)
{
log.error("記錄操作日志信息異常:", e);
}
return obj;
}
/**
* 記錄業(yè)務方日志
*/
public void insertExternalOperationLog(String remark....) throws Throwable
{
//通過工廠獲取具體的外部日志處理類
OperationLogService operationLogService = operationLogFactory
.getOperationLogService(remark);
operationLogService.insertOperationLog();
}
3吟宦,外部日志處理接口
public interface OperationLogService
{
void insertOperationLog(....);
String getRemark();
}
4,外部日志處理實現類(針對A系統(tǒng)的)
public class XXOperationLog implements OperationLogService
{
@Autowired
private ThreadPoolTaskExecutor operateLogThreadPool;
public void insertOperationLog(....)
{
// 省略,使用線程池保存數據涩维,不展開
operateLogThreadPool
.execute(new XXOperationLogTask(..));
}
@Override
public String getRemark()
{
return "xxxx";//這里返回A系統(tǒng)的標識
}
}
如果后續(xù)N系統(tǒng)還要繼續(xù)接入其他系統(tǒng)就再接入新加一個實現類殃姓。
5,工廠類OperationLogFactory
public class OperationLogFactory
{
@Autowired
private List<OperationLogService> list;
public OperationLogService getOperationLogService(String remark) throws Throwable
{
for (OperationLogService operationLogService : list)
{
if (operationLogService.getRemark().equals(remark))
{
return operationLogService;
}
}
throw new NoSuchBeanDefinitionException("沒找到對應業(yè)務方的日志實現類,業(yè)務方remark:" + remark);
}
}
工廠類這里使用的是集合注入,這也是我無意間了解到的蜗侈,是不是很方便篷牌?list可以拿到這個接口的所有實現類。
到這里基礎模塊的日志部分就完成了踏幻,然后就是N系統(tǒng)的其他模塊(這個是日志記錄發(fā)起者)的引用了枷颊。
三,其他模塊(日志記錄發(fā)起者)的引用
1该面,需要引入基礎模塊對外提供的jar包:
使用maven坐標引入的方式夭苗。這里采用的dubbo的調用方式,如果沒了解過的同學吆倦,可以把這個jar包當成第三方的工具听诸,通過這個jar包就可以使用第三方的服務。
2蚕泽,注冊相關的bean:
① 為切面類ControllerOperateLogAspect注冊一個bean。
②為切面類ControllerOperateLogAspect中調用的基礎模塊日志功能的dubbo服務注冊一個bean桥嗤。
(不過這里采用的是引入配置文件的方式须妻,就是在項目中import基礎模塊jar包中配置好的xml配置文件,配置文件已經配置好了需要的bean泛领,調用者不需要具體配置那些bean)
3荒吏,在需要記錄日志的接口上方加上注解@OperateLogAnnotation
好了,整個流程結束啦渊鞋,可以看看發(fā)起的日志是否寫入了基礎服務
和A系統(tǒng)的數據庫中绰更。
終于寫完了