ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

利用Spring的aop原理实现系统级日志管理

2021-11-28 16:06:11  阅读:180  来源: 互联网

标签:String ip aop request sysLog Spring 日志 null public


日常开发中,我们常用的日志有两种,一种是业务日志,该类型主要用于记录系统中某些业务的变化或属性的改变,比如业务流转过程中记录状态的变化或对象属性的变化,此类型主要用于查询业务轨迹使用;另一种是系统日志,主要记录方法的调用信息,比如方法名称,参数以及调用者的名称、ip、调用时间等信息。本文结合项目中的实际情况,介绍下如何使用Spring的aop原理实现系统级日志管理。

核心代码

1.声明系统日志切面类并交给Spring容器管理

代码如下:

@Aspect
@Component
public class SysLogAspect {
    
    @Autowired
    private SysLogService sysLogService;

    @Pointcut("execution(* com.xx.xx.*.service.*.*(..))")
    public void logPointCut() { 

    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        // 执行方法
        Object result = point.proceed();
        // 执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        // 保存日志
        saveSysLog(point, time);
        return result;
    }

    private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {

        String userName = BaseController.getUsername();//BaseController为项目中的基类,主要存储用户登录后的一些基本信息,该类可有可无,根据自己的实际情况而定

        //判断是否SysLogService的调用操作,SysLogService本身不再记录日志
        if(joinPoint.getTarget() instanceof SysLogService) { //SysLogService,自己声明的系统日志接口
            return ;
        }

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        SysLog sysLog = new SysLog();

        // 请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()");

        // 请求的参数
        Object[] args = joinPoint.getArgs();
        try{
            String params = JSONObject.toJSONString(args[0]);
            sysLog.setParams(params);
        } catch (Exception e){

        }

        // 获取request
        HttpServletRequest request = HttpUtils.getHttpServletRequest();
        // 设置IP地址
        sysLog.setIp(IPUtils.getIpAddr(request));

        // 用户名
        sysLog.setUserName(userName);

        // 执行时长(毫秒)
        sysLog.setTime(time);

        // 保存系统日志
        sysLogService.save(sysLog);
    }

}

2.声明ip工具类

代码如下:

public class IPUtils {
    
    private static Logger logger = LoggerFactory.getLogger(IPUtils.class);

    /**
     * 获取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);
        }
            
        return ip;
    }
    
}

3.声明HttpUtils工具类

代码如下:

public class HttpUtils {
    
    private static final Log log = LogFactory.getLog(HttpUtils.class);

    /**
     * 获取HttpServletRequest对象
     * @return
     */
    public static HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }
    
    /**
     * 输出信息到浏览器
     * @param response
     * @throws IOException
     */
    public static void print(HttpServletResponse response, int code, String msg) throws IOException {
        response.setContentType("application/json; charset=utf-8");
        HttpResult result = HttpResult.error(code, msg);
        String json = JSONObject.toJSONString(result);
        response.getWriter().print(json);
        response.getWriter().flush();
        response.getWriter().close();
    }
    
    public static String sendpost(String serverUrl, String data) {
        
        StringBuilder responseBuilder = null;
        BufferedReader reader = null;
        OutputStreamWriter wr = null;

        String re=null;
        try {
            URL url = new URL(serverUrl);
            URLConnection e = url.openConnection();
            e.setDoOutput(true);
            e.setConnectTimeout(5000);
            wr = new OutputStreamWriter(e.getOutputStream());
            wr.write(data);
            wr.flush();
            reader = new BufferedReader(new InputStreamReader(e.getInputStream()));
            responseBuilder = new StringBuilder();
            String line = null;

            while((line = reader.readLine()) != null) {
                responseBuilder.append(line).append("\n");
            }
            re=responseBuilder.toString();
            log.debug("http请求返回结果:"+re);
        } catch (IOException e1) {
            log.error("", e1);
        } finally {
            if(wr != null) {
                try {
                    wr.close();
                } catch (IOException e2) {
                    log.error("close error", e2);
                }
            }

            if(reader != null) {
                try {
                    reader.close();
                } catch (IOException e3) {
                    log.error("close error", e3);
                }
            }

        }

        return re;
    }
}

4.测试结果

利用Spring的aop原理实现系统级日志管理

备注:由于系统被频繁使用,每个接口被调用时都会生成一条数据,所以系统日志表中的数据量会特别大,要定期备份数据并清除一些旧数据,否则表中的数据会越来越多影响性能。

标签:String,ip,aop,request,sysLog,Spring,日志,null,public
来源: https://blog.csdn.net/m0_64355285/article/details/121592838

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有