• SpringBoot+Vue实现AOP系统日志功能


    AOP扫盲:Spring AOP (面向切面编程)原理与代理模式—实例演示

    logs表:

    1. CREATE TABLE `logs` (
    2. `id` int(11) NOT NULL AUTO_INCREMENT,
    3. `operation` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '操作名称',
    4. `type` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '操作类型',
    5. `ip` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'ip地址',
    6. `user` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '操作人',
    7. `time` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '操作时间',
    8. PRIMARY KEY (`id`)
    9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统日志';

    aop依赖:

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-aopartifactId>
    4. dependency>

    获取IP地址工具类 IpUtils.java:

    1. import javax.servlet.http.HttpServletRequest;
    2. public class IpUtils {
    3. public static String getIpAddr(HttpServletRequest request) {
    4. String ip = request.getHeader("x-forwarded-for");
    5. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    6. ip = request.getHeader("Proxy-Client-IP");
    7. }
    8. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    9. ip = request.getHeader("X-Forwarded-For");
    10. }
    11. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    12. ip = request.getHeader("WL-Proxy-Client-IP");
    13. }
    14. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    15. ip = request.getHeader("X-Real-IP");
    16. }
    17. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    18. ip = request.getRemoteAddr();
    19. }
    20. return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    21. }
    22. }

    自定义注解 @HoneyLogs:

    1. import java.lang.annotation.*;
    2. @Target(ElementType.METHOD)
    3. @Retention(RetentionPolicy.RUNTIME)
    4. @Documented
    5. public @interface HoneyLogs {
    6. // 操作的模块
    7. String operation();
    8. // 操作类型
    9. String type();
    10. }

    切面 LogAspect.java:

    1. import cn.hutool.core.date.DateUtil;
    2. import cn.hutool.core.thread.ThreadUtil;
    3. import cn.hutool.core.util.ArrayUtil;
    4. import com.example.springboot.common.HoneyLogs;
    5. import com.example.springboot.entity.Logs;
    6. import com.example.springboot.entity.User;
    7. import com.example.springboot.service.LogsService;
    8. import com.example.springboot.utils.IpUtils;
    9. import com.example.springboot.utils.TokenUtils;
    10. import lombok.extern.slf4j.Slf4j;
    11. import org.aspectj.lang.JoinPoint;
    12. import org.aspectj.lang.annotation.AfterReturning;
    13. import org.aspectj.lang.annotation.Aspect;
    14. import org.springframework.stereotype.Component;
    15. import org.springframework.web.context.request.RequestContextHolder;
    16. import org.springframework.web.context.request.ServletRequestAttributes;
    17. import javax.annotation.Resource;
    18. import javax.servlet.http.HttpServletRequest;
    19. @Component
    20. @Aspect
    21. @Slf4j
    22. public class LogsAspect {
    23. @Resource
    24. LogsService logsService;
    25. @AfterReturning(pointcut = "@annotation(honeyLogs)", returning = "jsonResult")
    26. public void recordLog(JoinPoint joinPoint, HoneyLogs honeyLogs, Object jsonResult) {
    27. // 获取当前登录的用户的信息
    28. User loginUser = TokenUtils.getCurrentUser();
    29. if (loginUser == null) { // 用户未登录的情况下 loginUser是null 是null的话我们就要从参数里面获取操作人信息
    30. // 登录、注册
    31. Object[] args = joinPoint.getArgs();
    32. if (ArrayUtil.isNotEmpty(args)) {
    33. if (args[0] instanceof User) {
    34. loginUser = (User) args[0];
    35. }
    36. }
    37. }
    38. if (loginUser == null) {
    39. log.error("记录日志信息报错,未获取到当前操作用户信息");
    40. return;
    41. }
    42. // 获取HttpServletRequest对象
    43. ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    44. HttpServletRequest request = servletRequestAttributes.getRequest();
    45. // 获取到请求的ip
    46. String ip = IpUtils.getIpAddr(request);
    47. Logs logs = Logs.builder()
    48. .operation(honeyLogs.operation())
    49. .type(honeyLogs.type())
    50. .ip(ip)
    51. .user(loginUser.getUsername())
    52. .time(DateUtil.now())
    53. .build();
    54. ThreadUtil.execAsync(() -> {
    55. // 异步记录日志信息
    56. logsService.save(logs);
    57. });
    58. }
    59. }

    Logs.java

    1. import com.baomidou.mybatisplus.annotation.IdType;
    2. import com.baomidou.mybatisplus.annotation.TableId;
    3. import lombok.AllArgsConstructor;
    4. import lombok.Builder;
    5. import lombok.Data;
    6. import lombok.NoArgsConstructor;
    7. @Data
    8. @AllArgsConstructor
    9. @NoArgsConstructor
    10. @Builder
    11. public class Logs {
    12. @TableId(type = IdType.AUTO)
    13. private Integer id;
    14. private String operation;
    15. private String type;
    16. private String ip;
    17. private String user;
    18. private String time;
    19. }

    LogsController.java

    1. import cn.hutool.core.util.StrUtil;
    2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    3. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    4. import com.example.springboot.common.Result;
    5. import com.example.springboot.entity.Logs;
    6. import com.example.springboot.service.LogsService;
    7. import com.example.springboot.service.UserService;
    8. import org.springframework.beans.factory.annotation.Autowired;
    9. import org.springframework.web.bind.annotation.*;
    10. import java.util.List;
    11. /**
    12. * 系统日志相关接口
    13. */
    14. @RestController
    15. @RequestMapping("/logs")
    16. public class LogsController {
    17. @Autowired
    18. LogsService logsService;
    19. @Autowired
    20. UserService userService;
    21. /**
    22. * 删除信息
    23. */
    24. @DeleteMapping("/delete/{id}")
    25. public Result delete(@PathVariable Integer id) {
    26. logsService.removeById(id);
    27. return Result.success();
    28. }
    29. /**
    30. * 批量删除信息
    31. */
    32. @DeleteMapping("/delete/batch")
    33. public Result batchDelete(@RequestBody List ids) {
    34. logsService.removeBatchByIds(ids);
    35. return Result.success();
    36. }
    37. /**
    38. * 多条件模糊查询信息
    39. * pageNum 当前的页码
    40. * pageSize 每页查询的个数
    41. */
    42. @GetMapping("/selectByPage")
    43. public Result selectByPage(@RequestParam Integer pageNum,
    44. @RequestParam Integer pageSize,
    45. @RequestParam String operation) {
    46. QueryWrapper queryWrapper = new QueryWrapper().orderByDesc("id"); // 默认倒序,让最新的数据在最上面
    47. queryWrapper.like(StrUtil.isNotBlank(operation), "operation", operation);
    48. Page page = logsService.page(new Page<>(pageNum, pageSize), queryWrapper);
    49. return Result.success(page);
    50. }
    51. }

    前端:

    Logs.vue:

  • 相关阅读:
    安科瑞单相无线预付费电能表DDSY1352-NK技术要求-Susie 周
    1024程序员节主题征文 | 35种语言输出1024
    EfficientNet:通过模型效率彻底改变深度学习
    【仿牛客网笔记】项目进阶,构建安全高效的企业服务——热帖排行
    我第一个开源AI小产品-video2blog即将正式发布
    Google Earth Engine(GEE)——sentinel-1数据中乌克兰附近数据缺失轨道36缺失
    LinkedList源码分享
    打造一个极度舒适的Chrome扩展项目开发环境
    C#11新特性之原始字符串
    Rust编程-I/O
  • 原文地址:https://blog.csdn.net/weixin_49171365/article/details/133634004