springboot中使用aop将操作日志记录到数据库

1.pom中引入aop依赖

<!--spring切面aop依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.创建实体类

import java.io.Serializable;

/**
 * 日志表
 * */
public class AdminLog implements Serializable {

    private static final long serialVersionUID = 7925874058046995566L;

    private String id;
    private String userId;//用户id 操作人ID
    private String userName;//用户名称 关联admin_user
    private String loginip;//登录ip
    private int type;//操作类型(0登录、1查询、2修改)
    private String url ; // 操作的url
    private String operation;//操作内容
    private String createtime;//操作时间
    private String remark;//备注
	/**生成getter和setter方法 */

3.自定义log注解

import java.lang.annotation.*;

/**
 * created by chen on 2019/8/6.
 * 配置自定义log注解类
 */
@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented //生成文档
public @interface MyLog {
    /** 操作事件     */
    String operation () default "";

    /** 日志类型 */
    int type ();
}

4.创建aop切面实现类

import com.***.admin.entity.AdminLog;
import com.***.admin.entity.AdminUser;
import com.***.util.UUIDUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/** 系统日志:切面处理类 */
@Aspect
@Component
public class SysLogAspect {
	/**我这里是使用log4j2把一些信息打印在控制台上面,可以不写 */
    private static final Logger log = LogManager.getLogger(SysLogAspect.class);

	/**操作数据库 */
    @Autowired
    private MyLogMapper myLogMapper;

    //定义切点 @Pointcut
    //在注解的位置切入代码
    @Pointcut("@annotation(com.***.log.MyLog)")
    public void logPoinCut() {
    }

    //切面 配置通知
    @Before("logPoinCut()")         //AfterReturning
    public void saveOperation(JoinPoint joinPoint) {
        log.info("---------------接口日志记录---------------");
        //用于保存日志
        AdminLog adminLog = new AdminLog();

        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();

        //获取操作--方法上的Log的值
        MyLog myLog = method.getAnnotation(MyLog.class);
        if (myLog != null) {
            //保存操作事件
            String operation = myLog.operation();
            adminLog.setOperation(operation);

            //保存日志类型
            int type = myLog.type();
            adminLog.setType(type);

            log.info("operation="+operation+",type="+type);
        }

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String requestURL = request.getRequestURL().toString();
        adminLog.setUrl(requestURL);
        // 客户端ip
        String ip = request.getRemoteAddr();
        adminLog.setLoginip(ip);
        // 操作人账号、姓名(需要提前将用户信息存到session)
        AdminUser user = (AdminUser) request.getSession().getAttribute("user");
        if(user != null) {
            String userId = user.getId();
            String userName = user.getName();
            adminLog.setUserId(userId);
            adminLog.setUserName(userName);
        }
        log.info("url="+requestURL,"ip="+ip);
       
        //调用service保存Operation实体类到数据库
        //我id使用的是UUID,不需要的可以注释掉
        String id = UUIDUtil.getUUID();
        adminLog.setId(id);
        myLogMapper.insert(adminLog);
    }
}

5.mapper层将操作添加到数据库

import com.***.admin.entity.AdminLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;

/**
 * created by Administrator on 2019/8/6.
 */
@Mapper
public interface MyLogMapper {
    @Insert("insert into admin_log" +
            " (id,user_id,user_name,loginip,type,url,operation,createtime,remark)" +
            " values" +
            " (#{id},#{userId},#{userName},#{loginip},#{type},#{url},#{operation},now(),#{remark})")
    void insert(AdminLog adminLog);
}

6.测试

@RestController
@RequestMapping("user")
public class UserController {

    private static final Logger log = LogManager.getLogger(UserController.class);

    @Autowired
    private UserService userService;
  
    /*测试操作日志保存到数据库*/
    /*假装登录,将用户信息存到session(方法是我之前写的懒得改,所以直接取的第一条数据)*/
    @RequestMapping("/login")
    public List<AdminUser> login(HttpServletRequest request){
        List<AdminUser> user = userService.getUser();
        AdminUser user1 = user.get(0);
        request.getSession().setAttribute("user",user1);
        return user;
    }
    /*记录日志*/
    @MyLog(operation = "查询用户信息",type = 1)
    @RequestMapping("/log")
    public List<AdminUser> insertLog(HttpServletRequest request){
        List<AdminUser> user = userService.getUser();
        return user;
    }
}

然后是控制台打印信息
在这里插入图片描述
数据库信息
在这里插入图片描述

  • 8
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
你可以通过Spring AOP实现这个功能。具体步骤如下: 1. 创建一个实体类,用于保存错误日志信息,包括用户信息、请求url、方法、参数、异常信息等。 2. 创建一个切面类,使用@Aspect注解标注,该切面类定义一个@Before通知,用于捕获Controller抛出的异常,并将异常信息和其他相关信息保存到数据库。 3. 在切面类通过@Pointcut注解指定切入点,即对哪些Controller的方法进行切面处理。 4. 在切面类使用@Autowired注解注入实体类对应的Repository,然后在@Before通知调用Repository的方法将错误信息保存到数据库。 具体实现细节可以参考以下代码: ```java @Aspect @Component public class ErrorLogAspect { @Autowired private ErrorLogRepository errorLogRepository; @Pointcut("execution(* com.example.demo.controller..*.*(..))") public void logPointcut() {} @Before("logPointcut()") public void logError(JoinPoint joinPoint) { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); ErrorLog errorLog = new ErrorLog(); errorLog.setUserId(request.getHeader("userId")); // 从请求头获取用户信息 errorLog.setUrl(request.getRequestURI()); // 获取请求url errorLog.setMethod(joinPoint.getSignature().toShortString()); // 获取方法名 errorLog.setArgs(Arrays.toString(joinPoint.getArgs())); // 获取方法参数 errorLog.setExceptionMessage(getExceptionMessage(joinPoint)); // 获取异常信息 errorLogRepository.save(errorLog); // 保存错误日志数据库 } private String getExceptionMessage(JoinPoint joinPoint) { Throwable ex = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(ExceptionHandler.class).value(); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); ex.printStackTrace(pw); return sw.toString(); } } ``` 其,ErrorLog是保存错误日志信息的实体类,ErrorLogRepository是对应的Repository。在logError方法,通过JoinPoint获取方法名、方法参数等信息,通过RequestContextHolder获取请求信息,最后将错误日志保存到数据库。getExceptionMessage方法用于获取异常信息。在Controller,需要使用@ExceptionHandler注解来捕获异常,并将异常信息保存到数据库

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值