Java使用切面做全局日志统计

公共类

package com.chinaunicom.standard.product.ucenter.common.utils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * 上下文工具类
 *
 * @Author: ggw
 * @Date: 2024-06-24
 */
public class ContextUtil {

	public static final String APPLET_LOGIN_TOKEN = "token";

	private ContextUtil() {

	}

	/**
	 * 获取HttpServletRequest
	 *
	 * @author lijie<shs-cyhlwzylj@chinaunicom.cn>
	 * @return HttpServletRequest
	 */
	public static HttpServletRequest getHttpServletRequest() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}

	/**
	 * 获取HttpServletResponse
	 *
	 * @author lijie<shs-cyhlwzylj@chinaunicom.cn>
	 * @return HttpServletResponse
	 */
	public static HttpServletResponse getHttpServletResponse() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
	}

	/**
	 * 通过参数名获取请求参数值
	 *
	 * @author lijie<shs-cyhlwzylj@chinaunicom.cn>
	 * @param headerName 参数名
	 * @return String
	 */
	public static String getHttpServletRequestParamByKey(String headerName) {
		// 优先从请求头中获取
		String paramVal = getHttpServletRequest().getHeader(headerName);
		if (StringUtils.isEmpty(paramVal)) {
			// 头部为空时从请求url后获取
			paramVal = getUrlParam(getHttpServletRequest().getQueryString(), headerName);
		}
		return paramVal;
	}

	/**
	 * 获取请求中的登录令牌
	 *
	 * @author lijie<shs-cyhlwzylj@chinaunicom.cn>
	 * @return String
	 */
	public static String getRequestLoginToken() {
		return getHttpServletRequestParamByKey(APPLET_LOGIN_TOKEN);
	}

	/**
	 * 设置请求头中的Attribute
	 *
	 * @author lijie<shs-cyhlwzylj@chinaunicom.cn>
	 * @param name
	 * @param value void
	 */
	public static void setRequestAttribute(String name, Object value) {
		getHttpServletRequest().setAttribute(name, value);
	}

	/**
	 * 获取指定的URL参数值
	 *
	 * @author lijie<shs-cyhlwzylj@chinaunicom.cn>
	 * @param urlParam url参数字符串 eg:aa=11&bb==&cc=33
	 * @param paramKey 参数键 eg:cc
	 * @return String
	 */
	public static String getUrlParam(String urlParam, String paramKey) {
		if (StringUtils.isEmpty(urlParam)) {
			return null;
		}
		String params = urlParam.substring(urlParam.indexOf("?") + 1, urlParam.length());
		String[] paramArray = params.split("&");
		if (null != paramArray && paramArray.length > 0) {
			Map<String, String> paramMap = new HashMap<>(paramArray.length);
			for (String param : paramArray) {
				paramMap.put(param.substring(0, param.indexOf("=")), param.substring(param.indexOf("=") + 1));
			}
			return paramMap.get(paramKey);
		}
		return null;
	}

}

具体实现

import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;


@Component
@Aspect
@Order(0)
@Slf4j
public class UcenterLogOperationAspect extends AbstractController {
//根据增删改查全部统计
    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)||@annotation(org.springframework.web.bind.annotation.GetMapping)||@annotation(org.springframework.web.bind.annotation.DeleteMapping)||@annotation(org.springframework.web.bind.annotation.PutMapping)")
    public void ApiOperation() {
    }

    @Autowired
    private OperationLogMapper operationLogMapper;

    /**
     * 操作日志处理
     *
     * @param proceedingJoinPoint
     * @return
     */
     //根据ApiOperation这个注解获取接口描述
    @Around("ApiOperation()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) {
        long beginTime = System.currentTimeMillis();
        Object o = null;
        try {
            o = proceedingJoinPoint.proceed();
            //保存日志
            saveLog(proceedingJoinPoint, beginTime, (byte) 0, JSON.toJSONString(o));
            return o;
        } catch (Throwable throwable) {
            try {
                saveLog(proceedingJoinPoint, beginTime, (byte) -1, JSON.toJSONString(throwable.getMessage()));
            } catch (Exception e) {
                log.error("日志切面未知异常:{}", e);
            }
        }
        return o;
    }


    private void saveLog(ProceedingJoinPoint proceedingJoinPoint, long time, byte status, String errMsg) {
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        log.info("operatorType:" + apiOperation);
        // 注解上的描述
        // 判断是否记录日志
        if (apiOperation != null) {
            //请求相关信息
            HttpServletRequest request = ContextUtil.getHttpServletRequest();
            String url = request.getRequestURI();
            //这些接口不捕获,当然也可以做成配置化的,直接取网关的也可以
            if (!url.contains("/ucenter/logOperation/add") || url.contains("/ucenter/verifyCode")
                    || !url.contains("/ucenter/uuser/loginUserAuthInfo")) {
                // 初始化日志实体类
                OperationLog operationLog = new OperationLog();
                operationLog.setRequestIp(request.getRemoteHost());
                operationLog.setRequestTime(System.currentTimeMillis() - time);
                operationLog.setRequestStatus(status);
                operationLog.setOperation(apiOperation.value());
                String token = null;
                token = request.getHeader("token");
                if (StringUtils.isNotEmpty(token)) {
                    String accessToken = redisTemplate.opsForValue().get(token);
                    if (StringUtils.isNotEmpty(accessToken)) {
                        UserInfoResp userInfoResp = JSON.parseObject(accessToken, UserInfoResp.class);
                        operationLog.setCreatorName(userInfoResp.getUserName());
                    }
                    operationLog.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
                    //保存到DB
                    operationLogMapper.insert(operationLog);
                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值