SpringBoot自定义注解实现操作日志(适用于毕设)

一 前言

        在初学spring时,难免会遇到自定义注解的需求,尤其是学习了一段时间,想和前端的小伙伴做一个前后端分离的项目,但是这个项目会涉及到登录日志和操作日志,此时,通过自定义日志注解的方式就显得格外重要。

二 开发环境说明

IDEA版本:2023.3.3

jdk:1.8

MySQL:5.7

        本次笔者采用的是SpringBoot的2.5.12版本,之所以没有选择3.X的版本,是因为所需要用到的hutool包暂时对SpringBoot3.x存在兼容性问题,之前在用3.x做日志的时候,遇到了一个很让人无语的问题,那就是HttpServletRequest的引用路径问题。在最新版的hutool工具中,HttpServletRequest的引用路径是javax.servlet.http.HttpServletRequest;而在3.x中引用路径变为了jakarta.servlet.http.HttpServletRequest。其实就是一个单词的区别,查看了源码,功能都是一样的,但是直接爆红,没办法只能采用2.x做了。

三 需求分析

        对于程序员来说,需求往往是行外人士提出的,所以每次拿到需求以后,我们都要养成一个需求分析的习惯。首先,我们需要记录一条数据,这条数据记录了某位用户在访问某个特定接口的时候做了哪些事情,例如当需要对用户做增加操作时,我们希望记录下是谁在什么时间通过什么IP地址或者是操作系统等新增了一条用户,或者是我们需要记录哪位用户在什么时间通过哪个IP地址和浏览器登录了这个系统,并且可以随时进行查看。

        那么重点在于记录这两个字。我们不可能要在每一个被访问的接口实现类中,都写上那么一部分新增日志的代码,这会大大增加工作量,因此如果可以在每一个特定接口上增加一个注解,只需要把注解内容补全,就可以知道用户做了些什么事情了。同时需要单独为日志做一个模块,方便我们日后通过网页查询。

那么我们整理一下:

1.做一个日志的增删改查;

2.自定义日志注解

四 需求的实现

1 创建一个spring项目来实现日志的增删改查。

1.1创建项目

        打开IDEA,依次点击file-new-project,选择Spring Initializr来创建SpringBoot项目,也可以访问Spring的官网https://start.spring.io/ 来创建。对与需要勾选的内容就不去过多赘述,反正不够可以在pom文件中加。

        如果采用了笔者的IDEA版本,那么需要在pom文件中修改Java版本,并且将项目的版本修改为1.8。

1.2 添加依赖并修改配置文件

依赖如下(省略创建项目时已经具备的依赖,其实就是SpringBoot的基础依赖)

<dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.5.3.1</version>
</dependency>
<dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.29</version>
</dependency>
<dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.22</version>
</dependency>
<dependency>
       <groupId>cn.hutool</groupId>
       <artifactId>hutool-all</artifactId>
       <version>5.8.12</version>
</dependency>

配置文件笔者采用的是properties风格,yml风格大同小异

server.port=8002
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&useInformationSchema=true
spring.datasource.username=root
spring.datasource.password=123456

至此,基础的配置完成。

1.3 利用Navicat创建数据库

1.4 在新建的项目中创建文件夹和文件

        以上是笔者创建的文件目录,对于controller、entity等文件夹不做过多赘述,如果有不明白的小伙伴,可以查看我另外一篇文章。

1.5 自定义注解

在目录中,有一个annotation文件夹,这里面放的就是日志的注解。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
    String value() default "未命名日志";
}

在aop文件夹中,存放改注解的切面

@Aspect
@Order
@Component
public class LogAop {
    @Pointcut("@annotation(com.example.log.annotation.LogAnnotation)")
    private void getLogPointCut() {
    }

    @AfterReturning(pointcut = "getLogPointCut()")
    public void doAfterReturning(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
        //这里操作人姓名暂时设置未知,具体操作的人,需要通过其他方法获取,这里仅对日志以及自定义注解的使用做简单介绍。
        String userName = "未知";
        // 异步记录日志
        LogUtil.writeLog(logAnnotation, userName);
    }
}

        我们可以看到最下面的两句话,其中一个注释为“异步记录日志”,就是调用了util文件夹中的LogUtil文件中的writeLog方法。一下是该方法的具体内容。

@Component
public class LogUtil{
    private static final LogService logService = SpringUtil.getBean(LogService.class);

    public static void writeLog(LogAnnotation logAnnotation, String userName) {
        logService.saveLog(logAnnotation,userName);
    }
}

        需要注意的是,在LogUtil中,必须加入@Component注解,来保证被SpringBoot扫描到。接下来就到了接口实现类中了。

@Service
public class LogServiceImpl extends ServiceImpl<LogMapper, Log> implements LogService {
    @Override
    public void saveLog(LogAnnotation logAnnotation, String userName) {
        HttpServletRequest request = getRequest();
        Log log = new Log();
        log.setName(userName);
        log.setType(LogEnum.OP_LOG.getValue());
        log.setTime(DateTime.now());
        log.setIp(IpUtil.getIp(request));
        log.setBrowser(OsUtil.getBrowser(request));
        log.setOs(OsUtil.getOs(request));
        this.save(log);
    }

    public static HttpServletRequest getRequest() {
        ServletRequestAttributes servletRequestAttributes= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return servletRequestAttributes.getRequest();
    }
}

        到了这一步,代表整个操作日志的逻辑就写完了。

1.6 运行与测试

        为方便演示,在controller文件夹中直接创建了一个DemoController文件。

@RestController
public class DemoController {
    @PostMapping("/add")
    @LogAnnotation("新增了一条数据")
    public String page(){
        return "新增了一项内容";
    }
}

        运行项目,通过postman调用该接口测试。

        可以看到,postman返回的内容,正好是controller文件中return的内容。然后去Navicat中找到这个表,并查看数据。

        可以清晰的看到,已经写入了一条数据,并且name中的内容和controller中自定义注解的内容相同。这就代表了这个注解已经生效并且可以正常的工作了。

五 应用拓展

        细心的小伙伴会发现,代码中的username其实是空值,这个值应该获取到的是操作人的姓名。之所以是空值,最大的原因就是这个demo根本没有登录环节,既然没有登录,那么更不会获取到登录人的相关信息。

        另外,上述内容仅讲述了自定义注解实现记录操作日志的方法,但是实际情况中,登录日志也是必不可少的一个环节。在这里提供两个解决思路,首先是仿照上述代码,分别自定义一个登录登出日志的注解,另外一个思路是与其他依赖配合直接书写登录登出日志。

        对于登录和登出,个人推荐采用sa-token,可以去它的官网进一步了解,(sa-token官网:Sa-Token)sa-token中附带了很多使用的API,比如执行登录、操作权限等,实现思路也很容易,就是在LogUtil中做一部分修改,加上implements SaTokenListener即可。

        如果你对上述代码有疑问,或者有更好的编写方式,欢迎留言评论,也可以在我另一个文章(基于vue+SpringBoot前后端分离毕设模板(最全的案例--附源码地址)_前后端分离模板-CSDN博客)中的源码内添加我的联系方式。

        

  • 32
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值