使用spring的AOP实现web日志记录

一、AOP介绍


什么是AOP
AOP:Aspect Oriented Programming,中文翻译为”面向切面编程“。面向切面编程是一种编程范式,它作为OOP面向对象编程的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理、权限控制、缓存控制、日志打印等等。AOP采取横向抽取机制,取代了传统纵向继承体系的重复性代码
AOP把软件的功能模块分为两个部分:核心关注点和横切关注点。业务处理的主要功能为核心关注点,而非核心、需要拓展的功能为横切关注点。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点进行分离
使用AOP有诸多好处,如:
1.集中处理某一关注点/横切逻辑
2.可以很方便的添加/删除关注点
3.侵入性少,增强代码可读性及可维护性

AOP的术语
1.Join point(连接点)
Spring 官方文档的描述:

A point during the execution of a program, such as the execution of a method or the handling of an exception. In Spring AOP, a join point always represents a method execution.

程序执行过程中的一个点,如方法的执行或异常的处理。在Spring AOP中,连接点总是表示方法的执行。通俗的讲,连接点即表示类里面可以被增强的方法
2.Pointcut(切入点)

Pointcut are expressions that is matched with join points to determine whether advice needs to be executed or not. Pointcut uses different kinds of expressions that are matched with the join points and Spring framework uses the AspectJ pointcut expression language

切入点是与连接点匹配的表达式,用于确定是否需要执行通知。切入点使用与连接点匹配的不同类型的表达式,Spring框架使用AspectJ切入点表达式语言。我们可以将切入点理解为需要被拦截的Join point
3.Advice(增强/通知)
所谓通知是指拦截到Joinpoint之后所要做的事情就是通知,通知分为前置通知、后置通知、异常通知、最终通知和环绕通知(切面要完成的功能)
4.Aspect(切面)
Aspect切面表示Pointcut(切入点)和Advice(增强/通知)的结合

二、实现

  1. 切入点(pointcut)
    a、通过修饰符以及类路径的一系列东西,例如 public * com .* …不多做介绍
    b、通过注解的方式

    本文就以注解的方式实现

    扫描二维码关注公众号,回复: 8632141 查看本文章
  2. 日志表设计

    @Entity
    @Data
    @Table(name = "operation_log")
    public class OperationLog {
    	@Id
    	@GeneratedValue(strategy= GenerationType.IDENTITY)
    	private Long id;
    	private Long userId;
        private String userName;
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm ss", timezone = "GMT+8")
    	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm ss")
        @CreatedDate
        private Date createDate;
        //请求地址
        private String url;
        //ip
        private String ip;
        //请求参数
        @Type(type="text")
        private String args;
    }
    
  3. 创建注解类

    @Target({ElementType.METHOD, ElementType.TYPE})//用于设定注解使用范围  METHOD==方法上方
    public @interface LogAnnotation {
    }
    
  4. 拦截类

    @Aspect
    @Component
    public class LogAspect {
    	
    	@Autowired
    	private LogService logService;
    	
    	@Pointcut("@annotation(LogAnnotation)")
        public void annotationPointcut() {
        }
    	@Before("annotationPointcut()")
        public void beforePointcut(JoinPoint joinPoint) {
    		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    		HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
            String requestURI = request.getRequestURI();
            //获取IP
            String ip = request.getRemoteAddr();
            //获取所有请求参数名称
            Enumeration<String> parameterNames = request.getParameterNames();
            String args="";
            while(parameterNames.hasMoreElements()) {
            	String nextElement = parameterNames.nextElement();
            	String value = request.getParameter(nextElement);
            	args+="k:"+nextElement+",v:"+value+";";
            }
            
            HttpSession session = request.getSession();
            User user = (User) session.getAttribute(AppConstant.SESSION_USER);
            
            OperationLog operationLog=new OperationLog();
            operationLog.setCreateDate(new Date());
            operationLog.setArgs(args);
            operationLog.setIp(ip);
            operationLog.setUrl(requestURI);
            operationLog.setUserId(user.getId());
            operationLog.setUserName(user.getName());
            logService.saveLog(operationLog);
        }
    }
    
  5. 控制器

    	@LogAnnotation
    	@RequestMapping("/add")
    	public void add(args....) {
    		........
    	}
    
  6. 完成 !

发布了6 篇原创文章 · 获赞 4 · 访问量 195

猜你喜欢

转载自blog.csdn.net/weixin_42870117/article/details/103874259