SpringBoot AOP 实现日志管理

173 阅读5分钟

主页:写程序的小王叔叔的博客欢迎来访

支持:点赞​收藏​关注

一、实现效果

二、流程图

 

三、代码

1.基本注解类 -- 这个要在控制层中引用,后面说引用方式

/***
 * 系统日志管理表
 * @ClassName: SysLogController
 * @Description: TODO(描述)
 * @author author
 * @date 2019-12-03 10:54:52
 */

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLogAspectValue {

	 String describtion() default "";//日志描述
	 String logType() default "1";//日志种类-1:系统日志2:业务日志
	 String type()  default "GET";//请求方式:(GET/POST)
	 String url()  default "";//请求链接
	 String table()  default "";//操作的数据库表
	 String params()  default "";//请求参数
	 String method()  default "";//请求方法
	 
}

2.日志切面方法

/***
 *  系统日志切面
 * @ClassName: SysLogAspect
 * @Description: TODO(描述)
 * @author author
 * @date 2019-12-04 10:34:41
 */
@Aspect  // 使用@Aspect注解声明一个切面
@Component
public class SystemLogAspect{
 
	 private final String POINT_CUT ="@annotation(com.*.*.modules.sys.log.entity)";
	 
	@Autowired
	public SysLogService sysLogService;
    /**
     * 这里我们使用注解的形式
     * 当然,我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
     * 切点表达式:   execution(...)
     */
    @Pointcut(POINT_CUT)
    public void PointCut() {}

    
    /**
     * 环绕通知 @Around  , 当然也可以使用 @Before (前置通知)  @After (后置通知)
     * @param point
     * @return
     * @throws Throwable
     */
    //@Around(POINT_CUT)
    @Around("@annotation(SysLogAspectValue)")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        Object result = point.proceed();
        try {
        	//正常保存日志
            saveLog(point, System.currentTimeMillis() - beginTime);
        } catch (Exception e) {
        	//异常保存日志
        	//afterReturningMethod(point, e);
        }
        return result;
    }
 
    /***
     * 捕获异常
     * 
     * @Title: afterReturningMethod
     * @Description: TODO(描述)
     * @param joinPoint
     * @param e
     * @author author
     * @throws Throwable 
     * @date 2019-12-10 01:40:37
     */ 
    @AfterThrowing(throwing = "exception",value = "@annotation(SysLogAspectValue)",argNames="exception")
    public void afterReturningMethod(JoinPoint joinPoint, Exception e) throws Throwable{
    	if(e!=null){
    		SysLog sysLog =  new SysLog();
        	long beginTime = System.currentTimeMillis();
        	long time = System.currentTimeMillis() - beginTime;

        	MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
    	
            // 接收到请求,记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
    		sysLog.setId(IdGenerate.longUUIDId());//主键
            sysLog.setLogId(sysLog.getId().toString());//日志编号
            
            sysLog.setTime(time);//时长
            sysLog.setIp(request.getRemoteAddr());//请求的IP
            sysLog.setCreateBy(sysLog.getIp());//请求人
            sysLog.setCreateTime( new Date() );//创建时间
            SysLogAspectValue sysLogAspectValue = method.getAnnotation(SysLogAspectValue.class);
            if(sysLogAspectValue != null){
                //注解上的描述
            	sysLog.setLogComment(sysLogAspectValue.describtion());//备注
            	sysLog.setLogType(sysLogAspectValue.logType());//日志类型
            	sysLog.setType(sysLogAspectValue.type());//请求类型
            	sysLog.setUrl(sysLogAspectValue.url());//请求链接
            	sysLog.setTable(sysLogAspectValue.table());//操作的数据表
            	sysLog.setMethod(sysLogAspectValue.method());//操作请求方法
            }
            //请求的 类名、方法名
            sysLog.setClassName(joinPoint.getTarget().getClass().getName());//类名
            sysLog.setMethodName(signature.getName());//方法名
        	
            //请求的参数
            Object[] args = joinPoint.getArgs();
            List<String> list = new ArrayList<String>();
            for (Object o : args) {
                list.add(new Gson().toJson(o));
            }
            sysLog.setParams("Params:[ " + list.toString()+" ]:Aspectj @AfterThrowing");
            sysLog.setLogError(joinPoint.getSignature().getName()+ "[ message:" + e.getMessage() + "]:Aspectj @AfterThrowing");
            System.out.println("=====异常保存日志成功==============================");
            sysLogService.save(sysLog);
            System.out.println("=====异常保存日志  结束=========================");
    	}
    }
    
    /**
     * 正常保存日志
     * @param joinPoint
     * @param time
     * @throws Throwable 
     */
    public void saveLog(ProceedingJoinPoint joinPoint, long time) {
        SysLog sysLog =  new SysLog();
        sysLog = this.addSysLog(joinPoint,sysLog , time );
        //请求的参数
        Object[] args = joinPoint.getArgs();
        List<String> list = new ArrayList<String>();
        for (Object o : args) {
            list.add(new Gson().toJson(o));
        }
        sysLog.setParams("Params:[ " + list.toString()+" ]:Aspectj @Around");
        sysLog.setLogError( "[ message: 无 ]:Aspectj @Around");
        System.out.println("=====正常保存日志成功==============================");
        sysLogService.save(sysLog);
        System.out.println("=====正常保存日志  结束=========================");
    }

    /**
     * 组装日志model
     * @Title: addSysLog
     * @Description: TODO(描述)
     * @param sysLog
     * @return
     * @author author
     * @date 2019-12-10 02:09:04
     */
	public SysLog addSysLog(ProceedingJoinPoint joinPoint, SysLog sysLog , long time) {
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
	
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
		sysLog.setId(IdGenerate.longUUIDId());//主键
        sysLog.setLogId(sysLog.getId().toString());//日志编号
        
        sysLog.setTime(time);//时长
        sysLog.setIp(request.getRemoteAddr());//请求的IP
        sysLog.setCreateBy(sysLog.getIp());//请求人
        sysLog.setCreateTime( new Date() );//创建时间
        SysLogAspectValue sysLogAspectValue = method.getAnnotation(SysLogAspectValue.class);
        if(sysLogAspectValue != null){
            //注解上的描述
        	sysLog.setLogComment(sysLogAspectValue.describtion());//备注
        	sysLog.setLogType(sysLogAspectValue.logType());//日志类型
        	sysLog.setType(sysLogAspectValue.type());//请求类型
        	sysLog.setUrl(sysLogAspectValue.url());//请求链接
        	sysLog.setTable(sysLogAspectValue.table());//操作的数据表
        	sysLog.setMethod(sysLogAspectValue.method());//操作请求方法
        }
        //请求的 类名、方法名
        sysLog.setClassName(joinPoint.getTarget().getClass().getName());//类名
        sysLog.setMethodName(signature.getName());//方法名
		return sysLog;
	}
    
    
    
    
    
}

3.引用方法

/***
 * 菜单管理信息
 * @ClassName: SysMenuController
 * @Description: TODO(描述)
 * @author author
 * @date 2019-12-04 02:29:39
 */
@CrossOrigin
@RestController
@RequestMapping("/SysMenu")
public class SysMenuController {

	
		@Autowired
		public SysMenuService sysMenuService;
	
	
	
//-------------引用方法-------------------------------添加AOP注解日志管理
		@SysLogAspectValue(
				describtion = "添加一个新的菜单",
				logType = "1",
				type="POST",
				url="/SysMenu/SaveOneSysMenu",
				table="sys_menu",
				params = "SysMenu"
		)
//-------------------------------------------------------------------
		@ResponseBody
		@ApiOperation(value = "添加一个新的菜单", notes = "/SysMenu/SaveOneSysMenu")
		@PostMapping(value = "/SaveOneSysMenu")
		public SysMenu SaveOneSysMenu(@RequestBody SysMenu sysMenu){
			return  sysMenuService.saveOneSysMenu(sysMenu);
		}
		
		//添加AOP注解日志管理
		@SysLogAspectValue(
				describtion = "查询菜单信息",
				logType = "1",
				type="POST",
				url="/SysMenu/SelectAllSysMenu",
				table="sys_menu",
				params = "SysMenu"
		)
		@ResponseBody
		@ApiOperation(value = "查询菜单信息", notes = "/SysMenu/SelectAllSysMenu")
		@GetMapping(value = "/SelectAllSysMenu")
		public List<SysMenu> SelectAllSysMenu(){
			return sysMenuService.SelectAllSysMenu();
		}
		
		//添加AOP注解日志管理
		@SysLogAspectValue(
				describtion = "修改菜单信息",
				logType = "1",
				type="POST",
				url="/SysMenu/ModifySysMenu",
				table="sys_menu",
				params = "SysMenu"
		)
		@ResponseBody
		@ApiOperation(value = "修改菜单信息", notes = "/SysMenu/ModifySysMenu")
		@PostMapping(value = "/ModifySysMenu")
		public List<SysMenu> ModifySysMenu(@RequestBody SysMenu sysMenu){
			sysMenuService.ModifySysMenu(sysMenu);
			return this.sysMenuService.SelectAllSysMenu();
		}
		
		
		
		//添加AOP注解日志管理
		@SysLogAspectValue(
				describtion = "删除一个菜单信息",
				logType = "1",
				type="POST",
				url="/SysMenu/DelOneSysMenu",
				table="sys_menu",
				params = "mapId"
		)
		@ResponseBody
		@ApiOperation(value = "删除一个菜单信息", notes = "/SysMenu/DelOneSysMenu")
		@PostMapping(value = "/DelOneSysMenu")
		public List<SysMenu> DelOneSysMenu(@RequestBody  Map<Object,Object> mapId){
			sysMenuService.DelOneSysMenu(mapId.get("menuId").toString());
			return this.sysMenuService.SelectAllSysMenu();
		}
}

4.日志实体类

@Entity
@Table(name = "sys_log")
@Component
@org.hibernate.annotations.Table(comment="系统日志信息", appliesTo = "sys_log")
public class SysLog implements Serializable{

private static final long serialVersionUID = 42L;
	
	@Id
	@ApiModelProperty("主键")
	@Column(name="id",nullable = false,columnDefinition = "bigint(64)  comment '主键'")
	private Long id;// 主键Id

	@ApiModelProperty("日志编号")
	@Column(name="log_id",columnDefinition = "varchar(255)  comment '日志编号'" )
	private String logId;//日志编号
	
	@ApiModelProperty("请求链接")
	@Column(name="url",columnDefinition = "text  comment '请求链接'" )
	private String url;//请求链接
	
	@ApiModelProperty("请求方法")
	@Column(name="method",columnDefinition = "text  comment '请求方法'" )
	private String method;//请求方法
	
	@ApiModelProperty("请求类名")
	@Column(name="class_name",columnDefinition = "text  comment '请求类名'" )
	private String className;//请求方法
	
	@ApiModelProperty("请求方法名")
	@Column(name="method_name",columnDefinition = "text  comment '请求方法名'" )
	private String methodName;//请求方法
	
	@ApiModelProperty("请求参数")
	@Column(name="params",columnDefinition = "text  comment '请求参数'" )
	private String params;//请求参数
	
	@ApiModelProperty("日志类型:(1:系统日志2:业务日志)")
	@Column(name="lot_type",columnDefinition = "varchar(255)  comment '日志类型:(1:系统日志2:业务日志)'" )
	private String logType;//请求方法
	
	@ApiModelProperty("请求方式:(GET/POST)")
	@Column(name="type",columnDefinition = "varchar(255)  comment '请求方式(GET/POST)'" )
	private String type;//请求方法
	
	@ApiModelProperty("请求IP")
	@Column(name="IP",columnDefinition = "text  comment '请求IP'" )
	private String ip;//请求方法
	
	@ApiModelProperty("操作的数据库表")
	@Column(name="log_table",columnDefinition = "varchar(255)  comment '操作的数据库表'" )
	private String table;//操作的数据库表
	
	@ApiModelProperty("请求异常")
	@Column(name="log_error",columnDefinition = "text  comment '请求异常'" )
	private String logError;//请求异常
	
	@ApiModelProperty("运行时长")
	@Column(name="time",columnDefinition = "varchar(255) comment '运行时长'" )
	private long time;//
	
	@ApiModelProperty("备注")
	@Column(name="log_comment",columnDefinition = "text  comment '备注'" )
	private String logComment;//备注

	@ApiModelProperty("创建人")
	@Column(name="create_by" )
	private String createBy;//创建人

	@ApiModelProperty("创建时间")
	@Column(name="create_time"  )
	private Date createTime;//创建时间
	
 //实现setter/getter
	 
 
	 
	 
	 
	

}

以上就是AOP实现切面的日志管理,有问题的欢迎指正,然后我修改,让程序更加完美。

⚠️注意 ~

💯本期内容就结束了,如果内容有误,麻烦大家评论区指出

如有疑问❓可以在评论区留言💬或私信留言💬,尽我最大能力🏃‍♀️帮大家解决👨‍🏫!

如果我的文章有帮助,欢迎点赞+关注✔️鼓励博主🏃,您的鼓励是我分享的动力🏃🏃🏃~