基于AOP实现登录日志和操作日志(新手入门版)

基于AOP实现登录日志和操作日志

  • 目录结构
  • 代码
  • PostMan测试代码
  • 控制台查看输出
  • 解析成JSON
  • 如果你觉得对你有帮助的话,请点赞收藏

目录结构

基于AOP实现登录日志和操作日志(新手入门版)_第1张图片

代码


package com.demo.mymaintest.constants;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 系统日志注解
 *
 * @author Mark [email protected]
 */
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target({ElementType.METHOD,ElementType.PARAMETER })
public @interface SysLog {

	String value() default "";

}

package com.demo.mymaintest.aop;


import com.alibaba.fastjson.JSONObject;
import com.demo.mymaintest.constants.SysLog;
import com.demo.mymaintest.entity.SysLogEntity;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统日志,切面处理类
 *
 * @author yhj
 */
@Aspect
@Component
public class SysLogAspect {

  // 定义切点 切点表达式指向SysLog注解,我们再业务方法上可以加上SysLog注解,然后所标注
  // 的方法都能进行日志记录
  @Pointcut("@annotation(com.demo.mymaintest.constants.SysLog)")
  public void logPointCut() {}

  @Around(value = "logPointCut()")
  private Object Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    HttpServletRequest request  = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    String requestURI = request.getRequestURI();
    String requestMethod = request.getMethod();
    String remoteAddr = request.getRemoteAddr();
    SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Long nowDate = System.currentTimeMillis(); // 步入时间戳
    String startTime = dateformat.format(nowDate);

    MethodSignature method1 = (MethodSignature) proceedingJoinPoint.getSignature();
    Class<?> currentClass = proceedingJoinPoint.getTarget().getClass();
    Object proceed = proceedingJoinPoint.proceed();
    List<Object> allArgs = Arrays.asList(proceedingJoinPoint.getArgs());
    List<Object> args =
        allArgs.stream()
            .map(
                arg -> {
                  if (!(arg instanceof HttpServletRequest)
                      && !(arg instanceof HttpServletResponse)) {
                    return arg;
                  } else {
                    return null;
                  }
                })
            .filter(arg -> arg != null)
            .collect(Collectors.toList());

    SysLogEntity sysLogEntity = new SysLogEntity();
    sysLogEntity.setUsername("登录人从request中获取");
    MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
    		Method method = signature.getMethod();
    SysLog syslog = method.getAnnotation(SysLog.class);
    if(syslog != null){
            //注解上的描述
            sysLogEntity.setOperation(syslog.value());
        }
    sysLogEntity.setRequestPath(requestURI);
    sysLogEntity.setRequestMethod(requestMethod);
    sysLogEntity.setCurrentTimeMills(startTime);
    sysLogEntity.setArgsType(getMethodArgumentTypeName(method1));
    sysLogEntity.setAllArgs(args);
    sysLogEntity.setResponseData(proceed != null ? proceed.toString() : "null");
    sysLogEntity.setExecuteTimeMills((System.currentTimeMillis() - nowDate) + "ms");
    sysLogEntity.setClassMethodLocation(currentClass.getName() + "." + method.getName());
    sysLogEntity.setRemoteAddr(remoteAddr);
    sysLogEntity.setNowTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    sysLogEntity.setResponseType(method.getReturnType().getName());

    // TODO 将sysLogEntity存入ES

    System.out.println(JSONObject.toJSONString(sysLogEntity));
    return proceed;
  }

  @AfterThrowing(value = "logPointCut()")
  private void AfterThrowing() {
    System.out.println("异常通知");
  }

  private Map<String, String> getMethodArgumentTypeName(MethodSignature method) {
    Map<String, String> map = new HashMap<>();
    String[] argTypeNames = method.getParameterNames();
    Class[] parameterTypes = method.getParameterTypes();
    for (int i = 0; i < parameterTypes.length; i++) {
      map.put(parameterTypes[i].getName(), argTypeNames[i]);
    }
    return map;
  }
}
package com.demo.mymaintest.controller;


import com.demo.mymaintest.constants.SysLog;
import com.demo.mymaintest.entity.BookEntity;
import com.demo.mymaintest.entity.SysUser;
import com.demo.mymaintest.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;

import org.springframework.web.bind.annotation.*;

/**
 * @ClassName TestApiController
 * @Author yhj
 * @Date 2023/7/15 13:22
 * @Description
 * @Version 1.0
 */

@RestController
@RequestMapping("/api")
@Slf4j
public class TestApiController {

    @PostMapping("/add")
    @SysLog(value = "添加数据测试")
    public R test(@RequestBody BookEntity bookEntity) {
        bookEntity.setBookImg("testImg");
        bookEntity.setBookIntro("书籍简介");
        return R.ok(200,"添加成功",bookEntity);
    }
    @PostMapping("/login")
    @SysLog(value = "用户登录")
    public ResponseEntity login(@RequestBody SysUser sysUser){
            String ok = "恭喜你登录成功";
            if(sysUser.getUserName().equals("test")){
                return ResponseEntity.ok(ok);
            }
            return ResponseEntity.ok().body("登录失败");
    }
    @DeleteMapping("/delete")
    @SysLog("删除")
    public ResponseEntity<String> deleteById(@PathVariable("id") Integer id){
        return ResponseEntity.ok("删除成功");
    }
}

package com.demo.mymaintest.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

/**
 *
 *
 * @author yhj
 * @date 2023-06-12 09:47:10
 */
@Data
public class BookEntity implements Serializable {
	private static final long serialVersionUID = 1L;
	/**
	 *
	 */
	@TableId
	private Integer bookId;
	/**
	 * 书籍编号
	 */
	private String bookIsbn;
	/**
	 * 书籍名称
	 */
	private String bookName;
	/**
	 * 书籍价格
	 */
	private Float bookPrice;

	/**
	 * 书籍封面
	 */
	private String bookImg;
	/**
	 * 简介
	 */
	private String bookIntro;
	/**
	 * 已购数量
	 */
	private int bookPurchasedNumber;
}

package com.demo.mymaintest.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Date;

/**
 * 

* 用户表 *

* * @author jerry * @since 2021-06-16 */
@Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) public class SysUser implements Serializable { private static final long serialVersionUID=1L; @TableId(value = "id", type = IdType.AUTO) private Long id; /** * 用户编号 */ //@ApiModelProperty("用户编号") private String userCode; /** * 用户名 */ //@ApiModelProperty("用户名") private String userName; /** * 登录密码 */ //@ApiModelProperty("登录密码") private String password; /** * 真实姓名 */ //@ApiModelProperty("真实姓名") private String realName; /** * 手机号码 */ //@ApiModelProperty("手机号码") private String mobile; /** * 邮箱地址 */ //@ApiModelProperty("邮箱地址") private String email; /** * 组织机构id */ //@ApiModelProperty("组织机构id") private Long orgId; /** * 组织机构名称 */ //@ApiModelProperty("组织机构名称") private String orgName; /** * 用户类型 */ //@ApiModelProperty("用户类型") private Integer userType; /** * 描述 */ //@ApiModelProperty("描述") private String userDesc; /** * 联系地址 */ //@ApiModelProperty("联系地址") private String address; /** * 传真 */ //@ApiModelProperty("传真") private String fax; /** * 邮编 */ //@ApiModelProperty("邮编") private String postalcode; /** * 状态(0:禁用 1:正常) */ //@ApiModelProperty("状态(0:禁用 1:正常)") private Integer status; /** * 数据权限类型(role user group) */ //@ApiModelProperty("数据权限类型(role user group)") private String permissionType; /** * 创建时间 */ //@ApiModelProperty("创建时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; /** * 创建人 */ //@ApiModelProperty("创建人") private String createBy; /** * 更新时间 */ //@ApiModelProperty("更新时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date updateTime; /** * 更新人 */ //@ApiModelProperty("更新人") private String updateBy; /** * 是否删除(0-否 1-是) */ //@ApiModelProperty("是否删除(0-否 1-是)") private Integer isDeleted; /** * 公司地址 */ //@ApiModelProperty("公司地址") private String orgAddress; /** * 部门id */ //@ApiModelProperty("部门id") private String jobId; /** * 部门名称 */ //@ApiModelProperty("部门名称") private String jobName; /** * 过期期限 */ //@ApiModelProperty("过期期限") @JsonFormat(pattern = "yyyyMM", timezone = "GMT+8") private Date expire; private String orgCode; }

PostMan测试代码

基于AOP实现登录日志和操作日志(新手入门版)_第2张图片

控制台查看输出

基于AOP实现登录日志和操作日志(新手入门版)_第3张图片

解析成JSON

{
    "allArgs":[                           // 所有入参
        {
            "bookId":123,
            "bookImg":"testImg",
            "bookIntro":"书籍简介",
            "bookIsbn":"123213414",
            "bookName":"test",
            "bookPrice":12.77,
            "bookPurchasedNumber":0
        }
    ],
    "argsType":{                        // 入参实体类
        "com.demo.mymaintest.entity.BookEntity":"bookEntity"
    },
    "classMethodLocation":"com.demo.mymaintest.controller.TestApiController.test",     // 方法
    "currentTimeMills":"2023-07-21 16:30:49",     // 时间
    "executeTimeMills":"9ms",   // 运行时间
    "nowTime":"2023-07-21 16:30:49",  // 时间
    "operation":"添加数据测试",      //  controller上面的注释
    "remoteAddr":"0:0:0:0:0:0:0:1",  // 这个其实是127.0.0.1 没有进行封装
    "requestMethod":"POST",       
    "requestPath":"/api/add",     // 路径  
    "responseData":"{msg=添加成功, code=200, data=BookEntity(bookId=123, bookIsbn=123213414, bookName=test, bookPrice=12.77, bookImg=testImg, bookIntro=书籍简介, bookPurchasedNumber=0)}",
    "responseType":"com.demo.mymaintest.utils.R",    // 所有返参
    "username":"登录人从request中获取"     // 根据项目详情从token或者session中获取登录人
}

如果你觉得对你有帮助的话,请点赞收藏

你可能感兴趣的:(技术,JavaAOP,java,spring,boot)