自定义注解记录日志

java自定义注解记录日志

最近做了一个注解记录日志,经过反复打磨自觉比较严谨,同时也复习了自定义注解。现记录,方便以后调用。
导包:

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

注解部分

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLogRecord {
    String value() default "";
    String describe() default "";
}

切面记录逻辑部分:

@Aspect
@Component
public class SysLogAspect {
    private static final Logger log = LoggerFactory.getLogger(SysLogAspect.class);
	/**获取服务名称**/
    @Value("${spring.application.name}")
    private String serverName;
    /**
     * 与当前线程绑定避免多线程问题
     */
    ThreadLocal<Long> currentTime = new ThreadLocal<>();
    /**
     * 匹配数字类型的字符串:在实际开发中把String类型转换成number类型要先判断能不用转
     */
    Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
	/**保存日志接口**/
    @Autowired
    private ISysLogService iSysLogService;

    @Pointcut("@annotation(com.sinux.cc.syslogs.util.annotation.SysLogRecord)")
    public void logPointCut() {
    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        currentTime.set(System.currentTimeMillis());
        Object result = point.proceed();
        Long consumeTime = System.currentTimeMillis() - currentTime.get();
        currentTime.remove();
        /**
         * 从上下文环境获取request:
         * 这里是获取response的写法:
         *  HttpServletResponse servletResponse =
         *  ((ServletServerHttpResponse) RequestContextHolder.getRequestAttributes()).getServletResponse();
         *
         */
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        //保存日志
        saveSysLogs(point, consumeTime, result, request);
        return result;
    }

    private void saveSysLogs(ProceedingJoinPoint point, Long consumeTime, Object result, HttpServletRequest request) throws Exception {
        SysLog sl = new SysLog();

        Map<String, Object> map = returnResult(point);

        String ip = getIPAddress(request);
        String broswer = getBroswer(request);
        sl.setDescripe(map.get("descripe") == null ? "" : (String) map.get("descripe"));
        sl.setOperation(map.get("value") == null ? "" : (String) map.get("value"));
        sl.setMethod(map.get("menthodName") == null ? "" : (String) map.get("menthodName"));
        sl.setIp(ip);
        sl.setBroswer(broswer);
        /**
         * 用户名和id的获取,例如:shiro
         * userName = ShiroUtils.getSysUser().getUserName()
         * userId = ShiroUtils.getSysUser().getUserId();
         * 这里写死
         */
        sl.setUsername("cc");
        sl.setUserId(7L);
        sl.setCreateDate(new Date());
        sl.setTime(consumeTime + " 毫秒");
        /**
         * 0代表成功,1代表失败
         */
        sl.setOperateStatus(0);
        sl.setParams(map.get("sb") == null ? "" :  map.get("sb").toString());
        sl.setReturnParams(result.toString());
        sl.setServerName(serverName);

        iSysLogService.saveSysLogInfo(sl);
    }

    /**
     * 返回异常
     *
     * @param point
     * @param e
     */
    @AfterThrowing(pointcut = "logPointCut()", throwing = "e")
    public void afterThrowing(JoinPoint point, Throwable e) {
        Long t = System.currentTimeMillis() - currentTime.get();
        currentTime.remove();
        HttpServletRequest request =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).
                        getRequest();
        saveErrorLogs(point, t, request, e);

    }

    private void saveErrorLogs(JoinPoint point, Long t, HttpServletRequest request, Throwable e) {
        SysLog sl = new SysLog();
        String ip = getIPAddress(request);
        String broswer = getBroswer(request);
        Map<String, Object> map = returnResult(point);

        sl.setDescripe(map.get("descripe") == null ? "" : (String) map.get("descripe"));
        sl.setOperation(map.get("value") == null ? "" : (String) map.get("value"));
        sl.setMethod(map.get("menthodName") == null ? "" : (String) map.get("menthodName"));
        sl.setIp(ip);
        sl.setBroswer(broswer);
        /**
         * 用户名和id的获取,例如:shiro
         * userName = ShiroUtils.getSysUser().getUserName()
         * userId = ShiroUtils.getSysUser().getUserId();
         * 这里写死
         */
        sl.setUsername("cc");
        sl.setUserId(7L);
        sl.setCreateDate(new Date());
        sl.setTime(t + " 毫秒");
        /**
         * 0代表成功,1代表失败
         */
        sl.setOperateStatus(1);
        sl.setParams(map.get("sb") == null ? "" : (String) map.get("sb"));
        /**
         * 错误信息
         */
        sl.setReturnParams(e.getMessage());
        sl.setServerName(serverName);

        iSysLogService.saveSysLogInfo(sl);

    }

    public Map<String, Object> returnResult(JoinPoint point) {
        Map<String, Object> map = new HashMap<>();
        //方法签名
        MethodSignature signature = (MethodSignature) point.getSignature();
        //获取方法
        Method method = signature.getMethod();
        //获取方法上的注解
        SysLogRecord sysLogRecord = method.getAnnotation(SysLogRecord.class);
        if (sysLogRecord != null) {
            //从注解中获取参数
            map.put("value", sysLogRecord.value());
            map.put("descripe", sysLogRecord.describe());
        }
        //组装成:类名.方法名()
        String menthodName = point.getTarget().getClass().getName() + "." + signature.getName() + "()";
        map.put("menthodName", menthodName);
        /**
         * 获取请求参数并遍历
         */
        StringBuffer sb = new StringBuffer("{");
        Object[] argsValue = point.getArgs();
        String[] argsName = ((MethodSignature) point.getSignature()).getParameterNames();
        if (null != argsValue) {
            for (int i = 0; i < argsValue.length; i++) {
                sb.append(" ").append(argsName[i]).append(":").append(argsValue[i]);
            }
        }
        map.put("sb", sb.toString() + "}");

        return map;
    }
	/**
	*获取ip地址:这里考虑了多层中间件,如 网关、nginx等
	**/
    public static String getIPAddress(HttpServletRequest request) {
        String ip = null;

        //X-Forwarded-For:Squid 服务代理
        String ipAddresses = request.getHeader("X-Forwarded-For");
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //Proxy-Client-IP:apache 服务代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //WL-Proxy-Client-IP:weblogic 服务代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //HTTP_CLIENT_IP:有些代理服务器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //X-Real-IP:nginx服务代理
            ipAddresses = request.getHeader("X-Real-IP");
        }

        //有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }

        //还是不能获取到,最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }

    //获取浏览器信息
    /**
    *导入了获取浏览器的包:
    *  <dependency>
    *      <groupId>eu.bitwalker</groupId>
    *     <artifactId>UserAgentUtils</artifactId>
    *      <version>1.21</version>
    *   </dependency>
    ***/
    public String getBroswer(HttpServletRequest request) {
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        Browser browser = userAgent.getBrowser();
        return browser.getName();
    }

    /**
     * 判断字符串是不是数字类型
     * 实际环境中userId 数字类型,需要先判断是不是数字类型在转换
     * @param str
     * @return
     */
    public  boolean isInteger(String str) {

        return pattern.matcher(str).matches();
    }
}

使用的时候加上注解,在写个value 和describe 不写就默认为空

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神雕大侠mu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值