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);}}

推薦閱讀