您现在的位置是:主页 > news > 承德专业做网站/优秀营销软文范例100字

承德专业做网站/优秀营销软文范例100字

admin2025/5/7 1:18:44news

简介承德专业做网站,优秀营销软文范例100字,wordpress做首页,老域名全部失效请拿笔记好点击上方“linkoffer”,选择关注公众号高薪职位第一时间送达一. 功能简介本文主要记录如何使用 注解aop切面异步监听 的方式来实现日志记录功能。主要记录的信息有: 操作人,操作IP,方法名,参数,消耗时间,日…

承德专业做网站,优秀营销软文范例100字,wordpress做首页,老域名全部失效请拿笔记好点击上方“linkoffer”,选择关注公众号高薪职位第一时间送达一. 功能简介本文主要记录如何使用 注解aop切面异步监听 的方式来实现日志记录功能。主要记录的信息有: 操作人,操作IP,方法名,参数,消耗时间,日…

点击上方“linkoffer”,

选择关注公众号高薪职位第一时间送达

一. 功能简介

本文主要记录如何使用 注解+aop切面+异步监听 的方式来实现日志记录功能。

主要记录的信息有: 操作人,操作IP,方法名,参数,消耗时间,日志类型,操作类型(操作日志和异常日志)以及增删改查记录,操作时间等。

主要流程:

AOP切面得到请求数据 -> 发布监听事件 -> 异步监听日志入库

二. 项目结构

f4596f18adf19aa346754306d600a1e8.png

三. 项目实战

1.引入依赖

org.springframework.boot

spring-boot-starter-aop

2.自定义注解

主要标注日志的具体用处也就是具体操作

package com.xd.pre.log;

import java.lang.annotation.*;

//元注解,定义注解被保留策略,一般有三种策略

//1、RetentionPolicy.SOURCE 注解只保留在源文件中,在编译成class文件的时候被遗弃

//2、RetentionPolicy.CLASS 注解被保留在class中,但是在jvm加载的时候北欧抛弃,这个是默认的声明周期

//3、RetentionPolicy.RUNTIME 注解在jvm加载的时候仍被保留

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD}) //定义了注解声明在哪些元素之前

@Documented

public @interface SysLog {

//定义成员

String descrption() default "" ;//描述

}

3.AOP切面类

AOP切面类是最主要的,可以使用自定义注解或针对包名实现AOP增强。

1)这里实现了对自定义注解的切点,对使用了自定义注解的方法进行AOP切面处理;

2)对方法运行时间进行监控;

3)对方法名,参数名,参数值,对日志描述以及异常信息的优化处理;

4)发布监听事件,日志异步入库

在方法上增加@Aspect 注解声明切面,使用@Pointcut 注解定义切点,标记方法。

package com.xd.pre.log;

import cn.hutool.core.convert.Convert;

import cn.hutool.core.util.URLUtil;

import cn.hutool.extra.servlet.ServletUtil;

import com.xd.pre.security.PreUser;

import com.xd.pre.security.util.SecurityUtil;

import com.xd.pre.utils.LogUtil;

import com.xd.pre.utils.R;

import lombok.extern.slf4j.Slf4j;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.*;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.ApplicationContext;

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.time.Instant;

import java.time.LocalDateTime;

import java.util.Arrays;

import java.util.Objects;

/**

* @Classname SysLogAspect

* @Description 系统日志切面

* @Author 李号东 lihaodongmail@163.comgit reset --merge

* @Date 2019-04-22 23:52

* @Version 1.0

* ①切面注解得到请求数据 -> ②发布监听事件 -> ③异步监听日志入库

*/

@Slf4j

@Aspect

@Component

public class SysLogAspect {

private com.xd.pre.domain.SysLog sysLog = new com.xd.pre.domain.SysLog();

/**

* 事件发布是由ApplicationContext对象管控的,我们发布事件前需要注入ApplicationContext对象调用publishEvent方法完成事件发布

**/

@Autowired

private ApplicationContext applicationContext;

/***

* 定义controller切入点拦截规则,拦截SysLog注解的方法

*/

@Pointcut("@annotation(com.xd.pre.log.SysLog)")

public void sysLogAspect() {

}

/***

* 拦截控制层的操作日志

* @param joinPoint

* @return

* @throws Throwable

*/

@Before(value = "sysLogAspect()")

public void recordLog(JoinPoint joinPoint) throws Throwable {

// 开始时间

long beginTime = Instant.now().toEpochMilli();

HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();

PreUser securityUser = SecurityUtil.getUser();

sysLog.setUserName(securityUser.getUsername());

sysLog.setActionUrl(URLUtil.getPath(request.getRequestURI()));

sysLog.setStartTime(LocalDateTime.now());

sysLog.setRequestIp(ServletUtil.getClientIP(request));

sysLog.setRequestMethod(request.getMethod());

sysLog.setUa(request.getHeader("user-agent"));

//访问目标方法的参数 可动态改变参数值

Object[] args = joinPoint.getArgs();

//获取执行的方法名

sysLog.setActionMethod(joinPoint.getSignature().getName());

// 类名

sysLog.setClassPath(joinPoint.getTarget().getClass().getName());

sysLog.setActionMethod(joinPoint.getSignature().getName());

sysLog.setFinishTime(LocalDateTime.now());

// 参数

sysLog.setParams(Arrays.toString(args));

sysLog.setDescription(LogUtil.getControllerMethodDescription(joinPoint));

long endTime = Instant.now().toEpochMilli();

sysLog.setConsumingTime(endTime - beginTime);

}

/**

* 返回通知

* @param ret

* @throws Throwable

*/

@AfterReturning(returning = "ret", pointcut = "sysLogAspect()")

public void doAfterReturning(Object ret) {

// 处理完请求,返回内容

R r = Convert.convert(R.class, ret);

if (r.getCode() == 200){

// 正常返回

sysLog.setType(1);

} else {

sysLog.setType(2);

sysLog.setExDetail(r.getMsg());

}

// 发布事件

applicationContext.publishEvent(new SysLogEvent(sysLog));

}

/**

* 异常通知

* @param e

*/

@AfterThrowing(pointcut = "sysLogAspect()",throwing = "e")

public void doAfterThrowable(Throwable e){

// 异常

sysLog.setType(2);

// 异常对象

sysLog.setExDetail(LogUtil.getStackTrace(e));

// 异常信息

sysLog.setExDesc(e.getMessage());

// 发布事件

applicationContext.publishEvent(new SysLogEvent(sysLog));

}

}

目前使用: 前置通知,后置通知,异常通知

事件发布是由 ApplicationContext对象管控的,我们发布事件前需要注入 ApplicationContext对象调用publishEvent方法完成事件发布

4.日志实体类

主要记录日志的详细信息

package com.xd.pre.domain;

import com.baomidou.mybatisplus.annotation.IdType;

import com.baomidou.mybatisplus.annotation.TableId;

import java.time.LocalDateTime;

import java.io.Serializable;

import lombok.Data;

import lombok.EqualsAndHashCode;

import lombok.experimental.Accessors;

/**

*

* 系统日志

*

*

* @author lihaodong

* @since 2019-04-27

*/

@Data

@EqualsAndHashCode(callSuper = false)

@Accessors(chain = true)

public class SysLog implements Serializable {

private static final long serialVersionUID = 1L;

/**

* 主键

*/

@TableId(value = "id", type = IdType.AUTO)

private Integer id;

/**

* 操作IP

*/

private String requestIp;

/**

* 操作类型 1 操作记录 2异常记录

*/

private Integer type;

/**

* 操作人ID

*/

private String userName;

/**

* 操作描述

*/

private String description;

/**

* 请求方法

*/

private String actionMethod;

/**

* 请求url

*/

private String actionUrl;

/**

* 请求参数

*/

private String params;

/**

* 浏览器

*/

private String ua;

/**

* 类路径

*/

private String classPath;

/**

* 请求方法

*/

private String requestMethod;

/**

* 开始时间

*/

private LocalDateTime startTime;

/**

* 完成时间

*/

private LocalDateTime finishTime;

/**

* 消耗时间

*/

private Long consumingTime;

/**

* 异常详情信息 堆栈信息

*/

private String exDetail;

/**

* 异常描述 e.getMessage

*/

private String exDesc;

}

5.ApplicationEvent&Listener完成业务解耦

ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听,监听具体的实现内容是什么,发布者的工作只是为了发布事件而已。

其实生活中有很多这样的例子: 我们在平时常见的比赛中,裁判员或者主持人给我们开始的信号,也就是给我们发布了一个开始的事件,而参赛的双方人员都在监听着这个事件,一旦事件发布后双方人员就开始拼命努力赢得比赛。而裁判或者主持人并不关心你比赛的过程,只是给你发布事件你执行就可以了

系统日志事件

package com.xd.pre.log;

import com.xd.pre.domain.SysLog;

import org.springframework.context.ApplicationEvent;

/**

* @Classname SysLogEvent

* @Description 系统日志事件

* @Author 李号东 lihaodongmail@163.com

* @Date 2019-04-28 11:34

* @Version 1.0

*/

public class SysLogEvent extends ApplicationEvent {

public SysLogEvent(SysLog source) {

super(source);

}

}

我们自定义事件SysLogEvent继承了ApplicationEvent,继承后必须重载构造函数,构造函数的参数可以任意指定,其中source参数指的是发生事件的对象,一般我们在发布事件时使用的是this关键字代替本类对象,而sysLog参数是我们自定义的注册用户对象,该对象可以在监听内被获取。

异步监听日志事件

package com.xd.pre.log;

import com.xd.pre.domain.SysLog;

import com.xd.pre.service.ISysLogService;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.event.EventListener;

import org.springframework.core.annotation.Order;

import org.springframework.scheduling.annotation.Async;

import org.springframework.stereotype.Component;

/**

* @Classname SysLogListener

* @Description 注解形式的监听 异步监听日志事件

* @Author 李号东 lihaodongmail@163.com

* @Date 2019-04-28 11:34

* @Version 1.0

*/

@Slf4j

@Component

public class SysLogListener {

@Autowired

private ISysLogService sysLogService;

@Async

@Order

@EventListener(SysLogEvent.class)

public void saveSysLog(SysLogEvent event) {

SysLog sysLog = (SysLog) event.getSource();

// 保存日志

sysLogService.save(sysLog);

}

}

我们只需要让我们的监听类被Spring所管理即可,在我们用户注册监听实现方法上添加@EventListener注解,该注解会根据方法内配置的事件完成监听。

6.具体用法

只需要在你控制层要记录日志的方法上加上@SysLog注解即可

/**

* 获取用户列表集合

*

* @param page

* @param userDTO

* @return

*/

@SysLog(descrption = "查询用户集合")

@GetMapping

@PreAuthorize("hasAuthority('sys:user:view')")

public R getList(Page page, UserDTO userDTO) {

return R.ok(userService.getUsersWithRolePage(page, userDTO));

}

源码地址

码云: https://gitee.com/li_haodong/pre

GitHub: https://github.com/LiHaodong888/pre

5c0e2ca742520ee4a7060d3658f25882.png