• SpringBoot使用LogAspect的切面日志


    目录

    1、引入依赖

    2、切面方法

    3、Log类

     4、LogAspect类

    5、SysLog实体类

    6、服务类和服务实现类

    7、实际调用


    1、引入依赖

    1. <dependency>
    2. <groupId>org.aspectjgroupId>
    3. <artifactId>aspectjweaverartifactId>
    4. dependency>
    5. <dependency>
    6. <groupId>org.springframework.bootgroupId>
    7. <artifactId>spring-boot-starter-aopartifactId>
    8. <scope>testscope>
    9. dependency>
    10. <dependencies>
    11. <dependency>
    12. <groupId>org.projectlombokgroupId>
    13. <artifactId>lombokartifactId>
    14. dependency>
    15. dependencies>

    2、切面方法

    切面方法说明如下:

    @Aspect 作用是把当前类标识为一个切面供容器读取
    @Pointcut (切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
    @Before 标识一个前置增强方法,相当于BeforeAdvice的功能
    @AfterReturning 后置增强,相当于AfterReturningAdvice,方法退出时执行
    @AfterThrowing 异常抛出增强,相当于ThrowsAdvice
    @After final增强,不管是抛出异常或者正常退出都会执行
    @Around 环绕增强,相当于MethodInterceptor

    3、Log类

    1. package com.shucha.deveiface.biz.aspect;
    2. import java.lang.annotation.*;
    3. /**
    4. * @author tqf
    5. * @Description 自定义拦截日志
    6. * @Version 1.0
    7. * @since 2022-08-08 15:28
    8. */
    9. @Target({ElementType.PARAMETER, ElementType.METHOD})
    10. @Retention(RetentionPolicy.RUNTIME)
    11. @Documented
    12. public @interface Log {
    13. /**
    14. * 操作描述 查询、新增、修改、删除等
    15. * @return
    16. */
    17. String menu() default "";
    18. /**
    19. * 接口名称 不需要填写 可以通过request.getRequestURL().toString(); 获取
    20. * @return
    21. */
    22. String operation() default "";
    23. /**
    24. * 是否记录请求参数数据, 默认true: 记录; false:不记录
    25. *
    26. * @return
    27. */
    28. boolean isData() default true;
    29. }

     4、LogAspect类

    1. package com.shucha.deveiface.biz.aspect;
    2. import com.alibaba.fastjson.JSON;
    3. import com.alibaba.fastjson.serializer.SerializerFeature;
    4. import com.sdy.common.model.Response;
    5. import com.sdy.mvc.controller.BaseController;
    6. import com.sdy.mvc.utils.HttpUtil;
    7. import com.shucha.deveiface.biz.model.SysLog;
    8. import com.shucha.deveiface.biz.service.SysLogService;
    9. import feign.Request;
    10. import lombok.extern.slf4j.Slf4j;
    11. import org.apache.commons.lang3.ArrayUtils;
    12. import org.aspectj.lang.JoinPoint;
    13. import org.aspectj.lang.ProceedingJoinPoint;
    14. import org.aspectj.lang.Signature;
    15. import org.aspectj.lang.annotation.*;
    16. import org.aspectj.lang.reflect.MethodSignature;
    17. import org.springframework.beans.factory.annotation.Autowired;
    18. import org.springframework.core.annotation.Order;
    19. import org.springframework.stereotype.Component;
    20. import org.springframework.web.context.request.RequestContextHolder;
    21. import org.springframework.web.context.request.ServletRequestAttributes;
    22. import javax.servlet.http.HttpServletRequest;
    23. import java.lang.reflect.Method;
    24. import java.lang.reflect.Parameter;
    25. import java.util.Date;
    26. import java.util.Enumeration;
    27. import java.util.HashMap;
    28. import java.util.Map;
    29. /**
    30. * @author tqf
    31. * @Description 日志切面类
    32. * @Version 1.0
    33. * @since 2022-08-08 15:28
    34. */
    35. @Aspect
    36. @Component
    37. @Slf4j
    38. @Order(1)
    39. public class LogAspect {
    40. @Autowired
    41. private SysLogService sysLogService;
    42. private final ThreadLocal startTime = new ThreadLocal<>();
    43. // 配置织入点
    44. @Pointcut("@annotation(Log)")
    45. public void logPointCut() {
    46. }
    47. @Before("logPointCut()")
    48. private void before() {
    49. startTime.set( System.currentTimeMillis());
    50. }
    51. /**
    52. * 处理完请求后执行
    53. * @param joinPoint
    54. * @param res
    55. * @throws Exception
    56. */
    57. @AfterReturning(returning = "res", pointcut = "logPointCut()")
    58. public void afterReturning(JoinPoint joinPoint, Response res) throws Exception {
    59. long nowTime = System.currentTimeMillis();
    60. HttpServletRequest request = getRequest();
    61. handleLog(joinPoint, null, res, nowTime, request);
    62. }
    63. /**
    64. * 拦截异常操作
    65. * @param joinPoint 切点
    66. * @param e 异常
    67. */
    68. @AfterThrowing(value = "logPointCut()", throwing = "e")
    69. public void doAfterThrowing(JoinPoint joinPoint, Exception e) throws Exception {
    70. // 从上下文中获取reqeust
    71. ServletRequestAttributes servletRequestAttributes =
    72. (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
    73. // HttpServletRequest request = getRequest();
    74. HttpServletRequest request = servletRequestAttributes.getRequest();
    75. handleLog(joinPoint, e, null, System.currentTimeMillis(), request);
    76. }
    77. protected void handleLog(final JoinPoint joinPoint, final Exception e, Response jsonResult, Long nowTime, HttpServletRequest request) throws Exception {
    78. Log controllerLog = getAnnotationLog(joinPoint);
    79. ProceedingJoinPoint point = (ProceedingJoinPoint)joinPoint;
    80. if (controllerLog == null) {
    81. return;
    82. }
    83. // 数据库日志
    84. SysLog sysLog = new SysLog();
    85. // 接口地址
    86. String requestUrl = request.getRequestURL().toString();
    87. // 请求的IP地址
    88. String ip = HttpUtil.getIpAddr(request);
    89. sysLog.setIp(ip);
    90. // 获取操作内容
    91. String content = controllerLog.menu();
    92. // 获取请求参数
    93. String requestData = "";
    94. if(controllerLog.isData()){
    95. requestData = getRequestParams(point, request);
    96. }
    97. if (jsonResult == null) {
    98. content = content + "--出现服务异常!";
    99. }
    100. if (jsonResult != null && !jsonResult.getSuccess()) {
    101. content = content + "--执行失败!";
    102. }
    103. sysLog.setContent(content)
    104. .setType(content)
    105. .setCreateTime(new Date())
    106. .setRequestUrl(requestUrl)
    107. .setRequestData(requestData);
    108. // 保存数据库
    109. sysLogService.save(sysLog);
    110. }
    111. /**
    112. * 是否存在注解,如果存在就获取
    113. */
    114. private Log getAnnotationLog(JoinPoint joinPoint) {
    115. Signature signature = joinPoint.getSignature();
    116. MethodSignature methodSignature = (MethodSignature) signature;
    117. Method method = methodSignature.getMethod();
    118. if (method != null) {
    119. return method.getAnnotation(Log.class);
    120. }
    121. return null;
    122. }
    123. private HttpServletRequest getRequest() {
    124. ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    125. return attributes.getRequest();
    126. }
    127. /**
    128. * 获取请求参数 json格式返回
    129. * @param request
    130. * @return
    131. */
    132. private String getParameterName(HttpServletRequest request){
    133. // 增加查询日志 获取所有查询的参数名称和值 json格式存储
    134. Map map = new HashMap();
    135. Enumeration paramNames = request.getParameterNames();
    136. while (paramNames.hasMoreElements()) {
    137. String paramName = (String) paramNames.nextElement();
    138. String[] paramValues = request.getParameterValues(paramName);
    139. if (paramValues.length == 1) {
    140. String paramValue = paramValues[0];
    141. if (paramValue.length() != 0) {
    142. map.put(paramName, paramValue);
    143. }
    144. }
    145. }
    146. return JSON.toJSONString(map);
    147. }
    148. /**
    149. * 获取请求参数
    150. * @param request
    151. * @return
    152. */
    153. public String getRequestParams(ProceedingJoinPoint point, HttpServletRequest request) {
    154. MethodSignature methodSignature = (MethodSignature)point.getSignature();
    155. Method method = methodSignature.getMethod();
    156. String queryString = null;
    157. String requestMethod = request.getMethod();
    158. if (requestMethod.equals(Request.HttpMethod.POST.name())) {
    159. //参数值
    160. Object[] args = ArrayUtils.toArray(point.getArgs());
    161. queryString = JSON.toJSONString(args[0], SerializerFeature.WriteMapNullValue);
    162. }
    163. else {
    164. //参数名
    165. Parameter[] parameters = method.getParameters();
    166. //参数值
    167. Object[] args = ArrayUtils.toArray(point.getArgs());
    168. Map map = new HashMap<>();
    169. for (int i = 0; i < parameters.length; i++) {
    170. map.put(parameters[i].getName(), args[i]);
    171. }
    172. queryString = JSON.toJSONString(map);
    173. }
    174. return queryString;
    175. }
    176. }

    5、SysLog实体类

    1. package com.shucha.deveiface.biz.model;
    2. import com.baomidou.mybatisplus.annotation.TableId;
    3. import com.fasterxml.jackson.annotation.JsonFormat;
    4. import com.sdy.common.model.BaseModel;
    5. import com.sdy.common.utils.DateUtil;
    6. import io.swagger.annotations.ApiModelProperty;
    7. import lombok.Data;
    8. import lombok.EqualsAndHashCode;
    9. import lombok.experimental.Accessors;
    10. import java.util.Date;
    11. /**
    12. *

    13. * 用户操作日志
    14. *

    15. *
    16. * @author tqf
    17. * @since 2022-08-08 15:25
    18. */
    19. @Data
    20. @EqualsAndHashCode(callSuper = true)
    21. @Accessors(chain = true)
    22. public class SysLog extends BaseModel {
    23. private static final long serialVersionUID = 1L;
    24. /**
    25. * 主键
    26. */
    27. @ApiModelProperty(value = "主键")
    28. @TableId
    29. private Long id;
    30. /**
    31. * 操作用户id
    32. */
    33. @ApiModelProperty(value = "操作用户id")
    34. private Long userId;
    35. @ApiModelProperty(value = "请求参数")
    36. private String requestData;
    37. @ApiModelProperty(value = "请求接口地址")
    38. private String requestUrl;
    39. /**
    40. * IP地址
    41. */
    42. @ApiModelProperty(value = "IP地址")
    43. private String ip;
    44. /**
    45. * 操作内容
    46. */
    47. @ApiModelProperty(value = "操作内容")
    48. private String content;
    49. /**
    50. * 操作类型
    51. */
    52. @ApiModelProperty(value = "操作类型")
    53. private String type;
    54. /**
    55. * 创建时间
    56. */
    57. @ApiModelProperty(value = "创建时间")
    58. @JsonFormat(pattern = DateUtil.DATETIME_FORMAT)
    59. private Date createTime;
    60. }

    创建表和插入数据

    1. SET NAMES utf8mb4;
    2. SET FOREIGN_KEY_CHECKS = 0;
    3. -- ----------------------------
    4. -- Table structure for sys_log
    5. -- ----------------------------
    6. DROP TABLE IF EXISTS `sys_log`;
    7. CREATE TABLE `sys_log` (
    8. `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
    9. `user_id` int(11) NULL DEFAULT NULL COMMENT '操作用户id',
    10. `ip` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT 'IP地址',
    11. `content` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '操作内容',
    12. `request_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '请求接口地址',
    13. `request_data` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '请求参数',
    14. `type` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '操作类型\r\n0:登陆\r\n1:新增用户\r\n2:开户\r\n3:用户基本信息编辑\r\n4:用户资源编辑\r\n5:新增角色\r\n6编辑角色\r\n7:角色权限编辑\r\n8:角色关联用户编辑\r\n9:新增菜单\r\n10:菜单编辑\r\n11:日志查询',
    15. `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
    16. PRIMARY KEY (`id`) USING BTREE,
    17. INDEX `idx_user_id`(`user_id`) USING BTREE
    18. ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '操作日志信息' ROW_FORMAT = Dynamic;
    19. -- ----------------------------
    20. -- Records of sys_log
    21. -- ----------------------------
    22. INSERT INTO `sys_log` VALUES (1, NULL, '192.168.0.111', '查询数据', 'http://192.168.0.111:50041/test/getData', '{}', '查询数据', '2022-08-08 17:21:51');
    23. INSERT INTO `sys_log` VALUES (2, NULL, '192.168.0.111', '新增数据发发发', NULL, NULL, NULL, NULL);
    24. INSERT INTO `sys_log` VALUES (3, NULL, '192.168.0.111', '新增数据', 'http://192.168.0.111:50041/test/saveData', '{\"content\":\"新增数据发发发\",\"createTime\":null,\"id\":2,\"ip\":\"192.168.0.111\",\"requestData\":null,\"requestUrl\":null,\"type\":null,\"userId\":null}', '新增数据', '2022-08-08 17:22:12');
    25. SET FOREIGN_KEY_CHECKS = 1;

     

    6、服务类和服务实现类

    1. package com.shucha.deveiface.biz.service;
    2. import com.sdy.mvc.service.BaseService;
    3. import com.shucha.deveiface.biz.model.SysLog;
    4. /**
    5. *

    6. * 用户操作日志 服务类
    7. *

    8. *
    9. * @author cgj
    10. * @since 2021-07-13
    11. */
    12. public interface SysLogService extends BaseService {
    13. }
    1. package com.shucha.deveiface.biz.service.impl;
    2. import com.sdy.mvc.service.impl.BaseServiceImpl;
    3. import com.shucha.deveiface.biz.mapper.SysLogMapper;
    4. import com.shucha.deveiface.biz.model.SysLog;
    5. import com.shucha.deveiface.biz.service.SysLogService;
    6. import lombok.extern.slf4j.Slf4j;
    7. import org.springframework.beans.factory.annotation.Autowired;
    8. import org.springframework.stereotype.Service;
    9. /**
    10. *

    11. * 用户操作日志 服务实现类
    12. *

    13. *
    14. * @author cgj
    15. * @since 2021-07-13
    16. */
    17. @Slf4j
    18. @Service
    19. public class SysLogServiceImpl extends BaseServiceImpl implements SysLogService {
    20. @Autowired
    21. private SysLogMapper sysLogMapper;
    22. }

    7、实际调用

    1. package com.shucha.deveiface.web.controller;
    2. import com.sdy.common.model.Response;
    3. import com.shucha.deveiface.biz.aspect.Log;
    4. import com.shucha.deveiface.biz.model.SysLog;
    5. import com.shucha.deveiface.biz.service.SysLogService;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.web.bind.annotation.*;
    8. /**
    9. * @author tqf
    10. * @Description
    11. * @Version 1.0
    12. * @since 2022-08-08 15:23
    13. */
    14. @RestController
    15. @RequestMapping("/test")
    16. public class TestController {
    17. @Autowired
    18. private SysLogService logService;
    19. @Log(menu = "查询数据")
    20. @GetMapping("/getData")
    21. public Response test(){
    22. return Response.success("请求成功");
    23. }
    24. @Log(menu = "新增数据")
    25. @PostMapping("/saveData")
    26. public Response saveData(@RequestBody SysLog sysLog){
    27. logService.save(sysLog);
    28. return Response.success();
    29. }
    30. }
  • 相关阅读:
    双位置继电器XJLS-8G/220
    Windows + Msys 下编译 TensorFlow 2.14
    分享一个项目:go `file_line`,在编译期得到源码行号,减少运行期runtime消耗
    Opencv形态学——腐蚀、膨胀、开运算与闭运算、梯度运算、礼帽、黑帽
    面试阿里、字节全都一面挂,被面试官说我的水平还不如应届生
    Qt之解析HTML
    WebShell 木马免杀过WAF
    【Linux】线程池
    【Hack The Box】windows练习-- Buff
    如何在虚拟机上安装linux操纵系统
  • 原文地址:https://blog.csdn.net/tanqingfu1/article/details/126230286