博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring MVC 中使用AOP 进行统一日志管理--注解实现
阅读量:4588 次
发布时间:2019-06-09

本文共 4540 字,大约阅读时间需要 15 分钟。

1.AOP简介

AOP称为面向切面编程

 AOP的基本概念

(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知

(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用

(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

2.为什么要这么做?

AOP最常见的用法是进行日志管理和事务管理。现在我们重点说日志,下一节我们再介绍日志。

加入没使用AOP日志,但是为了日常维护方便和查找错误方便,我们要输入日志的话只能使用log.info()输出,关键是每一个需要日志的地方都要进行重复操作,而且不同的人输出的日志格式或者日志信息不统一,不便于使用。所以,我们使用切面,将日志服务作为一个组件动态地切入到我们需要地方,统一管理。

3.实现

我是在以前搭建的Spring MVC 工程基础上实现的日志功能。

首先在原来的基础上添加

org.aspectj
aspectjweaver
1.9.1

这个jar包的版本要和jdk匹配,否则会报错,jdk1.7以上必须使用1.7以上版本,为了避免报错,我直接使用了最高版本的。另外还要保证maven jar 保证有    这两个jar包

4.项目配置

项目配置中特别需要注意的是我是给controller层添加日志服务,而controller层是由Spring MVC 进行管理的,所以我们的日志服务组件也要确保能被spring MVC 扫到,而且要在spring MVC 配置文件中天AOP命名空间的支持,同时开启aop 支持。我之前走了很多弯路,就算因为我把这些配置都写在了spring的配置文件中,导致切面类一直无法生效。

5.切面类

package com.lzl.sss.aop;import java.io.UnsupportedEncodingException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Enumeration;import javax.servlet.http.HttpServletRequest;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;@Component@Aspect//定义切面类public class WebLogAspect {    private Logger logger = LoggerFactory.getLogger(WebLogAspect.class);        //定义切入点    @Pointcut("execution(* com.lzl.sss.controller.*.*(..))")    public void log(){            }        //定义通知,方法执行前    @Before("log()")    public void doBefore(JoinPoint poin) throws UnsupportedEncodingException{        logger.info("方法执行前,当前时间:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();        HttpServletRequest request = attributes.getRequest();        // 记录下请求内容        logger.info("请求URL : " + request.getRequestURL().toString());        logger.info("请求方法 : " + request.getMethod());        logger.info("IP地址 : " + request.getRemoteAddr());        Enumeration
enu = request.getParameterNames(); while (enu.hasMoreElements()) { String name = (String) enu.nextElement(); logger.info("参数:{},值:{}", name,new String(request.getParameter(name).getBytes("ISO-8859-1"),"utf-8")); } } //定义通知,方法执行后 @After("log()") public void after(JoinPoint poin){ logger.info("方法执行后,当前时间:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); } //定义通知,方法返回前 @AfterReturning(pointcut="log()",returning="returnVal") public void AfterReturning(JoinPoint poin){ logger.info("方法返回前,当前时间:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); } //定义通知,抛出异常 @AfterThrowing(pointcut="log()",throwing="error") public void AfterThrowing(Throwable error){ logger.info("方法报错,当前时间:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); } //定义通知环绕型 @Around("log()") public Object Around (ProceedingJoinPoint pjp) throws Throwable{ logger.info("环绕前:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); Object obj= pjp.proceed(); logger.info("环绕后:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); return obj; }}

切面类有以下几个注意的点:

(1).切点表达式。

第一个*表示匹配任意的方法返回值,..(两个点)表示零个或多个,上面的第一个..表示controller包及其子包,第二个*表示所有类,第三个*表示所有方法,第二个..表示方法的任意参数个数

(2).环绕型通知

环绕型通知在方法执行前后都会执行。且要添加返回类型,否则会导致连接点执行的方法无返回值。

(3).通知类型的执行顺序

正常情况:around--->before--->要执行的方法--->around---->after--->afterReturnning

报错情况下:around--->before--->要执行的方法--->around---->after--->afterThrowing

(4)注解

@Component 注解将类声明为一个组件,并注入到spring MVC 容器中

@Aspect 将这个bean修饰成一个切面类

6.实现效果

 

转载于:https://www.cnblogs.com/li-zhi-long/p/9391885.html

你可能感兴趣的文章
android新手关于左右滑动的问题,布局把<android.support.v4.view.ViewPager/><ImageView/> 放在上面就不行了。...
查看>>
python第二十一天---昨天没写完作业
查看>>
爬虫基础--IO多路复用单线程异步非阻塞
查看>>
Johnny Solving CodeForces - 1103C (构造,图论)
查看>>
oracle数据库自学笔记(持续更新中……)
查看>>
BZOJ3685: 普通van Emde Boas树
查看>>
Jquery 操作Cookie
查看>>
nginx
查看>>
递归和非递归的二分查找
查看>>
JSP自定义标签
查看>>
项目测试流程
查看>>
《代码大全》学习之--使用变量的一般事项
查看>>
JS位操作符
查看>>
mongodb
查看>>
VC++使用socket进行TCP、UDP通信实例总结
查看>>
Docker 构建网络服务后本机不能访问
查看>>
element ui table单选框点击全选问题
查看>>
Prometheus+Grafana监控Kubernetes
查看>>
年假总述
查看>>
BIEE一些目录
查看>>