spring AOP实现自定义日志

需求:开发中,需要简单的记录用户的操作日志。

AOP技术利用一种称为横切的技术,解剖封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,这样就能减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。

具体实现:

第一步:spring-mvc.xml文件中配置

<mvc:annotation-driven/>

 <!-- 启动对@AspectJ注解的支持 -->

<aop:aspectj-autoproxy proxy-target-class="true"/>


第二步:自定义注解

@Target({ElementType.PARAMETER, ElementType.METHOD})      

@Retention(RetentionPolicy.RUNTIME)      
@Documented
public @interface SystemLog {
String name()  default "";      

}


第三步:定义切面

@Aspect
@Component
public class LogAop {

private final Logger logger = Logger.getLogger(MqttMessageHandlerRunnable.class);

@Autowired
private IApiCallRecordService callService;
    
/**

* (后置通知)
* @Title: afterExec      
* @param joinPoint 切点
* @param rtv 方法返回值
*/
    @AfterReturning(value="@annotation(com.lingyun.llkmc.log.SystemLog)",returning = "rtv")
    public void afterExec(JoinPoint joinPoint,Object rtv){
        try {
MethodSignature ms=(MethodSignature) joinPoint.getSignature();
Method method=ms.getMethod();
String methodName = method.getAnnotation(SystemLog.class).name();
int developId = getDevelopId(joinPoint); //从切点中获取,方法的请求参数中的用户Id
JSONObject ro = (JSONObject)rtv; //我们系统中controller接口方法返回都是json格式
//记录操作日志,哪个用户调用了哪个方法+返回状态码
saveLog(methodName,ro.getString("statusCode"),developId);
} catch (Exception e) {
logger.error("记录接口调用日志错误",e);
}
    }
    
    /**
     * 
     * (异常通知)
     * @Title: afterThrowing   
     * @param joinPoint 切点
     * @param t 抛出的异常
     */
    @AfterThrowing(value="@annotation(com.lingyun.llkmc.log.SystemLog)",throwing = "t")
    public void afterThrowing(JoinPoint joinPoint,Throwable t){
        try {
MethodSignature ms=(MethodSignature) joinPoint.getSignature();
Method method=ms.getMethod();
String methodName = method.getAnnotation(SystemLog.class).name();
int developId = getDevelopId(joinPoint);
//记录日志
saveLog(methodName,"500",developId);
logger.error(method.getName()+"接口调用日志异常",t);
} catch (Exception e) {
logger.error("记录接口调用日志错误",e);
}
    }
    
    /**
     * 
     * (插入日志到数据库)
     * @Title: saveLog      
     * @param method
     * @param statusCode
     * @param developerId
     */
private void saveLog(String method, String statusCode, Integer developerId) {
ApiCallRecord record = new ApiCallRecord(method, statusCode, developerId);
callService.insert(record);
}

/**

* (获取用户Id)
* @Title: getDevelopId 
* @param joinPoint
* @return
*/
private int getDevelopId(JoinPoint joinPoint) {
Object[] os = joinPoint.getArgs();
int developerId = 0;
for (int i = 0; i < os.length; i++) {
Object o = os[i];
if (o instanceof DeveloperUser) {
developerId = ((DeveloperUser) o).getDeveloperId();
break;
}
}
return developerId;
}

}

第四步:在controller的接口方法上使用我们的自定义注解

@SystemLog(name="添加设备")

@ResponseBody
@RequestMapping(value="addDevice/{openToken}", method=RequestMethod.POST)

public JSONObject addDevice(HttpServletRequest request){

}

阅读更多
个人分类: spring
上一篇mysql查询死锁信息
下一篇spring boot/cloud 添加支持https +docker中
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭