【log】操作类日志处理 与 报错类日志处理logback

news/2024/4/20 10:56:55/文章来源:https://blog.csdn.net/m0_70083523/article/details/128961081

文章目录

    • 一、操作类日志处理【环绕增强】
      • aop环绕增强
          • 导包
          • 第一步:自定义注解@interface
          • 第二步:在Controller写一个测试的方法:
          • 第三步:编写LogAspect增强类与增强方法
      • 日志写入数据库(使用mybatis)
          • 第一步:创建关于日志的数据库(用户、操作、方法、执行时间、个人服务器IP、操作时间等)
          • 第二步:创建实体类
          • 第三步: dao层(省略mapper和service层)
          • 第四步: LogAspect增强类与增强方法
          • 两个工具类 IPUtils 、HttpContextUtils :
      • 日志写入文件
      • 日志写入搜索引擎(非分布式引擎)
    • 二、报错类日志处理logback
          • 第一步:创建logback-spring.xml文件放入resource下
          • 第二步:配置application.properties文件
          • 第三步:编写controller测试

一、操作类日志处理【环绕增强】

aop环绕增强

导包
<!-- aop依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
第一步:自定义注解@interface
  • @interface 注解类,自定义注解
  • @Target 用来说明该注解可以被声明在那些元素之前
    • ElementType.METHOD说明该注解只能被声明在一个类的方法前
  • @Retention 用来说明该注解类的生命周期。
    • RetentionPolicy.RUNTIME注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解
/*** 自定义注解* 用于在Controller层使用注解标注哪个方法需要增加日志*/@Target(ElementType.METHOD)   //在方法加载Log
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {String value() default "";
}
第二步:在Controller写一个测试的方法:
@RestController
@RequestMapping("/index")public class IndexController {/*一般将这个日志放到Controller,因为要记录方法的执行时间。也可以记录service,但是最好Controller*/@Log("这是Index的修改方法")@GetMapping("/updateIndex")public int updateIndex(){System.out.println("这是修改");return 10;}
}
第三步:编写LogAspect增强类与增强方法
@Aspect
@Component
public class LogAspect {//切入点,指定当使用Log注解时进入环绕增强@Pointcut("@annotation(com.wy.log.Log)")public void pointcut() {}/*** 环绕增强* @param point* @return*/@Around("pointcut()")public Object around(ProceedingJoinPoint point) {try {System.out.println("执行环绕增强..............开始");Object result = point.proceed();  //调用目标方法:point.proceed()System.out.println("执行环绕增强..............结束");return result;   //与Controller的返回值一致(没什么用)} catch (Throwable throwable) {throwable.printStackTrace();}return null;}
}

执行:http://localhost:8080/index/updateIndex
结果:
在这里插入图片描述
说明:调用目标的方法的输出结果没什么大用,就是Controller的返回值

日志写入数据库(使用mybatis)

使用mybatis的话,要导入mybatis的核心包,和sql驱动,配置文件

<!--mybatis的核心包-->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.3</version>
</dependency>
<!--mysql驱动-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.44</version>
</dependency>
spring:datasource:username: zzzzpassword: zzzzurl: jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8&useSSL=falsedriver-class-name: com.mysql.jdbc.Driver
第一步:创建关于日志的数据库(用户、操作、方法、执行时间、个人服务器IP、操作时间等)
DROP TABLE IF EXISTS `sys_log`;
CREATE TABLE `sys_log` (`ID` bigint(20) NOT NULL AUTO_INCREMENT,`USERNAME` varchar(50) DEFAULT NULL COMMENT '用户名',`OPERATION` varchar(50) DEFAULT NULL COMMENT '用户操作',`TIME` int(11) DEFAULT NULL COMMENT '响应时间',`METHOD` varchar(200) DEFAULT NULL COMMENT '请求方法',`PARAMS` varchar(500) DEFAULT NULL COMMENT '请求参数',`IP` varchar(64) DEFAULT NULL COMMENT 'IP地址',`CREATE_TIME` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
第二步:创建实体类
@Data
public class SysLog {private Long id;private String username;private String operation;private Integer time;private String method;private String params;private String ip;private String createTime;
}
第三步: dao层(省略mapper和service层)
@Repository
public interface SysLogDao {@Insert("insert into sys_log(USERNAME,OPERATION,TIME,METHOD,PARAMS,IP) " +"values(#{username},#{operation},#{time},#{method},#{params},#{ip})")public int insertSysLog(SysLog sysLog);
}
第四步: LogAspect增强类与增强方法
@Aspect
@Component
public class LogAspect {@Autowiredprivate SysLogDao sysLogDao;//切入点,指定当使用Log注解时进入环绕增强@Pointcut("@annotation(com.wy.log.Log)")public void pointcut() {}/*** 环绕增强* @param point* @return*/@Around("pointcut()")public Object around(ProceedingJoinPoint point) {try {//1、获取时间Long beginTime = System.currentTimeMillis();  //调取方法前开始计时(毫秒)Object res = point.proceed();//调用目标方法:point.proceed()Long endTime = System.currentTimeMillis();  //调取方法前开始计时(毫秒)Long time = endTime-beginTime;//2、获取本地IP:工具类直接使用//从request中解析出ip地址HttpServletRequest request = HttpContextUtils.getHttpServletRequest();//3、拿到方法上的描述:某个操作MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();Log logAnnotation = method.getAnnotation(Log.class);//4、请求的方法名String className = point.getTarget().getClass().getName();String methodName = signature.getName();//5、请求的参数// 请求的方法参数值Object[] args = point.getArgs();// 请求的方法参数名称String params = "";LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();String[] paramNames = u.getParameterNames(method);if (args != null && paramNames != null) {for (int i = 0; i < args.length; i++) {params += "  " + paramNames[i] + ": " + args[i];}/*sysLog.setParams(params);*/}SysLog sysLog = new SysLog();sysLog.setUsername("朱尔斯");   //一般是从session或request中拿取sysLog.setTime(Integer.parseInt(time.toString()));sysLog.setIp(IPUtils.getIpAddr(request));sysLog.setOperation(logAnnotation.value());sysLog.setMethod(className + "." + methodName + "()");sysLog.setParams(params);sysLogDao.insertSysLog(sysLog);return res;} catch (Throwable throwable) {throwable.printStackTrace();}return null;}
}

执行:http://localhost:8080/index/updateIndex
结果:在这里插入图片描述

两个工具类 IPUtils 、HttpContextUtils :
package com.hz.utils;
import javax.servlet.http.HttpServletRequest;
public class IPUtils {/*** 获取IP地址* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址*/public static String getIpAddr(HttpServletRequest request) {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("WL-Proxy-Client-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" : ip;}
}
package com.hz.utils;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;public class HttpContextUtils {public static HttpServletRequest getHttpServletRequest() {return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();}
}

日志写入文件

日志写入搜索引擎(非分布式引擎)

二、报错类日志处理logback

之前有说过log4j的处理方式:https://blog.csdn.net/m0_70083523/article/details/127498052

第一步:创建logback-spring.xml文件放入resource下

关于logback的日志配置网上就能下载到【此文件私发】

<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration  scan="true" scanPeriod="10 seconds"><!--<include resource="org/springframework/boot/logging/logback/base.xml" />--><contextName>logback</contextName><!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 --><property name="log.path" value="D:/nmyslog/nmys" /><!-- 彩色日志 --><!-- 彩色日志依赖的渲染类 --><conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /><conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /><conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /><!-- 彩色日志格式 --><property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/><!--输出到控制台--><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息--><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>info</level></filter><encoder><Pattern>${CONSOLE_LOG_PATTERN}</Pattern><!-- 设置字符集 --><charset>UTF-8</charset></encoder></appender><!--输出到文件--><!-- 时间滚动输出 level为 DEBUG 日志 --><appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_debug.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset> <!-- 设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志归档 --><fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录debug级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>debug</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- 时间滚动输出 level为 INFO 日志 --><appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_info.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 每天日志归档路径以及格式 --><fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录info级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>info</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- 时间滚动输出 level为 WARN 日志 --><appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_warn.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset> <!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录warn级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>warn</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- 时间滚动输出 level为 ERROR 日志 --><appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_error.log</file><!--日志文件输出格式--><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset> <!-- 此处设置字符集 --></encoder><!-- 日志记录器的滚动策略,按日期,按大小记录 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数--><maxHistory>15</maxHistory></rollingPolicy><!-- 此日志文件只记录ERROR级别的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!--<logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。<logger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。name:用来指定受此logger约束的某一个包或者具体的某一个类。level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。如果未设置此属性,那么当前logger将会继承上级的级别。addtivity:是否向上级logger传递打印信息。默认是true。--><!--<logger name="org.springframework.web" level="info"/>--><!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>--><!--使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:--><!--root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能设置为INHERITED或者同义词NULL。默认是DEBUG可以包含零个或多个元素,标识这个appender将会添加到这个logger。--><!--开发环境:打印控制台--><springProfile name="dev"><logger name="com.nmys.view" level="debug"/></springProfile><root level="info"><appender-ref ref="CONSOLE" /><appender-ref ref="DEBUG_FILE" /><appender-ref ref="INFO_FILE" /><appender-ref ref="WARN_FILE" /><appender-ref ref="ERROR_FILE" /></root><!--生产环境:输出到文件--><!--<springProfile name="pro">--><!--<root level="info">--><!--<appender-ref ref="CONSOLE" />--><!--<appender-ref ref="DEBUG_FILE" />--><!--<appender-ref ref="INFO_FILE" />--><!--<appender-ref ref="ERROR_FILE" />--><!--<appender-ref ref="WARN_FILE" />--><!--</root>--><!--</springProfile>-->
</configuration>
第二步:配置application.properties文件
#读取配置文件
logging.config=classpath:logback-spring.xml#上面文件中也有路径的配置,如果上面没有,则可以在此处配置
#日志打印文件所在目录
logging.path=D:/项目名/log
第三步:编写controller测试
							//这个类要是当前Controller类
Logger log = Logger.getLogger(SfUserController.class);
log.info("要输出的内容");//输出信息
-------------------------------------------------
等级可分为OFFFATALERRORWARNINFODEBUGALL
如果配置OFF则不打出任何信息,
如果配置为INFO这样只显示INFO, WARN, ERROR的log信息,而DEBUG信息不会被显示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_73990.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis快速开发

查询user表中的所有数据 步骤&#xff1a; 创建user表 打开Navicat&#xff0c;新建查询&#xff0c;将下面SQL代码复制粘贴并执行&#xff1a; create database mybatis; use mybatis;drop table if exists tb_user;create table tb_user(id int primary key auto_incremen…

Vue3电商项目实战-商品详情模块6【17-商品详情-标签页组件、18-商品详情-热榜组件、19-商品详情-详情组件、20-商品详情-注意事项组件】

文章目录17-商品详情-标签页组件18-商品详情-热榜组件19-商品详情-详情组件20-商品详情-注意事项组件17-商品详情-标签页组件 目的&#xff1a;实现商品详情组件和商品评价组件的切换 大致步骤&#xff1a; 完成基础的tab的导航布局完成tab标签页的切换样式效果使用动态组件完…

【Rust 日报】2023-2-24 Dioxus 0.3 发布,巨大的更新

ascii-d - 画ASCII示意图的工具Rust写的画ASCII示意图的工具。支持各大平台。程序员的最爱啊。https://github.com/huytd/ascii-d/raw/master/_meta/toolbar-final.gifDioxus 0.3 发布&#xff0c;巨大的更新Dioxus 是新出的与 Yew 类似的 Rust Web 前端框架&#xff08;为什么…

【华为OD机试模拟题】用 C++ 实现 - 最大相连男生数(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 货币单位换算(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 选座位(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 停车场最大距离(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 重组字符串(2023.Q1) 【华为OD机试模…

Java-多线程-增强篇-锁强化第3篇

Java集合框架中的锁 今天我们继续来学习锁 字符串操作中的锁 String是线程安全的&#xff0c;因为使用final修饰Stringbuilder 是线程不安全的&#xff0c;其方法没有使用synchronized修饰StringBuffer 是线程安全的&#xff0c;其方法使用synchronized修饰 List集合中的锁 …

内核并发消杀器(KCSAN)技术分析

一、KCSAN介绍KCSAN(Kernel Concurrency Sanitizer)是一种动态竞态检测器&#xff0c;它依赖于编译时插装&#xff0c;并使用基于观察点的采样方法来检测竞态&#xff0c;其主要目的是检测数据竞争。KCSAN是一种检测LKMM(Linux内核内存一致性模型)定义的数据竞争(data race)的工…

【网络原理8】HTTP请求篇

在上一篇文章当中&#xff0c;我们也提到了什么是HTTP。 每一个HTTP请求&#xff0c;都会对应一个HTTP响应。 下面这一篇文章&#xff0c;将聊一下HTTP请求的一些内容 目录 一、URL 第一部分&#xff1a;协议名称 第二部分:认证信息(新的版本已经没有了) 第三部分&#xf…

【数通网络交换基础梳理1】二层交换机、以太网帧、MAC地址详解及数据帧转发原理(爆炸细)

一、网络模型 万年不变&#xff0c;先从模型结构分析&#xff0c;现在大家熟知的网络模型有两种。第一种是&#xff0c;OSI七层模型&#xff0c;第二种是TCP/IP模型。在实际运用中&#xff0c;参考更多的是TCP/IP模型。 OSI七层模型 TCP/IP模型 不需要全部理解&#xff0c;…

Spring MVC 源码- HandlerExceptionResolver 组件

HandlerExceptionResolver 组件HandlerExceptionResolver 组件&#xff0c;处理器异常解析器&#xff0c;将处理器&#xff08; handler &#xff09;执行时发生的异常&#xff08;也就是处理请求&#xff0c;执行方法的过程中&#xff09;解析&#xff08;转换&#xff09;成对…

Python变量的定义和使用

定义&#xff1a;变量就是计算机内存中存储某些数据的位置的名称 形象理解变量就是一个存放东西的容器&#xff0c;该容器的名字就叫做变量&#xff0c;容器存放的东西就是变量的值 变量的组成&#xff1a; 标识&#xff1a;标识对象所储存的内存地址&#xff0c;使用内置函数i…

六千字让你明白什么是数字孪生?

文章目录1. 背景2. 数字孪生基础2.1 概念2.2 价值3. 技术生态3.1 技术体系3.2 核心技术3.2.1 多领域、多尺度融合建模3.2.2 数据驱动与物理模型融合的状态评估3.2.3 数据采集和传输3.2.4 全生命周期数据管理3.2.5 虚拟现实呈现3.2.6 高性能计算3.3 建设3.3.1 重点3.3.1.1 数字孪…

SEATA是什么?它的四种分布式事务模式

一、SEATA是什么&#xff1f; Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 在继续学习使用SEATA之前&#xff0c;对s…

数据结构栈的经典OJ题【leetcode最小栈问题大剖析】【leetcode有效的括号问题大剖析】

目录 0.前言 1.最小栈 1.1 原题展示 1.2 思路分析 1.2.1 场景引入 1.2.2 思路 1.3 代码实现 1.3.1 最小栈的删除 1.3.2 最小栈的插入 1.3.3 获取栈顶元素 1.3.4 获取当前栈的最小值 2. 有效的括号 0.前言 本篇博客已经把两个关于栈的OJ题分块&#xff0c;可以根据目…

【华为OD机试模拟题】用 C++ 实现 - 分糖果(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

Jina 3.14 版本发布!支持独立部署Executor

Jina 是一个 MLOps 框架&#xff0c;赋能开发者在云上构建多模态、跨模态的应用程序。Jina 能够将 PoC 提升为生产就绪服务。基础设施的复杂性交给 Jina&#xff0c;开发者能够直接轻松使用高级解决方案和云原生技术。&#x1f31f; GitHubhttps://github.com/jina-ai/jina/rel…

基于博客系统的测试用例

登陆界面博客预览页博客详情页博客编辑页

【华为OD机试模拟题】用 C++ 实现 - 时间格式化(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 分积木(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 吃火锅(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - RSA 加密算法(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 构成的正方形数量(2023.Q1) 【华为OD机试模拟…

MATLAB绘制雷达图/蜘蛛图

雷达图/蜘蛛图 1 方法一 函数来源为MATLAB | 如何使用MATLAB绘制雷达图(蜘蛛图) 1.1 调用函数 1.2 案例 2 方法二 函数来源为MATLAB帮助-spider_plot 2.1 调用函数 语法&#xff08;Syntax&#xff09;&#xff1a; spider_plot(P)spider_plot(P, Name, Value, ...)h …

内网穿透常用方法系列总结

前言在内网渗透时&#xff0c;一个WebShell或CobaltStrike、Metasploit上线等&#xff0c;只是开端&#xff0c;更多是要内网横向移动&#xff0c;扩大战果&#xff0c;打到核心区域。但后渗透的前提是需要搭建一条通向内网的“专属通道”&#xff0c;才能进一步攻击。可实战中…