SpringBoot3+Vue3集成AOP系统日志

建表logs

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

在pom.xml导入AOP依赖

 <dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-aop</artifactId>

</dependency>

获取 IP 地址工具类 IpUtils.java

import javax.servlet.http.HttpServletRequest;

public class IpUtils {

    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }

}

自定义注解 @HoneyLogs

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HoneyLogs {
    // 操作的模块
    String operation();
    // 操作类型
    String type();
}

切面 LogAspect.java

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ArrayUtil;
import com.example.springboot.common.HoneyLogs;
import com.example.springboot.entity.Logs;
import com.example.springboot.entity.User;
import com.example.springboot.service.LogsService;
import com.example.springboot.utils.IpUtils;
import com.example.springboot.utils.TokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Component
@Aspect
@Slf4j
public class LogsAspect {

    @Resource
    LogsService logsService;

    @AfterReturning(pointcut = "@annotation(honeyLogs)", returning = "jsonResult")
    public void recordLog(JoinPoint joinPoint, HoneyLogs honeyLogs, Object jsonResult) {
        // 获取当前登录的用户的信息
        User loginUser = TokenUtils.getCurrentUser();
        if (loginUser == null) { // 用户未登录的情况下  loginUser是null  是null的话我们就要从参数里面获取操作人信息
            // 登录、注册
            Object[] args = joinPoint.getArgs();
            if (ArrayUtil.isNotEmpty(args)) {
                if (args[0] instanceof User) {
                    loginUser = (User) args[0];
                }
            }
        }
        if (loginUser == null) {
            log.error("记录日志信息报错,未获取到当前操作用户信息");
            return;
        }
        // 获取HttpServletRequest对象
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();

        // 获取到请求的ip
        String ip = IpUtils.getIpAddr(request);
        Logs logs = Logs.builder()
                .operation(honeyLogs.operation())
                .type(honeyLogs.type())
                .ip(ip)
                .user(loginUser.getUsername())
                .time(DateUtil.now())
                .build();

        ThreadUtil.execAsync(() -> {
            // 异步记录日志信息
            logsService.save(logs);
        });
    }

}

Logs.java

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Logs {
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String operation;
    private String type;
    private String ip;
    private String user;
    private String time;
}

LogsController.java

package com.example.controller;

import com.example.common.Result;
import com.example.entity.Logs;
import com.example.service.AdminService;
import com.example.service.LogsService;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @program: 双选系统
 * @description: 日志
 * @author: 
 * @create: 
 **/
@RestController
@RequestMapping("/logs")
public class LogsController {

    @Autowired
    LogsService logsService;

    @Autowired
    AdminService adminService;

    /**
    * @Description: 根据操作模块日志表分页查询
    * @Param: [logs, pageNum, pageSize]
    * @return: com.github.pagehelper.PageInfo
    * @Author: 
    * @Date: 
    */
    @GetMapping("selectPage")
    public Result selectPage(Logs logs,
                               @RequestParam(defaultValue = "1") Integer pageNum,
                               @RequestParam(defaultValue = "10") Integer pageSize) {

        PageInfo pageInfo = logsService.selectPage(logs,pageNum,pageSize);
        return Result.success(pageInfo);
    }
    /**
     * 删除信息
     */
    @DeleteMapping("/delete/{id}")
    public Result delete(@PathVariable Integer id) {
        logsService.removeById(id);
        return Result.success();
    }
    /**
     * 批量删除信息
     */
    @DeleteMapping("/delete/batch")
    public Result batchDelete(@RequestBody List<Integer> ids) {
        logsService.removeBatchByIds(ids);
        return Result.success();
    }

}

logs.vue

<template>
  <div>
    <div class="card" style="margin-bottom: 5px;">
      <el-input style="width: 200px" placeholder="查询模块" v-model="data.operation"></el-input>
      <!-- <el-select style="margin: 0 5px" v-model="data.type">
        <el-option v-for="item in ['新增', '修改', '删除']" :key="item" :value="item" :label="item"></el-option>
      </el-select> -->
      <!-- <el-input style="width: 200px" placeholder="查询操作人" v-model="data.optUser"></el-input> -->
      <el-button type="primary" style="margin-left: 10px" @click="load">查询</el-button>
      <el-button type="info" @click="reset">重置</el-button>
    </div>
    <div class="card">
      <!-- <div style="margin: 10px 0">
        <el-button type="danger" plain @click="delBatch">批量删除</el-button>
      </div> -->
    <el-table :data="data.tableData" stripe :header-cell-style="{ backgroundColor: 'aliceblue', color: '#666' }">
      <!-- <el-table-column type="selection" width="55" align="center"></el-table-column> -->
      <el-table-column label="序号">
          <template #default="scope">  
            {{ scope.$index + 1 }}  
          </template>
        </el-table-column>
      <el-table-column prop="operation" label="操作模块"></el-table-column>
      <el-table-column prop="type" label="操作类型">
        <template v-slot="scope">
          <el-tag type="primary" v-if="scope.row.type === '新增'">{{ scope.row.type }}</el-tag>
          <el-tag type="info" v-if="scope.row.type === '修改'">{{ scope.row.type }}</el-tag>
          <el-tag type="danger" v-if="scope.row.type === '删除'">{{ scope.row.type }}</el-tag>
          <el-tag type="danger" v-if="scope.row.type === '批量删除'">{{ scope.row.type }}</el-tag>
          <el-tag type="success" v-if="scope.row.type === '登录'">{{ scope.row.type }}</el-tag>
          <el-tag type="success" v-if="scope.row.type === '注册'">{{ scope.row.type }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="ip" label="操作人IP"></el-table-column>
      <el-table-column prop="user" label="操作人"></el-table-column>
      <el-table-column prop="time" label="操作时间"></el-table-column>
      <el-table-column label="操作" align="center" width="180">
        <template #default="scope">
          <el-button size="small" type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    </div>
    <div class="card">
      <el-pagination background layout="total, sizes, prev, pager, next, jumper"
      :page-sizes="[1, 5, 10, 50]"
       v-model:page-size="data.pageSize"
       v-model:current-page="data.pageNum" :total="data.total"
       @size-change="handleSizeChange"
       @current-change="handleCurrentChange"/>
    </div>

  </div>
</template>

<script setup>
import { reactive } from 'vue'
import request from '@/utils/request'
import {ElMessageBox, ElMessage} from "element-plus"

const data = reactive({
  formVisible : false,
  form:{},
  name:"",
  pageSize:10,
  pageNum:1,
  total:0,
  tableData:[],
  operation: '',
  user: JSON.parse(localStorage.getItem('honey-user') || '{}'),
  ids: [],
  type: '',
  optUser: '',
})

//跳转页码
const handleCurrentChange = (number) => {
  data.pageNum = number
  load()
}
//修改每页大小
const handleSizeChange = (number)=> {
  data.pageSize = number
  load()
}
//重置
const reset = () => {
  data.operation = ""
  load()
}
//查询
const load = ()=> {
  request.get('/logs/selectPage',{
    params:{
      pageNum:data.pageNum,
      pageSize:data.pageSize,
      operation:data.operation
      
    }
  }).then(res => {
    if(res.code === '200'){
      ElMessage.success("操作成功!")
      data.tableData = res.data?.list
      data.total = res.data.total
    }else{
      ElMessage.error(res.msg)
    }
  })
}
//删除
const handleDelete = (id) => {
  ElMessageBox.confirm('删除后数据无法恢复,您确定删除吗?', '删除确认', { type: 'warning' }).then(res => {
    request.delete('/logs/delete/'+id).then(res => {
      if (res.code === '200') {
        load()
      } else {
        ElMessage.error(res.msg)
      }
    })
  }).catch(err => {})
}
load()
</script>

<style>
.el-tooltip__popper {
  max-width: 300px !important;
}
</style>

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一个开源的Java框架,用于快速构建基于Java的企业级应用程序。Vue是一个开源的JavaScript框架,用于构建用户界面。 在你提到的日历签到系统中,可以使用Spring Boot作为后端框架,提供API接口和数据处理功能。Vue可以作为前端框架,用于构建用户界面,与后端进行数据交互和展示。 首先,你可以使用Spring Boot创建一个基本的Java项目。在项目中,你可以定义用户类、签到记录类等实体类,用于存储用户和签到信息。 接下来,你可以使用Spring Boot的数据库操作技术,如JPA或MyBatis,创建数据库表和关联关系。你可以创建用户表和签到记录表,将用户和签到信息存储在数据库中。 然后,你可以使用Spring Boot编写API接口,用于处理用户的注册、登录、签到等功能。通过定义控制器类和相应的方法,你可以实现用户的注册、登录和签到逻辑。 在前端方面,你可以使用Vue创建一个单页应用程序。你可以使用Vue的组件化思想,将用户界面分解为多个可重用的组件。你可以创建日历组件、签到记录组件等,然后将它们组合在一起。 通过Vue的路由功能,你可以定义不同页面之间的跳转和关系。例如,你可以创建一个注册页面、登录页面和签到页面,并通过路由进行相应的跳转。 最后,你可以使用Vue的异步请求功能,通过API接口与后端进行数据交互。你可以发送请求,获取用户和签到信息,并在前端展示出来。 总的来说,通过使用Spring Boot构建后端API接口,Vue构建前端用户界面,你可以实现一个基于Spring BootVue的日历签到系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值