zoukankan      html  css  js  c++  java
  • 通过AOP拦截打印日志,出入参数

    import java.lang.reflect.Modifier;
    
    import javassist.ClassClassPath;
    import javassist.ClassPool;
    import javassist.CtClass;
    import javassist.CtMethod;
    import javassist.bytecode.CodeAttribute;
    import javassist.bytecode.LocalVariableAttribute;
    import javassist.bytecode.MethodInfo;
    
    import org.apache.commons.lang.ArrayUtils;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.alibaba.fastjson.JSON;
    
    /**@Description 
     哪个资方需要输出日志,自己到**-config工程下的spring-commons.xml配置
    <!-- 日志打印 -->
    <bean id="aopLog" class="com.XXXXXXX.AopLog"/>
     * @author : 陈惟鲜 danger
     * @Date : 2018年8月9日 下午5:59:55
     *
     */
    @Aspect
    public class AopLog {
    
        private Logger logger = LoggerFactory.getLogger(getClass());
        /**拦截所有controller包下的方法*/
        @Pointcut("execution(* com.sinaif.king..controller..*.*(..))")
        private void controllerMethod(){}//定义一个切入点  
        
        /**拦截所有service包下的方法*/
        @Pointcut("execution(* com.sinaif.king..service..*.*(..))")
        private void serviceMethod(){}//定义一个切入点  
    
    //    // 1、前置通知: 在目标方法开始之前执行(就是要告诉该方法要在哪个类哪个方法前执行)
    //    @Before("controllerMethod() || serviceMethod()")
    //    public void beforeMethod(JoinPoint joinPoint) {
    //         String methodName = joinPoint.getSignature().getName();
    //         String className = joinPoint.getTarget().getClass().getName();
    //         String msgInfo = "【" + className + "." + methodName + "】";
    //         logger.info(msgInfo + "......start..........");
    //    }
    //    
    //    // 2、后置通知:在目标方法执行后(无论是否发生异常),执行的通知
    //    // 注意,在后置通知中还不能访问目标执行的结果!!!,执行结果需要到返回通知里访问
    //    @After("controllerMethod() || serviceMethod()")
    //    public void afterMethod(JoinPoint joinPoint) {
    //         String className = joinPoint.getTarget().getClass().getName();
    //         String methodName = joinPoint.getSignature().getName();
    //         String msgInfo = "【" + className + "." + methodName + "】";
    //         logger.info(msgInfo + "...............end.");
    //    }
        
        /** 
         * @Description : 日志打印
         * @author : 陈惟鲜 danger
         * @Date : 2018年8月8日 下午5:29:47
         * @param point
         * @return
         * @throws Throwable
         */
        @Around("controllerMethod() || serviceMethod()")  
        public Object doAround(ProceedingJoinPoint point) throws Throwable {
            String msgInfo = "@aop["+point.getSignature().getDeclaringTypeName()+"."+point.getSignature().getName()+"]"; // 所在的类.方法
            String requestStr = getRequestParam(point);
            requestStr = parameterHandle(requestStr, 10000);
            logger.info(msgInfo + "start.输入参数:" + requestStr);
            long startTime = System.currentTimeMillis();// 开始时间
            Object result = null;
            try{
                // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行  
                result = point.proceed();// result的值就是被拦截方法的返回值  
            }catch(Exception e){
                throw e;
            }finally{
                long handleTime = System.currentTimeMillis()-startTime;// 开始时间
                String responseStr = result==null?"无": JSON.toJSONString(result);
                responseStr = parameterHandle(responseStr, 10000);
                
                StringBuffer endString = new StringBuffer(100);
                endString.append(msgInfo).append("end.");
                endString.append("耗时(" + handleTime + "ms)");
                endString.append("输出参数:").append(responseStr);
                
                logger.info(endString.toString());
            }
            return result;  
        }
        
        /**
         * @Description : 参数处理,超过指定长度字符的,只显示1000...
         * @author : 陈惟鲜 danger
         * @Date : 2018年8月10日 上午11:44:11
         * @param paramStr
         * @param strlength
         * @return
         */
        private String parameterHandle(String paramStr, int strlength){
            if (paramStr.length() > strlength){
                paramStr = paramStr.substring(0, 1000) + "...";
            }
            if (paramStr.length() > 10){
                paramStr = "[" + paramStr + "]";
            }
            return paramStr;
        }
        
        /***
         * @Description : 获取请求参数
         * @author : 陈惟鲜 danger
         * @Date : 2018年8月9日 下午3:47:08
         * @param point
         * @return
         */
        private String getRequestParam(ProceedingJoinPoint point){
            String class_name = point.getTarget().getClass().getName();
            String method_name = point.getSignature().getName();
            /**
             * 获取方法的参数值数组。
             */
            Object[] methodArgs = point.getArgs();
            
            String[] paramNames = null;
            // 结果
            String requestStr = "";
            /**
             * 获取方法参数名称
             */
             try {
                paramNames = getFieldsName(class_name, method_name);
                requestStr = logParam(paramNames, methodArgs);
            } catch (Exception e) {
                requestStr = "获取参数失败";
            }
            return requestStr;
        }
        
        /**
         * 使用javassist来获取方法参数名称
         * @param class_name    类名
         * @param method_name   方法名
         * @return
         * @throws Exception
         */
        private String[] getFieldsName(String class_name, String method_name) throws Exception {
            Class<?> clazz = Class.forName(class_name);
            String clazz_name = clazz.getName();
            ClassPool pool = ClassPool.getDefault();
            ClassClassPath classPath = new ClassClassPath(clazz);
            pool.insertClassPath(classPath);
    
            CtClass ctClass = pool.get(clazz_name);
            CtMethod ctMethod = ctClass.getDeclaredMethod(method_name);
            MethodInfo methodInfo = ctMethod.getMethodInfo();
            CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
            LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
            if(attr == null){
                return null;
            }
            String[] paramsArgsName = new String[ctMethod.getParameterTypes().length];
            int pos = Modifier.isStatic(ctMethod.getModifiers()) ? 0 : 1;
            for (int i=0;i<paramsArgsName.length;i++){
                paramsArgsName[i] = attr.variableName(i + pos);
            }
            return paramsArgsName;
        }
        
        /**
         * 判断是否为基本类型:包括String
         * @param clazz clazz
         * @return  true:是;     false:不是
         */
        private boolean isPrimite(Class<?> clazz){
            if (clazz.isPrimitive() || clazz == String.class){
                return true;
            }else {
                return false;
            }
        }
    
    
        /**
         * 打印方法参数值  基本类型直接打印,非基本类型需要重写toString方法
         * @param paramsArgsName    方法参数名数组
         * @param paramsArgsValue   方法参数值数组
         */
        private String logParam(String[] paramsArgsName,Object[] paramsArgsValue){
            if(ArrayUtils.isEmpty(paramsArgsName) || ArrayUtils.isEmpty(paramsArgsValue)){
                return "";
            }
            StringBuffer buffer = new StringBuffer();
            for (int i=0;i<paramsArgsValue.length;i++){
                //参数名
                String name = paramsArgsName[i];
                //参数值
                Object value = paramsArgsValue[i];
                buffer.append(name +" = ");
                if(isPrimite(value.getClass())){
                    buffer.append(value + "  ,");
                }else {
                    buffer.append(value.toString() + "  ,");
                }
            }
            return buffer.toString();
        }
    }
  • 相关阅读:
    ASP.net 上传
    asp.net 上传
    asp.net dropdownlist和listbox
    jqeury之平移轮播
    vs2013的asp.net 管理
    jqeury轮播
    jqeury之轮播图
    重温委托(delegate)和事件(event)
    Log4Net
    解决SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/OpenDatasource' 的访问的方法
  • 原文地址:https://www.cnblogs.com/a393060727/p/9454281.html
Copyright © 2011-2022 走看看