美文网首页
springmvc aop切面日志

springmvc aop切面日志

作者: shaipxiang | 来源:发表于2019-09-29 09:06 被阅读0次
    1.web-info下面添加logback.xml
    <?xml version="1.0" encoding="UTF-8"?>     
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
        <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
            <param name="encoding" value="utf-8"/>
            <!-- 设置通道file和输出方式:org.apache.log4j.RollingFileAppender -->
            <param name="File" value="${catalina.home}/EHL_logs/ehl_atms_log.log" /><!-- 
                设置File参数:日志输出文件名 -->
            <param name="DatePattern" value="'-'yyyy-MM-dd" />
            <param name="Append" value="true" /><!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 -->
            <param name="MaxFileSize" value="5000KB" />
            <param name="MaxBackupIndex" value="10" /> 
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %p (%c:%L)- %m%n" /><!-- 
                    设置输出文件项目和格式 -->
            </layout>
        </appender>
    
        <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
            <!-- 设置监视器输出方式 -->
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-4r [%t] %-5p %c %x - %m%n" />
            </layout>
            <!--滤镜设置输出的级别 -->
            <filter class="org.apache.log4j.varia.LevelRangeFilter">
                <param name="levelMin" value="info" />
                <param name="levelMax" value="info" />
                <param name="AcceptOnMatch" value="true" />
            </filter>
        </appender>
    
        <root><!-- 设置接收所有输出的通道 -->
            <priority value="info" />
            <appender-ref ref="FILE" /><!-- 与前面的通道id相对应 -->
            <appender-ref ref="STDOUT" />
        </root>
    </log4j:configuration>  
    
    2.web.xml引入
    <!--logback配置开始-->
        <context-param>
            <param-name>logbackConfigLocation</param-name>
            <param-value>/WEB-INF/logback.xml</param-value>
        </context-param>
        <!--自定义监听器-->
        <listener>
            <listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
        </listener>
        <listener>
            <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
        </listener>
        <!--logback配置结束-->
    
    3.springmvc.xml中添加配置
    <!-- 启动对@AspectJ注解的支持 -->
        <aop:aspectj-autoproxy proxy-target-class="true"/>
        <!-- 日志注解 -->
        <bean id="LogAspect" class="com.ehl.frame.logback.SysLogAspect"/>
    

    头文件中需增加:
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd"

    4.定义注解
    /**
     * 系统日志注解
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface SysLog {
    
        String value() default "";
    }
    
    5.定义日志实体
    /**
     * @className:OperationLog
     * @description: 输出日志内容
     */
    public class OperationLog {
    
        /**
         * 用户编号
         */
        private String userId;
        /**
         * 用户名
         */
        private String userName;
    
        /**
         * 操作参数
         */
        private String params;
    
        /**
         * 返回信息
         */
        private String returnMsg;
    
        /**
         * 调用方法名称
         */
        private String method;
    
        /**
         * 请求追踪id
         */
        private String traceId;
    
        /**
         * 请求Ip
         */
        private String requestIp;
    
        /**
         * 操作描述
         */
        private String operationDescription;
    
        /**
         * 操作开始时间
         */
        private String operationStarttime;
    
        /**
         * 操作结束时间
         */
        private String operationEndtime;
    
        /**
         * 操作时长
         */
        private long time;
    }
    
    6.切面处理类
    /**
     * 系统日志,切面处理类
     *
     */
    @Aspect
    @Component
    public class SysLogAspect {
    
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
        @Pointcut("@annotation(com.ehl.frame.logback.SysLog)")
        public void logPointCut() {
            // 读取切面日志
        }
    
        @Around("logPointCut()")
        public Object around(ProceedingJoinPoint point) throws Throwable {
            // 记录开始时间
            long beginTime = System.currentTimeMillis();
            //执行方法
            Object result = point.proceed();
            //返回参数,暂时去掉,返回值多容易造成读写太慢
            String returnMsg = "";
            //if (result != null) {
            //    Class cls = Class.forName(result.getClass().getName());
            //    if (RespMsg.class.equals(cls)) {
            //        RespMsg respMsg = (RespMsg) result;
            //        returnMsg = respMsg.getMessage();
            //    } else if (List.class.equals(cls)) {
            //        List list = (List) result;
            //        if (!list.isEmpty()) {
            //            returnMsg += "返回数量:" + list.size();
            //        }
            //    } else if (Map.class.equals(cls)) {
            //        Map map = (Map) result;
            //        if (!map.isEmpty()) {
            //            returnMsg += "返回数量:" + map.size();
            //        }
            //    } else if (String.class.equals(cls)) {
            //        returnMsg += (String) result;
            //    } else {
            //        returnMsg += JSON.toJSONString(result);
            //    }
            //}
            long endTime = System.currentTimeMillis();
            //保存日志
            saveSysLog(point, beginTime, endTime, returnMsg);
            return result;
        }
    
        private void saveSysLog(ProceedingJoinPoint joinPoint, long beginTime, long endTime, String returnMsg) {
    
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
    
            OperationLog operationLog = new OperationLog();
    
            // 获取用户信息 记录用户信息
            HttpSession session = HttpUtil.getSession();
            String userId = null;
            String userName = null;
            LoginUserInfo userInfo = (LoginUserInfo) session.getAttribute("userLoginInfo");
            if (userInfo != null) {
                userId = userInfo.getUserId();
                userName = userInfo.getRealName();
            }
            operationLog.setUserId(userId);
            operationLog.setUserName(userName);
            SysLog syslog = method.getAnnotation(SysLog.class);
            if (syslog != null) {
                //注解上的描述
                operationLog.setOperationDescription(syslog.value());
            }
    
            //请求的方法名
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = signature.getName();
            operationLog.setMethod(methodName);
            Logger logger = LoggerFactory.getLogger(className);
            //请求的参数
            Object[] args = joinPoint.getArgs();
            try {
                if (args != null && args.length > 0) {
                    String params = JSON.toJSONString(args);
                    operationLog.setParams(params);
                }
            } catch (Exception e) {
                logger.error("输出日志参数获取失败");
            }
            operationLog.setReturnMsg(returnMsg);
    
            // 操作用时
            operationLog.setOperationStarttime(df.format(beginTime));
            operationLog.setOperationEndtime(df.format(endTime));
            operationLog.setTime(endTime - beginTime);
    
            //获取request
            HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
            //设置IP地址
            operationLog.setRequestIp(IPUtils.getIpAddr(request));
            // 跟踪记录id
            operationLog.setTraceId(UUID.randomUUID().toString());
    
    
            //保存系统日志
            String sysStr = JSONObject.toJSONString(operationLog);
            logger.info(sysStr);
        }
    }
    
    7.使用
        @SysLog("根据id查询厂商信息")
        @RequestMapping(value = "/query")
        @ResponseBody
        public Company query(HttpServletRequest request) {
            try {
                String id = request.getParameter("id");
                return companyServiceImpl.query(id);
            } catch (Exception e) {
                log.info(e.getMessage());
                Log.error("查询失败");
                return null;
            }
        }
    
    8.其他
    /**
         * 获取IP地址
         * 
         * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
         * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
         */
        public static String getIpAddr(HttpServletRequest request) {
            String ip = null;
            try {
                ip = request.getHeader("x-forwarded-for");
                if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("Proxy-Client-IP");
                }
                if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("WL-Proxy-Client-IP");
                }
                if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("HTTP_CLIENT_IP");
                }
                if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("HTTP_X_FORWARDED_FOR");
                }
                if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getRemoteAddr();
                }
            } catch (Exception e) {
                logger.error("IPUtils ERROR ", e);
            }
            
    //        //使用代理,则获取第一个IP地址
    //        if(StringUtils.isEmpty(ip) && ip.length() > 15) {
    //          if(ip.indexOf(",") > 0) {
    //              ip = ip.substring(0, ip.indexOf(","));
    //          }
    //      }
            
            return ip;
        }
        
    
    public class HttpContextUtils {
    
        public static HttpServletRequest getHttpServletRequest() {
            return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        }
    }
    
    9.补充:pom引入jar包
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.1.1</version>
            </dependency>
            <!--实现slf4j接口并整合-->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.1.1</version>
            </dependency>
            <dependency>
                <groupId>org.logback-extensions</groupId>
                <artifactId>logback-ext-spring</artifactId>
                <version>0.1.2</version>
            </dependency>
            <!-- 解决屏蔽日志报错问题 -->
            <dependency>
                <groupId>org.codehaus.janino</groupId>
                <artifactId>janino</artifactId>
                <version>3.0.7</version>
            </dependency>
            <!-- logback日志配置结束 -->
    

    相关文章

      网友评论

          本文标题:springmvc aop切面日志

          本文链接:https://www.haomeiwen.com/subject/ssgxpctx.html