SpringBoot自定义注解+异步+观察者模式实现业务日志保存( 二 )

2. 业务类型枚举/** * @author wangzhenjun * @date 2022/10/26 11:22 */public enum BusinessTypeEnum {/*** 其它*/OTHER(0,"其它"),/*** 新增*/INSERT(1,"新增"),/*** 修改*/UPDATE(2,"修改"),/*** 删除*/DELETE(3,"删除");private Integer code;private String message;BusinessTypeEnum(Integer code, String message) {this.code = code;this.message = message;}public Integer getCode() {return code;}public String getMessage() {return message;}}3. 编写切片这里小编是以切片后进行发起的,当然规范流程是要加异常后的切片,这里以最简单的进行测试哈,大家按需进行添加?。?
import com.example.demo.annotation.Log;import com.example.demo.entity.SysLog;import com.example.demo.listener.EventPubListener;import com.example.demo.utils.IpUtils;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;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.time.LocalDateTime;/** * @author wangzhenjun * @date 2022/10/26 15:39 */@Aspect@Componentpublic class SysLogAspect {private final Logger logger = LoggerFactory.getLogger(SysLogAspect.class);@Autowiredprivate EventPubListener eventPubListener;/*** 以注解所标注的方法作为切入点*/@Pointcut("@annotation(com.example.demo.annotation.Log)")public void sysLog() {}/*** 在切点之后织入* @throws Throwable*/@After("sysLog()")public void doAfter(JoinPoint joinPoint) {Log log = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(Log.class);ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();String method = request.getMethod();String url = request.getRequestURL().toString();String ip = IpUtils.getIpAddr(request);SysLog sysLog = new SysLog();sysLog.setBusinessType(log.businessType().getCode());sysLog.setTitle(log.title());sysLog.setRequestMethod(method);sysLog.setOperIp(ip);sysLog.setOperUrl(url);// 从登录中token获取登录人员信息即可sysLog.setOperName("我是测试人员");sysLog.setOperTime(LocalDateTime.now());// 发布消息eventPubListener.pushListener(sysLog);logger.info("=======日志发送成功 , 内容:{}",sysLog);}}4. ip工具类import com.baomidou.mybatisplus.core.toolkit.StringUtils;import javax.servlet.http.HttpServletRequest;/** * @author wangzhenjun * @date 2022/10/26 16:27 * 获取IP方法 * * @author jw */public class IpUtils {/*** 获取客户端IP** @param request 请求对象* @return IP地址*/public static String getIpAddr(HttpServletRequest request) {if (request == null) {return "unknown";}String ip = request.getHeader("x-forwarded-for");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("X-Forwarded-For");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("X-Real-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);}/*** 从多级反向代理中获得第一个非unknown IP地址** @param ip 获得的IP地址* @return 第一个非unknown IP地址*/public static String getMultistageReverseProxyIp(String ip) {// 多级反向代理检测if (ip != null && ip.indexOf(",") > 0) {final String[] ips = ip.trim().split(",");for (String subIp : ips) {if (false == isUnknown(subIp)) {ip = subIp;break;}}}return ip;}/*** 检测给定字符串是否为未知,多用于检测HTTP请求相关** @param checkString 被检测的字符串* @return 是否未知*/public static boolean isUnknown(String checkString) {return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);}}5. 事件发布事件发布是由ApplicationContext对象进行发布的,直接注入使用即可!使用观察者模式的目的:为了业务逻辑之间的解耦 , 提高可扩展性 。这种模式在spring和springboot底层是经常出现的,大家可以去看看 。发布者只需要关注发布消息,监听者只需要监听自己需要的,不管谁发的,符合自己监听条件即可 。
import com.example.demo.entity.SysLog;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.stereotype.Component;/** * @author wangzhenjun * @date 2022/10/26 16:38 */@Componentpublic class EventPubListener {@Autowiredprivate ApplicationContext applicationContext;// 事件发布方法public void pushListener(SysLog sysLogEvent) {applicationContext.publishEvent(sysLogEvent);}}

推荐阅读