SpringBoot自定义记事+异步+观察者模式实现业务日志保存
发布时间:2023-04-29
MENT = '转换快照历史纪录' ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
治疗类风湿关节炎的首选药物
一吃辣就拉肚子是什么原因
肠胃炎拉肚子吃什么药
风湿保健
实体类:
import com.baomidou.mybatisplus.Annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;import com.fasterxml.jackson.annotation.JsonFormat;import lombok.Data;import java.time.LocalDateTime;/** * 转换快照历史纪录表 sys_log * */@Data@TableName("sys_log")public class SysLog { private static final long serialVersionUID = 1L; /** * 快照字段 */ @TableId private Long id; /** * 转换模块化 */ private String title; /** * 业务并不一定(0其它 1新增 2修改 3删去) */ private Integer businessType; /** * 催促方式将 */ private String requestMethod; /** * 转换人员 */ private String operName; /** * 催促url */ private String operUrl; /** * 转换邮箱 */ private String operIp; /** * 转换时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime operTime;}四、主要功能大体渐进:先为副本一个出处-------->凸来来进行赚取要留存的原始数据-------->一个发布新闻者来发布新闻要留存的原始数据-------->一个窃听者窃听后留存(异步)
完整项目架构图如下:
1. 编著出处import com.example.demo.constant.BusinessTypeEnum;import java.lang.annotation.*;/** * 自定义转换快照历史纪录出处 * @author wangzhenjun * @date 2022/10/26 15:37 */@Target(ElementType.METHOD) // 出处只能用于方式@Retention(RetentionPolicy.RUNTIME) // ;也出处的生命周期@Documentedpublic @interface Log { String value() default ""; /** * 模块化 */ String title() default "检验模块化"; /** * 功能 */ BusinessTypeEnum businessType() default BusinessTypeEnum.OTHER;}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); @Autowired private 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 { @Autowired private ApplicationContext applicationContext; // 政治事件发布新闻方式 public void pushListener(SysLog sysLogEvent) { applicationContext.publishEvent(sysLogEvent); }}6. 窃听者@Async:单独重启一个新寄存器去留存,提高稳定性!@EventListener:窃听
/** * @author wangzhenjun * @date 2022/10/25 15:22 */@Slf4j@Componentpublic class MyEventListener { @Autowired private TestService testService; // 重启异步 @Async // 重启窃听 @EventListener(SysLog.class) public void saveSysLog(SysLog event) { log.info("=====即将异步留存到索引======"); testService.saveLog(event); }}五、检验1. controller/** * @author wangzhenjun * @date 2022/10/26 16:51 */@Slf4j@RestController@RequestMapping("/test")public class TestController { @Log(title = "检验呢",businessType = BusinessTypeEnum.INSERT) @GetMapping("/saveLog") public void saveLog(){ log.info("我就是来检验一下是否出乎意料!"); }}2. service/** * @author wangzhenjun * @date 2022/10/26 16:55 */public interface TestService { int saveLog(SysLog sysLog);}/** * @author wangzhenjun * @date 2022/10/26 16:56 */@Servicepublic class TestServiceImpl implements TestService { @Autowired private TestMapper testMapper; @Override public int saveLog(SysLog sysLog) { return testMapper.insert(sysLog); }}3. mapper这里适用mybatis-plus来进行留存
/** * @author wangzhenjun * @date 2022/10/26 17:07 */public interface TestMapper extends BaseMapper {}4. 检验 5. 索引 六、总结铛铛铛,终于完成了!这个实战在应用软件必不可少的,每个项目搭成人不同,但是结果都是一样的,留存快照到原始数据,这样可以来进行操纵杆的点击来进行统计,分析方法那个功能是否往往适用,那些好像需最佳化。只要是有原始数据的好像,分析方法一下总不会有收获的!后面快照多了就行分库分表,ELK搭成。知道的越好多不知道的就越好多,这一次下来,知道下面要学什么了嘛!!
。长期便秘是什么原因治疗类风湿关节炎的首选药物
一吃辣就拉肚子是什么原因
肠胃炎拉肚子吃什么药
风湿保健
标签:
相关阅读
-
美国经济学家里卡兹:破坏美元地位的并非是中国,而是我们的政府部门
仅有一个月以来,英国境况了一系列引人注目的事件,其中都仅限于“银行动荡”和奥斯本的加息决策,这些事件不仅制约了英国国外经济,还在International舞台上招致了核反应。尤其值得一提的是,这
- 2024-02-1016岁的他,凭着不服输活成了别人的效法
- 2024-02-10同时官宣,9人被伦
- 2024-02-10老百姓开始拒绝了!捐款、献血、奉献、帮人、折扣、生娃都不愿意
- 2024-02-10新增14个报考点!广西2023考研网报公告出炉!在广西考试只能什么条件?
- 2024-02-10开启教育帮扶历史性!湖南91所中高职院校结对子
- 2024-02-10许家印离婚发酵!恒大灾难背后的财务分割大战,传众高管早已离婚
- 2024-02-10《新农科信息化引导性专业指南》印发
- 2024-02-10博主建议毕业生租房优先权衡通勤距离
- 2024-02-10央行再出手!8月15日起,上调
- 2024-02-10词组混和 Day 71