feat(新增-记录日志): 记录日志环绕通知
Signed-off-by: bunny <1319900154@qq.com>
This commit is contained in:
parent
9fc4afebc2
commit
7b060d309c
|
@ -9,6 +9,7 @@
|
|||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="spzx-model" />
|
||||
<module name="common-util" />
|
||||
<module name="common-log" />
|
||||
<module name="common-service" />
|
||||
<module name="spzx-manager" />
|
||||
</profile>
|
||||
|
@ -16,6 +17,7 @@
|
|||
</component>
|
||||
<component name="JavacSettings">
|
||||
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||
<module name="common-log" options="-parameters" />
|
||||
<module name="common-service" options="-parameters" />
|
||||
<module name="common-util" options="-parameters" />
|
||||
<module name="spzx-manager" options="-parameters" />
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/spzx-common/common-log/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/spzx-common/common-service/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/spzx-common/common-util/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/spzx-common/src/main/java" charset="UTF-8" />
|
||||
|
|
1
pom.xml
1
pom.xml
|
@ -19,6 +19,7 @@
|
|||
<module>spzx-common</module>
|
||||
<module>spzx-model</module>
|
||||
<module>spzx-manager</module>
|
||||
<module>spzx-common/common-log</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.atguigu</groupId>
|
||||
<artifactId>spzx-parent-v2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>common-log</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>common-log</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.atguigu</groupId>
|
||||
<artifactId>spzx-model</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.atguigu</groupId>
|
||||
<artifactId>common-util</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.atguigu</groupId>
|
||||
<artifactId>common-service</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,18 @@
|
|||
package com.atguigu.log.annotation;
|
||||
|
||||
import com.atguigu.log.aspect.LogAspect;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
// 开启动类中开启包扫描也可以,
|
||||
// 如果不想这样写可以按照下面定义一个切面类,
|
||||
// 之后在SpringBoot中加入这个注解,让其扫描到
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Import(value = LogAspect.class)
|
||||
public @interface EnableLogAspect {
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.atguigu.log.annotation;
|
||||
|
||||
import com.atguigu.log.enums.OperatorType;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Log { // 自定义操作日志记录注解
|
||||
|
||||
String title(); // 模块名称
|
||||
|
||||
OperatorType operatorType() default OperatorType.MANAGE; // 操作人类别
|
||||
|
||||
int businessType(); // 业务类型(0其它 1新增 2修改 3删除)
|
||||
|
||||
boolean isSaveRequestData() default true; // 是否保存请求的参数
|
||||
|
||||
boolean isSaveResponseData() default true; // 是否保存响应的参数
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.atguigu.log.aspect;
|
||||
|
||||
import com.atguigu.exception.BunnyException;
|
||||
import com.atguigu.log.annotation.Log;
|
||||
import com.atguigu.log.service.AsyncOperaLogService;
|
||||
import com.atguigu.log.utils.LogUtil;
|
||||
import com.atguigu.spzx.model.entity.system.SysOperLog;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class LogAspect {
|
||||
@Autowired
|
||||
private AsyncOperaLogService asyncOperaLogService;
|
||||
|
||||
@Around(value = "@annotation(sysLog)")
|
||||
public Object doAroundAdvice(ProceedingJoinPoint joinPoint, Log sysLog) {
|
||||
// 构建前置参数
|
||||
SysOperLog sysOperLog = new SysOperLog();
|
||||
|
||||
LogUtil.beforeHandleLog(sysLog, joinPoint, sysOperLog);
|
||||
|
||||
Object proceed = null;
|
||||
try {
|
||||
proceed = joinPoint.proceed();
|
||||
// 执行业务方法
|
||||
LogUtil.afterHandleLog(sysLog, proceed, sysOperLog, 0, null);
|
||||
// 构建响应结果参数
|
||||
} catch (Throwable e) { // 代码执行进入到catch中,
|
||||
// 业务方法执行产生异常
|
||||
LogUtil.afterHandleLog(sysLog, proceed, sysOperLog, 1, e.getMessage());
|
||||
throw new BunnyException(e.getMessage());
|
||||
}
|
||||
|
||||
// 保存日志数据
|
||||
asyncOperaLogService.saveSysOperaLog(sysOperLog);
|
||||
|
||||
// 返回执行结果
|
||||
return proceed;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.atguigu.log.enums;
|
||||
|
||||
// 操作人类别
|
||||
public enum OperatorType {
|
||||
OTHER,// 其他
|
||||
MANAGE,// 后台用户
|
||||
MOBILE// 手机端用户
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.atguigu.log.service;
|
||||
|
||||
import com.atguigu.spzx.model.entity.system.SysOperLog;
|
||||
|
||||
// 保存日志数据
|
||||
public interface AsyncOperaLogService {
|
||||
void saveSysOperaLog(SysOperLog sysOperLog);
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.atguigu.log.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.atguigu.context.BaseContext;
|
||||
import com.atguigu.log.annotation.Log;
|
||||
import com.atguigu.spzx.model.entity.system.SysOperLog;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class LogUtil {
|
||||
|
||||
// 操作执行之后调用
|
||||
public static void afterHandleLog(Log sysLog, Object proceed,
|
||||
SysOperLog sysOperLog, int status,
|
||||
String errorMsg) {
|
||||
if (sysLog.isSaveResponseData()) {
|
||||
sysOperLog.setJsonResult(JSON.toJSONString(proceed));
|
||||
}
|
||||
sysOperLog.setStatus(status);
|
||||
sysOperLog.setErrorMsg(errorMsg);
|
||||
}
|
||||
|
||||
// 操作执行之前调用
|
||||
public static void beforeHandleLog(Log sysLog,
|
||||
ProceedingJoinPoint joinPoint,
|
||||
SysOperLog sysOperLog) {
|
||||
|
||||
// 设置操作模块名称
|
||||
sysOperLog.setTitle(sysLog.title());
|
||||
sysOperLog.setOperatorType(sysLog.operatorType().name());
|
||||
|
||||
// 获取目标方法信息
|
||||
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
sysOperLog.setMethod(method.getDeclaringClass().getName());
|
||||
|
||||
// 获取请求相关参数
|
||||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes)
|
||||
RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = requestAttributes.getRequest();
|
||||
sysOperLog.setRequestMethod(request.getMethod());
|
||||
sysOperLog.setOperUrl(request.getRequestURI());
|
||||
sysOperLog.setOperIp(request.getRemoteAddr());
|
||||
|
||||
// 设置请求参数
|
||||
if (sysLog.isSaveRequestData()) {
|
||||
String requestMethod = sysOperLog.getRequestMethod();
|
||||
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
|
||||
String params = Arrays.toString(joinPoint.getArgs());
|
||||
sysOperLog.setOperParam(params);
|
||||
}
|
||||
}
|
||||
sysOperLog.setOperName(BaseContext.getSysUser().getName());
|
||||
}
|
||||
}
|
|
@ -21,7 +21,8 @@ public class GlobalExceptionHandler {
|
|||
@ResponseBody
|
||||
public Result<Object> exceptionHandler(BunnyException exception) {
|
||||
log.error("GlobalExceptionHandler===>自定义异常信息:{}", exception.getMessage());
|
||||
return Result.error(exception.getCode(), exception.getMessage());
|
||||
Integer code = exception.getCode() != null ? exception.getCode() : 500;
|
||||
return Result.error(null, code, exception.getMessage());
|
||||
}
|
||||
|
||||
// 运行时异常信息
|
||||
|
@ -29,7 +30,8 @@ public class GlobalExceptionHandler {
|
|||
@ResponseBody
|
||||
public Result<Object> exceptionHandler(RuntimeException exception) {
|
||||
log.error("GlobalExceptionHandler===>运行时异常信息:{}", exception.getMessage());
|
||||
return Result.error(500, "出错了啦");
|
||||
|
||||
return Result.error(null, 500, "出错了啦");
|
||||
}
|
||||
|
||||
// 捕获系统异常
|
||||
|
@ -37,7 +39,8 @@ public class GlobalExceptionHandler {
|
|||
@ResponseBody
|
||||
public Result<Object> error(Exception exception) {
|
||||
log.error("GlobalExceptionHandler===>系统异常信息:{}", exception.getMessage());
|
||||
return Result.error(exception.getMessage());
|
||||
|
||||
return Result.error(null, 500, exception.getMessage());
|
||||
}
|
||||
|
||||
// 特定异常处理
|
||||
|
@ -45,7 +48,7 @@ public class GlobalExceptionHandler {
|
|||
@ResponseBody
|
||||
public Result<Object> error(ArithmeticException exception) {
|
||||
log.error("GlobalExceptionHandler===>特定异常信息:{}", exception.getMessage());
|
||||
return Result.error(null, exception.getMessage());
|
||||
return Result.error(null, 500, exception.getMessage());
|
||||
}
|
||||
|
||||
// spring security异常
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
<artifactId>common-util</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.atguigu</groupId>
|
||||
<artifactId>common-log</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- spring boot web开发所需要的起步依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.atguigu.spzx.manger;
|
||||
|
||||
import com.atguigu.log.annotation.EnableLogAspect;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
|
@ -14,6 +15,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||
@EnableCaching// 开启缓存注解
|
||||
@EnableScheduling
|
||||
@ComponentScan("com.atguigu")
|
||||
@EnableLogAspect// 开启切面类
|
||||
@MapperScan("com.atguigu.spzx.manger.mapper")
|
||||
@Slf4j
|
||||
public class MangerApplication {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.atguigu.spzx.manger.controller;
|
||||
|
||||
import com.atguigu.log.annotation.Log;
|
||||
import com.atguigu.log.enums.OperatorType;
|
||||
import com.atguigu.spzx.manger.service.CategoryService;
|
||||
import com.atguigu.spzx.model.entity.product.Category;
|
||||
import com.atguigu.spzx.model.vo.result.Result;
|
||||
|
@ -19,6 +21,8 @@ public class CategoryController {
|
|||
@Autowired
|
||||
private CategoryService categoryService;
|
||||
|
||||
|
||||
@Log(title = "根据parentId获取下级节点", businessType = 0, operatorType = OperatorType.MANAGE)
|
||||
@Operation(summary = "根据parentId获取下级节点", description = "根据parentId获取下级节点")
|
||||
@GetMapping(value = "findCategoryList/{parentId}")
|
||||
public Result<List<Category>> findByParentId(@PathVariable Long parentId) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.atguigu.spzx.manger.controller;
|
||||
|
||||
import com.atguigu.log.annotation.Log;
|
||||
import com.atguigu.log.enums.OperatorType;
|
||||
import com.atguigu.spzx.manger.service.CategoryBrandService;
|
||||
import com.atguigu.spzx.manger.service.ProductService;
|
||||
import com.atguigu.spzx.model.dto.product.ProductDto;
|
||||
|
@ -46,6 +48,7 @@ public class ProductController {
|
|||
return Result.success();
|
||||
}
|
||||
|
||||
@Log(title = "查询商品详情", businessType = 0, operatorType = OperatorType.MANAGE)
|
||||
@Operation(summary = "查询商品详情", description = "查询商品详情")
|
||||
@GetMapping("getById/{id}")
|
||||
public Result<Product> getById(@PathVariable Long id) {
|
||||
|
@ -76,7 +79,7 @@ public class ProductController {
|
|||
|
||||
@Operation(summary = "商品上下架", description = "商品上下架")
|
||||
@GetMapping("/updateStatus/{id}/{status}")
|
||||
public Result updateStatus(@PathVariable Long id, @PathVariable Integer status) {
|
||||
public Result<Product> updateStatus(@PathVariable Long id, @PathVariable Integer status) {
|
||||
productService.updateStatus(id, status);
|
||||
return Result.build(null, ResultCodeEnum.SUCCESS);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.atguigu.spzx.manger.mapper;
|
||||
|
||||
import com.atguigu.spzx.model.entity.system.SysOperLog;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysOperaLogMapper {
|
||||
/**
|
||||
* 异步执行保存日志操作
|
||||
*
|
||||
* @param sysOperaLog SysOperaLog
|
||||
*/
|
||||
void insert(SysOperLog sysOperaLog);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.atguigu.spzx.manger.service.impl;
|
||||
|
||||
import com.atguigu.log.service.AsyncOperaLogService;
|
||||
import com.atguigu.spzx.manger.mapper.SysOperaLogMapper;
|
||||
import com.atguigu.spzx.model.entity.system.SysOperLog;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AsyncOperaLogServiceImpl implements AsyncOperaLogService {
|
||||
@Autowired
|
||||
private SysOperaLogMapper sysOperaLogMapper;
|
||||
|
||||
/**
|
||||
* 异步执行保存日志操作
|
||||
*
|
||||
* @param sysOperaLog SysOperLog
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
public void saveSysOperaLog(SysOperLog sysOperaLog) {
|
||||
sysOperaLogMapper.insert(sysOperaLog);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="com.atguigu.spzx.manger.mapper.OrderInfoMapper">
|
||||
|
||||
|
||||
<!-- 查询指定日期产生的订单数据 -->
|
||||
<select id="selectOrderStatistics" resultType="com.atguigu.spzx.model.entity.order.OrderStatistics">
|
||||
select DATE_FORMAT(oi.create_time, '%Y-%m-%d') orderDate,
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="com.atguigu.spzx.manger.mapper.SysOperaLogMapper">
|
||||
|
||||
<!-- 异步执行保存日志操作 -->
|
||||
<insert id="insert">
|
||||
insert into sys_oper_log (id, title, method, request_method, operator_type, oper_name, oper_url, oper_ip,
|
||||
oper_param, json_result, status, error_msg)
|
||||
values (#{id}, #{title}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{operUrl}, #{operIp},
|
||||
#{operParam}, #{jsonResult}, #{status}, #{errorMsg})
|
||||
</insert>
|
||||
</mapper>
|
|
@ -7,42 +7,40 @@ import lombok.Data;
|
|||
@Data
|
||||
@Schema(description = "SysOperLog")
|
||||
public class SysOperLog extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@Schema(description = "模块标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "模块标题")
|
||||
private String title;
|
||||
@Schema(description = "方法名称")
|
||||
private String method;
|
||||
|
||||
@Schema(description = "方法名称")
|
||||
private String method;
|
||||
@Schema(description = "请求方式")
|
||||
private String requestMethod;
|
||||
|
||||
@Schema(description = "请求方式")
|
||||
private String requestMethod;
|
||||
private Integer businessType; // 业务类型(0其它 1新增 2修改 3删除)
|
||||
|
||||
private Integer businessType ; // 业务类型(0其它 1新增 2修改 3删除)
|
||||
@Schema(description = "操作类别(0其它 1后台用户 2手机端用户)")
|
||||
private String operatorType;
|
||||
|
||||
@Schema(description = "操作类别(0其它 1后台用户 2手机端用户)")
|
||||
private String operatorType;
|
||||
@Schema(description = "操作人员")
|
||||
private String operName;
|
||||
|
||||
@Schema(description = "操作人员")
|
||||
private String operName;
|
||||
@Schema(description = "请求URL")
|
||||
private String operUrl;
|
||||
|
||||
@Schema(description = "请求URL")
|
||||
private String operUrl;
|
||||
@Schema(description = "主机地址")
|
||||
private String operIp;
|
||||
|
||||
@Schema(description = "主机地址")
|
||||
private String operIp;
|
||||
@Schema(description = "请求参数")
|
||||
private String operParam;
|
||||
|
||||
@Schema(description = "请求参数")
|
||||
private String operParam;
|
||||
@Schema(description = "返回参数")
|
||||
private String jsonResult;
|
||||
|
||||
@Schema(description = "返回参数")
|
||||
private String jsonResult;
|
||||
|
||||
@Schema(description = "操作状态(0正常 1异常)")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "错误消息")
|
||||
private String errorMsg;
|
||||
@Schema(description = "操作状态(0正常 1异常)")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "错误消息")
|
||||
private String errorMsg;
|
||||
}
|
Loading…
Reference in New Issue