SpringBoot基于注解切面监听事件
2021-02-17 09:17
标签:element super ignore 连接点 gevent oid spec throw 继承 创建监听器三步骤: 1、事件(event)可以封装和传递监听器中要处理的参数,如对象或字符串,并作为监听器中监听的目标。 2、监听器(listener)具体根据事件发生的业务处理模块,这里可以接收处理事件中封装的对象或字符串。 3、事件发布者(publisher)事件发生的触发者。 代码展示: pom.xml 第一步: 第二步: 定义切面,发布事件 定义切入点注解 相关实体类,mapper,service等忽略,可自己生成! 第三步: 自定义监听器处理业务 验证测试: 日志成功记录 SpringBoot基于注解切面监听事件 标签:element super ignore 连接点 gevent oid spec throw 继承 原文地址:https://www.cnblogs.com/notmore/p/12699683.html
定义一个事件,需要继承spring的ApplicationEvent
package top.xzhand.event;
import org.springframework.context.ApplicationEvent;
/**
* 定义一个事件,需要继承spring的ApplicationEvent
*/
public class LogEvent extends ApplicationEvent {
public LogEvent(Object source) {
super(source);
}
}
@Component
@Aspect
这两个注解必须添加package top.xzhand.event.aspect;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import top.xzhand.event.LogEvent;
import top.xzhand.po.RequestLog;
import org.aspectj.lang.JoinPoint;
import top.xzhand.util.LogUtil;
import java.util.Date;
/**
* 切面发布
*/
@Component
@Aspect
public class LogAspect {
public static final ThreadLocal
package top.xzhand.event.common;
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;
/**
* 方法级别 日志
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Log {
String value() default "";
}
package top.xzhand.po;
import java.util.Date;
public class RequestLog {
private Integer id;
private String requestUrl;
private String requestArgs;
private String ipUrl;
private String message;
private String responseResult;
private Date createAt;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getRequestUrl() {
return requestUrl;
}
public void setRequestUrl(String requestUrl) {
this.requestUrl = requestUrl == null ? null : requestUrl.trim();
}
public String getRequestArgs() {
return requestArgs;
}
public void setRequestArgs(String requestArgs) {
this.requestArgs = requestArgs == null ? null : requestArgs.trim();
}
public String getIpUrl() {
return ipUrl;
}
public void setIpUrl(String ipUrl) {
this.ipUrl = ipUrl == null ? null : ipUrl.trim();
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message == null ? null : message.trim();
}
public String getResponseResult() {
return responseResult;
}
public void setResponseResult(String responseResult) {
this.responseResult = responseResult == null ? null : responseResult.trim();
}
public Date getCreateAt() {
return createAt;
}
public void setCreateAt(Date createAt) {
this.createAt = createAt;
}
}
package top.xzhand.util;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import lombok.experimental.UtilityClass;
import org.aspectj.lang.JoinPoint;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import top.xzhand.event.common.Log;
import top.xzhand.po.RequestLog;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.Date;
@UtilityClass // 方法变量 静态话,类final 私有构造器
public class LogUtil {
public RequestLog getSysLog(JoinPoint point, RequestLog sysLog) {
HttpServletRequest request = getRequest();
sysLog.setIpUrl(getIP(request));
sysLog.setRequestUrl(URLUtil.getPath(request.getRequestURI()));
sysLog.setRequestArgs(request.getQueryString());
sysLog.setCreateAt(new Date());
return sysLog;
}
private HttpServletRequest getRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
private final String UNKNOWN = "unknown";
public String getIP(HttpServletRequest request) {
String ip = request.getHeader("X-Requested-For");
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return StrUtil.isBlank(ip) ? null : ip.split(",")[0];
}
public String getText(String val) {
return StrUtil.sub(val, 0, 65535);
}
/***
* 获取操作信息
*
* @param point
* @return
*/
public String getControllerMethodDescription(JoinPoint point) {
try {
// 获取连接点目标类名
String targetName = point.getTarget().getClass().getName();
// 获取连接点签名的方法名
String methodName = point.getSignature().getName();
// 获取连接点参数
Object[] args = point.getArgs();
// 根据连接点类的名字获取指定类
Class targetClass = Class.forName(targetName);
// 获取类里面的方法
Method[] methods = targetClass.getMethods();
String description = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == args.length) {
description = method.getAnnotation(Log.class).value();
break;
}
}
}
return description;
} catch (Exception e) {
return "";
}
}
/**
* 获取堆栈信息
*
* @param throwable
* @return
*/
public String getStackTrace(Throwable throwable) {
StringWriter sw = new StringWriter();
try (PrintWriter pw = new PrintWriter(sw)) {
throwable.printStackTrace(pw);
return getText(sw.toString());
}
}
}
package top.xzhand.event;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import top.xzhand.po.RequestLog;
/**
* 事件发布
*
*/
@Component
public class EventPublister {
@Autowired
private ApplicationContext applicationContext;
// 事件发布方法
public void pushListener(RequestLog requsetLog) {
applicationContext.publishEvent(new LogEvent(requsetLog));
}
}
package top.xzhand.event;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import top.xzhand.po.RequestLog;
import top.xzhand.service.RequestLogService;
/**
* 自己定义的监听器需要实现ApplicationListener,
* 同时泛型参数要加上自己要监听的事件Class名,
* 在重写的方法onApplicationEvent中,添加自己的业务处理
*/
@Component
public class LogListerner implements ApplicationListener
package top.xzhand.controller;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import top.xzhand.event.EventPublister;
import top.xzhand.event.common.Log;
import top.xzhand.po.RequestLog;
import top.xzhand.util.LogUtil;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
/**
*
*/
@Controller
public class TestEventListenerController {
@Autowired
private EventPublister publisher;
/**
* 非注解形式监听事件
* @param request
* @param arg
*/
@RequestMapping(value = "/test/logEvent1" )
public void testPublishEvent1(HttpServletRequest request,String arg ){
RequestLog requestLog=new RequestLog();
requestLog.setCreateAt(new Date());
requestLog.setRequestUrl(request.getContextPath());
requestLog.setIpUrl(LogUtil.getIP(request));
requestLog.setRequestArgs(request.getQueryString());
publisher.pushListener(requestLog);
System.out.println(JSON.toJSONString(requestLog));
}
/**
* 基于注解的切面事件发布监听
* @param request
* @param arg
*/
@Log
@RequestMapping(value = "/test/logEvent2" )
public void testPublishEvent2(HttpServletRequest request,String arg ){
System.out.println("切面注解监听");
}
}
上一篇:C#导入有道词典单词本到扇贝
文章标题:SpringBoot基于注解切面监听事件
文章链接:http://soscw.com/index.php/essay/56496.html