SpringBoot使用Aop自定义注解展示日志信息

org.springframework.boot

spring-boot-starter-aop

io.springfox

springfox-swagger2

2.7.0

com.github.xiaoymin

swagger-bootstrap-ui

1.9.6

cn.afterturn

easypoi-spring-boot-starter

4.1.3

org.springframework.boot

spring-boot-starter-test

org.springframework.boot

spring-boot-starter-security

io.jsonwebtoken

jjwt

0.9.0

org.springframework.boot

spring-boot-starter-data-redis

org.apache.commons

commons-pool2

com.github.axet

kaptcha

0.0.9

com.alibaba

druid-spring-boot-starter

1.1.10

com.rabbitmq

amqp-client

org.springframework.boot

spring-boot-starter-amqp

org.springframework.boot

spring-boot-starter-validation

src/main/resources

src/main/java

**/*.xml

org.springframework.boot

spring-boot-maven-plugin

4:枚举类


package com.qycq.server.enums;

import io.swagger.annotations.ApiModel;

import lombok.extern.slf4j.Slf4j;

/**

  • @author 七月初七

  • @version 1.0

  • @date 2021/7/19 23:11

*/

@ApiModel(value = “日志操作类型”)

@Slf4j

public enum LogEnum {

LOGIN(“登录操作!”),

LOGOUT(“退出操作!”),

SELECT(“查询操作”),

DELETE(“删除操作”),

UPDATE(“更新操作!”),

CALCULATION(“计算操作!”),

INSERT(“增加操作”);

/**

  • 操作类型

*/

private final String type;

LogEnum(final String type) {

this.type = type;

}

public String getType() {

return this.type;

}

}

5:@Log自定义注解


package com.qycq.server.annotations;

import com.qycq.server.enums.LogEnum;

import io.swagger.annotations.ApiModel;

import java.lang.annotation.*;

/**

  • @author 七月初七

  • @version 1.0

  • @date 2021/7/19 22:50

*/

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@ApiModel(value = “日志注解”)

public @interface Log {

/**

  • 日志描述

  • @return

*/

LogEnum[] type() default {};

}

6:切面类


package com.qycq.server.aspect;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.qycq.server.encapsulation.ResultBean;

import com.qycq.server.enums.LogEnum;

import com.qycq.server.exception.GlobalException;

import com.qycq.server.pojo.Errorlog;

import com.qycq.server.pojo.Log;

import com.qycq.server.service.ErrorlogService;

import com.qycq.server.service.LogService;

import com.qycq.server.utils.HttpServletRequestUtil;

import com.qycq.server.utils.IpUtil;

import com.qycq.server.utils.StringUtil;

import io.swagger.annotations.ApiModel;

import io.swagger.annotations.ApiOperation;

import lombok.extern.slf4j.Slf4j;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.Signature;

import org.aspectj.lang.annotation.*;

import org.aspectj.lang.reflect.MethodSignature;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.annotation.Order;

import org.springframework.security.authentication.AnonymousAuthenticationToken;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;

import java.lang.reflect.Method;

import java.lang.reflect.Parameter;

import java.text.SimpleDateFormat;

import java.util.*;

/**

  • @author 七月初七

  • @version 1.0

  • @date 2021/7/19 23:17

*/

@ApiModel(value = “日志注解切面类”)

@Slf4j

@Configuration

@Aspect

@Order(1)

public class LogAspectImpl {

private static final Logger LOGGER = LoggerFactory.getLogger(LogAspectImpl.class);

@Autowired

private ObjectMapper objectMapper;

@Autowired

private LogService logService;

@Autowired

private ErrorlogService errorlogService;

private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);

/**

  • 切点

*/

@Pointcut(“@annotation(com.qycq.server.annotations.Log)”)

public void pointcut() {

}

/**

  • 前置增强

  • @param joinPoint

*/

@Before(“pointcut()”)

public void before(JoinPoint joinPoint) {

LOGGER.info(“========= 前置增强 start… =========”);

}

/**

  • 环绕增强

  • @param proceedingJoinPoint

  • @return

*/

@Around(“pointcut()”)

public Object result(ProceedingJoinPoint proceedingJoinPoint) {

LOGGER.info(“========= 环绕增强 start… =========”);

//获取开始时间

long startTime = System.currentTimeMillis();

HttpServletRequest httpServletRequest = HttpServletRequestUtil.getHttpServletRequest();

Log log = new Log();

Object proceed = null;

try {

//返回结果

proceed = proceedingJoinPoint.proceed();

Signature signature = proceedingJoinPoint.getSignature();

MethodSignature methodSignature = (MethodSignature) signature;

Method method = methodSignature.getMethod();

if (method.isAnnotationPresent(ApiOperation.class)) {

//获取方法描述

ApiOperation annotation = method.getAnnotation(ApiOperation.class);

log.setComment(annotation.value());

LOGGER.info(annotation.value());

}

if (method.isAnnotationPresent(com.qycq.server.annotations.Log.class)) {

//获取操作类型

com.qycq.server.annotations.Log annotation = method.getAnnotation(com.qycq.server.annotations.Log.class);

for (LogEnum logEnum : annotation.type()) {

log.setRequestType(logEnum.getType());

LOGGER.info(logEnum.getType());

}

}

//获取登录用户名

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

if (!(authentication instanceof AnonymousAuthenticationToken)) {

log.setUsername(authentication.getName());

LOGGER.info(authentication.getName());

}

//获取JSON数据耗时

long endDate = System.currentTimeMillis();

//获取方法类型(get,post…)

String methodType = httpServletRequest.getMethod();

String requestURL = httpServletRequest.getRequestURL().toString();

String requestURI = httpServletRequest.getRequestURI();

String className = proceedingJoinPoint.getTarget().getClass().getName() + “.” + proceedingJoinPoint.getSignature().getName();

String requestIp = IpUtil.getIpAddr(httpServletRequest);

Object params = getParams(method, proceedingJoinPoint.getArgs());

log.setRequestMethod(methodType);

log.setRequestURL(requestURL);

log.setRequestURI(requestURI);

log.setClassName(className);

log.setRequestIp(IpUtil.getIpAddr(httpServletRequest));

log.setRequestParams(objectMapper.writeValueAsString(params));

log.setStartTime(simpleDateFormat.format(new Date(startTime)));

log.setEndDate(System.currentTimeMillis() - endDate);

log.setRequestMethodName(proceedingJoinPoint.getSignature().getName());

log.setResult(objectMapper.writeValueAsString(proceed));

// 打印日志信息输出到控制台

LOGGER.info(“methodType:{}”, methodType);

LOGGER.info(“requestMethodName:{}”, proceedingJoinPoint.getSignature().getName());

LOGGER.info(“requestURL:{}”, requestURL);

LOGGER.info(“requestURI:{}”, requestURI);

LOGGER.info(“className:{}”, className);

LOGGER.info(“requestIp:{}”, requestIp);

LOGGER.info(“params:{}”, objectMapper.writeValueAsString(params));

LOGGER.info(“startDate:{}”, simpleDateFormat.format(new Date(startTime)));

LOGGER.info(“endDate:{}”, startTime - endDate);

LOGGER.info(“result:{}”, objectMapper.writeValueAsString(proceed));

//保存日志

boolean save = logService.save(log);

if (save) {

LOGGER.info(“日志保存成功!”);

}

} catch (Throwable throwable) {

throwable.printStackTrace();

LOGGER.error(“日志保存失败:{” + throwable.getMessage() + “}”);

}

return proceed;

}

/**

  • 后置增强

  • @param joinPoint

*/

@AfterReturning(“pointcut()”)

public void afterReturning(JoinPoint joinPoint) {

LOGGER.info(“========== 进入后置增强… ==========”);

}

/**

  • 异常增强

  • @param joinPoint

  • @param error

*/

@AfterThrowing(value = “pointcut()”, throwing = “error”)

public void afterThrowing(JoinPoint joinPoint, Throwable error) {

Errorlog errorlog = new Errorlog();

HttpServletRequest httpServletRequest = HttpServletRequestUtil.getHttpServletRequest();

try {

//获取代理方法

Signature signature = joinPoint.getSignature();

MethodSignature methodSignature = (MethodSignature) signature;

//获取方法名称

Method method = methodSignature.getMethod();

if (method.isAnnotationPresent(ApiOperation.class)) {

//获取方法描述

ApiOperation annotation = method.getAnnotation(ApiOperation.class);

errorlog.setComment(annotation.value());

LOGGER.info(annotation.value());

}

if (method.isAnnotationPresent(com.qycq.server.annotations.Log.class)) {

//获取操作类型

com.qycq.server.annotations.Log annotation = method.getAnnotation(com.qycq.server.annotations.Log.class);

for (LogEnum logEnum : annotation.type()) {

errorlog.setRequestType(logEnum.getType());

LOGGER.info(logEnum.getType());

}

}

//获取完整类路径名

String classMethodName = method + “”;

errorlog.setClassName(classMethodName);

//获取请求地址

String ipAddr = IpUtil.getIpAddr(httpServletRequest);

errorlog.setRequestIp(ipAddr);

//获取参数

Object args = getParams(method, joinPoint.getArgs());

errorlog.setRequestParams(objectMapper.writeValueAsString(args));

//获取异常名称

String errorName = error.getClass().getName();

errorlog.setErrorName(errorName);

//获取请求方法类型

String methodType = httpServletRequest.getMethod();

errorlog.setRequestMethod(methodType);

//获取相对方法名称

String simpleName = joinPoint.getTarget().getClass().getSimpleName();

errorlog.setRequestMethodName(simpleName);

//获取方法的url

String requestURL = httpServletRequest.getRequestURL().toString();

errorlog.setRequestURL(requestURL);

//相对路径

String requestURI = httpServletRequest.getRequestURI();

errorlog.setRequestURI(requestURI);

//返回堆栈跟踪元素

String errorMessage = this.stackTraceToString(errorName, error.getMessage(), error.getStackTrace());

errorlog.setErrorMessage(errorMessage);

LOGGER.info(“方法:{}”, classMethodName);

LOGGER.info(“入参:{}”, args);

LOGGER.info(“uri:{}”, requestURI);

LOGGER.info(“url:{}”, requestURL);

LOGGER.info(“methodType:{}”, methodType);

LOGGER.info(“ipAddr:{}”, ipAddr);

LOGGER.error(“异常信息:{}”, errorMessage);

boolean save = errorlogService.save(errorlog);

if (save) {

LOGGER.info(“错误日志保存成功!”);

}

// LOGGER.error(“方法:{}, 入参:{}, uri:{}, 请求ip:{}, 异常信息:{}”, classMethodName, args, requestURI, ipAddr, errorMessage);

} catch (Throwable throwable) {

log.error(“{}”, throwable.getMessage(), throwable);

}

}

/**

  • 组装异常信息

  • @param errorName

  • @param errorMessage

  • @param stackTrace

  • @return

*/

private String stackTraceToString(String errorName, String errorMessage, StackTraceElement[] stackTrace) {

StringBuilder stringBuffer = new StringBuilder();

for (StackTraceElement traceElement : stackTrace) {

stringBuffer.append(traceElement).append(“\n”);

}

return errorName + “:” + errorMessage + “\n\t” + stringBuffer.toString();

}

/**

  • 获取参数

  • @param method 当前方法

  • @param args 当前参数

  • @return

*/

private Object getParams(Method method, Object[] args) {

List paramsList = new ArrayList<>();

//拿到当前方法的参数数组

Parameter[] parameters = method.getParameters();

for (int i = 0; i < parameters.length; i++) {

//获取RequestBody注解修饰的参数

if (parameters[i].isAnnotationPresent(RequestBody.class)) {

RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);

if (requestBody != null) {

paramsList.add(args[i]);

}

}

//获取RequestParam注解修饰的参数

if (parameters[i].isAnnotationPresent(RequestParam.class)) {

RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);

Map<String, Object> map = new HashMap<>(16);

//获取的形参名称作为key

String key = parameters[i].getName();

System.out.println("key = " + key);

if (StringUtil.isNotEmpty(requestParam.value())) {

key = requestParam.value();

}

map.put(key, args[i]);

paramsList.add(map);

}

}

if (paramsList.size() == 0) {

return null;

} else if (paramsList.size() == 1) {

return paramsList.get(0);

} else {

return paramsList;

}

}

}

7:mybatisPlus代码生成器pom


<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<maven.compiler.source>1.8</maven.compiler.source>

<maven.compiler.target>1.8</maven.compiler.target>

org.springframework.boot

spring-boot-starter-web

mysql

mysql-connector-java

runtime

com.baomidou

mybatis-plus-boot-starter

3.3.1.tmp

最后

我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习

已经将知识体系整理好(源码,笔记,PPT,学习视频)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

找小编(vip1024c)领取
7:mybatisPlus代码生成器pom


<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<maven.compiler.source>1.8</maven.compiler.source>

<maven.compiler.target>1.8</maven.compiler.target>

org.springframework.boot

spring-boot-starter-web

mysql

mysql-connector-java

runtime

com.baomidou

mybatis-plus-boot-starter

3.3.1.tmp

最后

我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习

已经将知识体系整理好(源码,笔记,PPT,学习视频)

[外链图片转存中…(img-KzptgKwv-1721721071025)]

[外链图片转存中…(img-cfBsxk74-1721721071026)]

[外链图片转存中…(img-RZZSEcHF-1721721071026)]

找小编(vip1024c)领取

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值