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
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;
}
}
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 {};
}
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;
}
}
}
<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,学习视频)
<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)领取