springboot添加切面

Posted 代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot添加切面相关的知识,希望对你有一定的参考价值。

package com.bxs.portal2.aspect;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.bxs.portal2.entity.SysLogBO;
import com.bxs.portal2.service.SysLogService;
import com.bxs.portal2.util.Serializor;
import com.google.common.collect.Maps;
import com.google.gson.Gson;

import lombok.extern.slf4j.Slf4j;

/**
 * 系统日志切面
 * 
 * @author zhuzhe
 * @date 2018/6/4 9:27
 * @email [email protected]
 */
@Aspect // 使用@Aspect注解声明一个切面
@Component
@Slf4j
public class SysLogAspect {

    @Autowired
    private SysLogService sysLogService;

    /**
     * 这里我们使用注解的形式 当然,我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method 切点表达式:
     * execution(...)
     */
    @Pointcut("execution(* com.bxs.portal2.service..*(..))")
    public void logPointCut() {
    }

    /**
     * 环绕通知 @Around , 当然也可以使用 @Before (前置通知) @After (后置通知)
     * 
     * @param point
     * @return
     * @throws Throwable
     * 
     *             @Before("logPointCut()") public Object
     *             around(ProceedingJoinPoint point) throws Throwable { try {
     *             saveLog(point, 10); } catch (Exception e) { } return null; }
     */

    @Before("logPointCut()")
    public void before(JoinPoint joinPoint) {
        log.info("前置通知");
        // 获取目标方法的参数信息
        Object[] obj = joinPoint.getArgs();
        // AOP代理类的信息
        joinPoint.getThis();
        // 代理的目标对象
        joinPoint.getTarget();
        // 用的最多 通知的签名
        Signature signature = joinPoint.getSignature();
        // 代理的是哪一个方法
        log.info("代理的是哪一个方法" + signature.getName());
        // AOP代理类的名字
        log.info("AOP代理类的名字" + signature.getDeclaringTypeName());
        // AOP代理类的类(class)信息
        signature.getDeclaringType();
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes
                .resolveReference(RequestAttributes.REFERENCE_REQUEST);
        // 如果要获取Session信息的话,可以这样写:
        // HttpSession session = (HttpSession)
        // requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
        // 获取请求参数
        Enumeration<String> enumeration = request.getParameterNames();
        Map<String, String> parameterMap = Maps.newHashMap();
        while (enumeration.hasMoreElements()) {
            String parameter = enumeration.nextElement();
            parameterMap.put(parameter, request.getParameter(parameter));
        }

        Optional<String> str = Serializor.toJson(parameterMap);
        if (obj.length > 0) {
            log.info("请求的参数信息为:" + Serializor.toJson(obj));
        }
    }

    /**
     * 后置最终通知(目标方法只要执行完了就会执行后置通知方法)
     * 
     * @param joinPoint
     */
    @After("logPointCut()")
    public void doAfterAdvice(JoinPoint joinPoint) {
        log.info("后置最终通知执行了!!!!");
    }

    @Around("logPointCut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        String queryString = request.getQueryString();
        log.info("请求开始, 各个参数, url: {}, method: {}, uri: {}, params: {}", url, method, uri, queryString);

        // result的值就是被拦截方法的返回值
        Object result = pjp.proceed();
        Gson gson = new Gson();
        log.info("请求结束,controller的返回值是 " + gson.toJson(result));
        return result;
    }

    /**
     * 保存日志
     * 
     * @param joinPoint
     * @param time
     */
    private void saveLog(ProceedingJoinPoint joinPoint, long time) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        System.out.println(method);
        SysLogBO sysLogBO = new SysLogBO();
        sysLogBO.setExeuTime(time);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        sysLogBO.setCreateDate(dateFormat.format(new Date()));
        // 请求的 类名、方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLogBO.setClassName(className);
        sysLogBO.setMethodName(methodName);
        // 请求的参数
        Object[] args = joinPoint.getArgs();
        try {
            List<String> list = new ArrayList<String>();
            for (Object o : args) {
                list.add(new Gson().toJson(o));
            }
            sysLogBO.setParams(list.toString());
        } catch (Exception e) {
        }
        sysLogService.save(sysLogBO);
    }
}

 

以上是关于springboot添加切面的主要内容,如果未能解决你的问题,请参考以下文章

springboot 切面添加日志功能

springboot添加切面

Springboot通过切面校验参数完整性

springBoot AOP学习

SpringBoot切面Aop的demo简单讲解

SpringBoot—集成AOP详解(面向切面编程Aspect)