Java日志处理

news2024/11/18 12:29:28

日志

日志就是Logging,它的目的是为了取代System.out.println()

输出日志,而不是用System.out.println(),有以下几个好处:
(1)可以设置输出样式,避免自己每次都写“ERROR: ” + var
(2)可以设置输出级别,禁止某些级别输出。例如:只输出错误日志
(3)可以被重定向到文件,这样可以在程序运行结束后查看日志
(4)可以按包名控制日志级别,只输出某些包打的日志

日志及分类(三类)

日志根据记录内容不同,分为三类
(1)SQL日志:记录系统执行的SQL语句
(2)异常日志:记录系统运行中发生的异常事件
(3)业务日志:记录系统运行过程,如用户登录、操作记录


JDK Logging(7个级别)

Java标准库内置了日志包java.util.logging,可以直接用

JDK的Logging定义了7个日志级别,从严重到普通:
①server
②warning
③info(默认)
④config
⑤fine
⑥finer
⑦finest

默认级别是INFO。因此,INFO级别以下的日志,不会被打印出来。使用日志级别的好处在于,调整级别,就可以屏蔽掉很多调试相关的日志输出

Logging系统在JVM启动时读取配置文件并完成初始化,一旦开始运行main()方法,就无法修改配置;配置不太方便,需要在JVM启动时传递参数。因此,Java标准库内置的Logging使用并不是非常广泛

Logger logger = Logger.getGlobal();
logger.severe("");
logger.warning("");
logger.info("");
logger.config("");
logger.fine("");
logger.finer("");
logger.finest("");

输出

Mar 02, 2019 6:32:13 PM Hello main
INFO: start process...
Mar 02, 2019 6:32:13 PM Hello main
WARNING: memory is running out...
Mar 02, 2019 6:32:13 PM Hello main
SEVERE: process will be terminated...

使用日志最大的好处是,它自动打印了时间、调用类、调用方法等很多有用的信息

(1)日志是为了替代System.out.println(),可以定义格式,重定向到文件等
(2)日志可以存档,便于追踪问题
(3)日志记录可以按级别分类,便于打开或关闭某些级别
(4)可以根据配置文件调整日志,无需修改代码
(5)Java标准库提供了java.util.logging来实现日志功能


Commons Logging和log4j

(1)通过Commons Logging实现日志,不需要修改代码即可使用Log4j
(2)使用Log4j只需要把log4j2.xml和相关jar放入classpath
(3)如果要更换Log4j,只需要移除log4j2.xml和相关jar
(4)只有扩展Log4j时,才需要引用Log4j的接口(例如,将日志加密写入数据库的功能,需要自己开发)


Commons Logging(6个级别)

和Java标准库提供的日志不同,Commons Logging是一个第三方日志库,它是由Apache创建的日志模块
Commons Logging的特色:可以挂接不同的日志系统,并通过配置文件指定挂接的日志系统。默认情况下,Commons Logging自动搜索并使用Log4j(Log4j是另一个流行的日志系统),如果没有找到Log4j,再使用JDK Logging(需要导入commons logging.jar)

commons-logging有6级日志,但是apache建议使用4级,即 ERROR、WARN、INFO、DEBUG。什么情况下输出日志由程序中写日志的方法决定,输出什么级别以上的日志和输出到哪里由配置文件决定

级别描述
①FATAL记录具有致命日志级别的消息
②ERROR记录具有错误日志级别的消息
③WARN表明会出现潜在错误的情形
④INFO使用信息日志级别记录消息(默认)
⑤DEBUG记录调试日志级别的错误
⑥TRACE使用跟踪日志级别记录消息

需要和两个类打交道,并且只有两步
第一步,通过LogFactory获取Log类的实例; 第二步,使用Log实例的方法打日志

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

Log log = LogFactory.getLog(Main.class);  // Main为本类
log.info("start...");
log.warn("end.");

类名描述
LogFactory抽象类,日志工厂,获取日志类
LogFactoryImplLogFactory的实现类,真正获取日志对象的地方
Log4JLogger对log4j的日志对象封装
Jdk14Logger对JDK1.4的日志对象封装
Jdk13LumberjackLogger对JDK1.3以及以前版本的日志对象封装
SimpleLogcommons-logging自带日志对象

使用Commons Logging时,如果在静态方法中引用Log,通常直接定义一个静态类型变量
在静态方法中引用Log

public class Main {
	static final Log log = LogFactory.getLog(Main.class);
	
	static void foo() {
		log.info("foo");
	}
}

在实例方法中引用Log,通常定义一个实例变量
在实例方法中引用Log

public class Person {
	protected final Log log = LogFactory.getLog(getClass());
	
	void foo() {
		log.info("foo");
	}
}

注意到实例变量log的获取方式是LogFactory.getLog(getClass()),虽然也可以用LogFactory.getLog(Person.class),但是前一种方式有个非常大的好处,就是子类可以直接使用该log实例

父类使用getLog(getClass()),子类可以直接使用log实例
在子类中使用父类实例化的log

public class Student extends Person {
	void bar() {
		log.info("bar");
	}
}

由于Java类的动态特性,子类获取的log字段实际上相当于LogFactory.getLog(Student.class),但却是从父类继承而来,并且无需改动代码

Commons Logging的日志方法,例如info(),除了标准的info(String)外,还提供了一个非常有用的重载方法:info(String, Throwable),这使得记录异常更加简单:

try {
} catch (Exception e) {
	log.error("got exception!", e);
}

log4j

Commons Logging,可以作为“日志接口”来使用。而真正的“日志实现”可以使用Log4j。
Log4j是一种非常流行的日志框架,是一个组件化设计的日志系统,它的架构大致如下
在这里插入图片描述

使用Log4j输出一条日志时,Log4j自动通过不同的Appender把同一条日志输出到不同的目的地
(1)console:输出到屏幕
(2)file:输出到文件
(3)socket:通过网络输出到远程计算机
(4)jdbc:输出到数据库

Log4j也是一个第三方库,需要从这里下载Log4j
在这里插入图片描述

下载jar文件:https://logging.apache.org/log4j/2.x/download.html

以XML配置为例,使用Log4j的时候,把一个log4j2.xml的文件放到classpath下就可以让Log4j读取配置文件并按照我们的配置来输出日志

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
	<Properties>
		<!-- 定义日志格式 -->
		<Property name="log.pattern">%d{MM-dd HH:mm:ss.SSS} [%t] %-5level
			%logger{36}%n%msg%n%n</Property>
		<!-- 定义文件名变量 -->
		<Property name="file.err.filename">log/err.log</Property>
		<Property name="file.err.pattern">log/err.%i.log.gz</Property>
	</Properties>
	<!-- 定义Appender,即目的地 -->
	<Appenders>
		<!-- 定义输出到屏幕 -->
		<Console name="console" target="SYSTEM_OUT">
			<!-- 日志格式引用上面定义的log.pattern -->
			<PatternLayout pattern="${log.pattern}" />
		</Console>
		<!-- 定义输出到文件,文件名引用上面定义的file.err.filename -->
		<RollingFile name="err" bufferedIO="true"
			fileName="${file.err.filename}" filePattern="${file.err.pattern}">
			<PatternLayout pattern="${log.pattern}" />
			<Policies>
				<!-- 根据文件大小自动切割日志 -->
				<SizeBasedTriggeringPolicy size="1 MB" />
			</Policies>
			<!-- 保留最近10份 -->
			<DefaultRolloverStrategy max="10" />
		</RollingFile>
	</Appenders>
	<Loggers>
		<Root level="info">
			<!-- 对info级别的日志,输出到console -->
			<AppenderRef ref="console" level="info" />
			<!-- 对error级别的日志,输出到err,即上面定义的RollingFile -->
			<AppenderRef ref="err" level="error" />
		</Root>
	</Loggers>
</Configuration>

虽然配置Log4j比较繁琐,但一旦配置完成,使用起来就非常方便。对上面的配置文件,凡是INFO级别的日志,会自动输出到屏幕,而ERROR级别的日志,不但会输出到屏幕,还会同时输出到文件。并且,一旦日志文件达到指定大小(1MB),Log4j就会自动切割新的日志文件,并最多保留10份

在开发阶段,始终使用Commons Logging接口来写入日志,并且开发阶段无需引入Log4j。如果需要把日志写入文件, 只需要把正确的配置文件和Log4j相关的jar包放入classpath,就可以自动把日志切换成使用Log4j写入,无需修改任何代码

log4j.properties

在CLASSPATH 下建立log4j.properties
log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
log4j.appender.stdout.Target=System.out  
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
log4j.appender.stdout.layout.ConversionPattern=%d %5p %c{1}:%L - %m%n

log4j.appender.file=org.apache.log4j.RollingFileAppender  
log4j.appender.file.File=${catalina.home}/logs/ddoMsg.log  
#log4j.appender.file.File=D:/SmgpAppService/logs/smgpApp.log  
log4j.appender.file.MaxFileSize=1024KB  
log4j.appender.file.MaxBackupIndex=100  
log4j.appender.file.layout=org.apache.log4j.PatternLayout  
log4j.appender.file.layout.ConversionPattern= %d{yyyy-MM-dd HH:mm:ss} %5p %c %t: - %m%n  
  
#INFO WARN ERROR DEBUG  
log4j.rootLogger=WARN, file, stdout  
#log4j.rootLogger=INFO,stdout  
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog  
#org.apache.commons.logging.simplelog.log.org.apache.commons.digester.Digester=debug  
#org.apache.commons.logging.simplelog.log.org.apache.commons.digester.ObjectCreateRule=debug  
#org.apache.commons.logging.simplelog.log.org.apache.commons.digester.Digester.sax=info 
log4j.logger.com.jason.ddoMsg=debug 

logger配置说明

log4j.rootLogger=INFO, stdout , R
此句为将等级为INFO的日志信息输出到stdout和R这两个目的地,stdout和R的定义在下面的代码,可以任意起名。
等级可分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL,如果配置OFF则不打出任何信息,如果配置为INFO这样只显示INFO, WARN, ERROR的log信息,而DEBUG信息不会被显示

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
此句为定义名为stdout的输出端是哪种类型,可以是

org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
此句为定义名为stdout的输出端的layout是哪种类型,可以是

org.apache.log4j.HTMLLayout(以HTML表格形式布局)
org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

log4j.appender.stdout.layout.ConversionPattern= [QC] %p [%t] %C.%M(%L) | %m%n
如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern,打印参数如下:

格式描述
[QC]log信息的开头,可以为任意字符,一般为项目简称
%m输出代码中指定的消息
%p输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r输出自应用启动到输出该log信息耗费的毫秒数
%c输出所属的类目,通常就是所在类的全名
%t输出产生该日志事件的线程名
%n输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
%d输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
%l输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数

输出的信息
[TS] DEBUG [main] AbstractBeanFactory.getBean(189) | Returning cached instance of singleton bean ‘MyAutoProxy’

log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
此句与第3行一样。定义名为R的输出端的类型为每天产生一个日志文件

log4j.appender.R.File=D:\Tomcat 5.5\logs\qc.log
此句为定义名为R的输出端的文件名为D:\Tomcat 5.5\logs\qc.log可以自行修改

log4j.appender.R.layout=org.apache.log4j.PatternLayout
与第4行相同

log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n
与第5行相同

log4j.logger.com. neusoft =DEBUG
指定com.neusoft包下的所有类的等级为DEBUG。
可以把com.neusoft改为自己项目所用的包名。

log4j.logger.com.opensymphony.oscache=ERROR
log4j.logger.net.sf.navigator=ERROR

这两句是把这两个包下出现的错误的等级设为ERROR,如果项目中没有配置EHCache,则不需要这两句

log4j.logger.org.apache.commons=ERROR
log4j.logger.org.apache.struts=WARN

这两句是struts的包

log4j.logger.org.displaytag=ERROR
这句是displaytag的包。(QC问题列表页面所用)

log4j.logger.org.springframework=DEBUG
此句为spring的包

log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
log4j.logger.org.hibernate=DEBUG

此两句是hibernate的包


以上这些包的设置可根据项目的实际情况而自行定制

log4j.rootLogger=DEBUG,console  

#以下是rootLogger的配置,子类默认继承,但是子类重写下面配置=rootLogger+自己配置
#输出到控制台     
log4j.appender.console=org.apache.log4j.ConsoleAppender    
#设置输出样式     
log4j.appender.console.layout=org.apache.log4j.PatternLayout   
#日志输出信息格式为  
log4j.appender.console.layout.ConversionPattern=[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n   

SLF4J和Logback

Commons Logging和Log4j(Simple logging这一对好基友,它们一个负责充当日志API,一个负责实现日志底层,搭配使facade for Java)用非常便于开发
SLF4J类似于Commons Logging,也是一个日志接口,而Logback类似于Log4j,是一个日志的实现

SLF4J对Commons Logging的接口有何改进。在Commons Logging中,要打印日志,有时候得这么写:

Log log = LogFactory.getLog(Main.class);  // Main为本类
int score = 99;
p.setScore(score);
log.info("Set score " + score + " for Person " + p.getName() + " ok.");

拼字符串是一个非常麻烦的事情,所以SLF4J的日志接口改进成这样了:

Logger log = LoggerFactory.getLogger(Main.class);  // Main为本类
int score = 99;
p.setScore(score);
logger.info("Set score {} for Person {} ok.", score, p.getName());

SLF4J的日志接口传入的是一个带占位符的字符串,用后面的变量自动替换占位符,所以看起来更加自然


SLF4J的接口实际上和Commons Logging几乎一模一样

Commons LoggingSLF4J
org.apache.commons.logging.Logorg.slf4j.Logger
org.apache.commons.logging.LogFactoryorg.slf4j.LoggerFactory
不同之处就是Log变成了Logger,LogFactory变成了LoggerFactory

logback同log4j相比具有众多优势
(1)更快的实现
(2)自动重新装载日志配置文件
(3)更好的过滤器(filter)
(4)自动压缩归档的日志文件
(5)堆栈跟踪里包括了Java包(jar文件)的信息
(6)自动删除旧日志归档文件

SLF4J:http://www.slf4j.org/download.html
Logback:https://logback.qos.ch/download.html

在这里插入图片描述

使用SLF4J的Logger和LoggerFactory即可。和Log4j类似,仍然需要一个Logback的配置文件,把logback.xml放到classpath下

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
		</encoder>
	</appender>

	<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<encoder>
			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
			<charset>utf-8</charset>
		</encoder>
		<file>log/output.log</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
			<fileNamePattern>log/output.log.%i</fileNamePattern>
		</rollingPolicy>
		<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
			<MaxFileSize>1MB</MaxFileSize>
		</triggeringPolicy>
	</appender>

	<root level="INFO">
		<appender-ref ref="CONSOLE" />
		<appender-ref ref="FILE" />
	</root>
</configuration>

从目前的趋势来看,越来越多的开源项目从Commons Logging加Log4j转向了SLF4J加Logback

(1)SLF4J和Logback可以取代Commons Logging和Log4j
(2)始终使用SLF4J的接口写入日志,使用Logback只需要配置,不需要修改代码

<!--   
    configuration为根元素,包含三个属性:  
    debug,指是否开启logback内部日志,没有设置此属性或设置其值为空、null或false时,表示不开启,否则,开启;
    scan,设置是否定时扫描配置文件
    scanPeriod,设置扫描周期,与scan属性配合使用,默认是60000毫秒,如果该属性值没有带单位,则单位为毫秒,可带的单位有milli/millisecond/second/seconde/minute/hour/day,可忽略大小写  
-->  
<configuration debug="true" scan="true" scanPeriod="600 seconds">  
  
    <!--   
        appender表示日志输出的方式,该元素必须包含name、classs属性;  
        name,表示appender的唯一标识  
        class一般常见有ch.qos.logback.core.FileAppender、ch.qos.logback.core.rolling.RollingFileAppender、ch.qos.logback.core.ConsoleAppender  
    -->  
    <!-- 下面appender表示输出到控制台 -->  
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">  
        <!-- 设置级别过滤器 -->  
        <filter class="ch.qos.logback.classic.filter.LevelFilter">  
            <!-- level级别的日志才会被处理,其他级别不处理 -->  
            <level>DEBUG</level>  
            <!-- 用于配置符合条件的操作 -->  
            <onMatch>ACCEPT</onMatch>  
            <!-- 用于配置不符合条件的操作 -->  
            <onMismatch>DENY</onMismatch>  
        </filter>  
        <!-- encoder指定编码格式,并根据指定的pattern输出日志信息 -->  
        <encoder charset="UTF-8">  
            <!-- pattern指定日志的输出格式 -->  
            <pattern>%d{HH:mm:ss.SSS}[%-5level][%thread][%logger{20}]-%msg%n</pattern>  
        </encoder>  
    </appender>  
  
    <!-- 下面是将日志输入到指定的文件中 -->  
    <appender name="file" class="ch.qos.logback.core.FileAppender">    
        <!-- 指定的日志文件名 -->  
        <file>logFile.log</file>  
        <!-- 是否追加到文件末尾,默认true -->  
        <append>true</append>  
        <encoder>  
          <pattern>%-4r [%thread] %-5level %logger{35} - %msg%n</pattern>  
        </encoder>  
    </appender>  
  
    <!-- 下面是以滚动的方式生成日志文件 -->  
    <appender name="rollingFile"  
        class="ch.qos.logback.core.rolling.RollingFileAppender">  
  
        <!-- 下面是设置的临界值过滤器 -->  
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">  
            <!-- 小于level级别的日志会被过滤掉 -->  
            <level>INFO</level>  
        </filter>  
  
        <!-- rollingPolicy表示滚动策略,下面表示以时间来指定滚动策略 -->  
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
            <!-- 如果用TimeBasedRollingPolicy,则fileNamePattern元素必须包含,指定日志的名称 -->  
            <fileNamePattern>E:/demo-%d{yyyy-MM-dd}.log</fileNamePattern>  
            <!-- 文件的最大保留数,超过此数字会自动删除 -->  
            <maxHistory>90</maxHistory>  
        </rollingPolicy>  
  
        <encoder>  
            <pattern>%d{HH:mm:ss.SSS}[%-5level][%thread][%logger{20}]-%msg%n</pattern>  
            <!-- 是否立即清空输出流,设置为false可以提高性能,但日志可能会丢失 -->  
            <immediateFlush>false</immediateFlush>  
        </encoder>  
    </appender>  
  
    <!-- root与logger类似,它表示根logger,只有大于等于level级别的日志才交由appender处理,level默认为DEBUG -->  
    <root level="INFO">  
        <appender-ref ref="stdout" />  
        <appender-ref ref="rollingFile" />  
        <appender-ref ref="file" />  
    </root>  
  
    <!--   
        logger元素用来设置某包或者类的日志输出级别  
        name:表示某包或类名称  
        level:表示日志级别,如果没有此属性,那么当前的logger会继承上级的日志级别  
    -->  
    <logger name="com.erayt" level="INFO" />  
    <logger name="com.erayt.solar2" level="DEBUG" />  
    <logger name="com.googlecode" level="WARN" />  
    <logger name="com.ibatis" level="WARN" />  
    <logger name="com.opensymphony" level="WARN" />  
    <logger name="com.opensymphony.xwork2" level="WARN" />  
    <logger name="net.sf" level="WARN" />  
    <logger name="org.apache" level="INFO" />  
    <logger name="org.apache.struts2" level="WARN" />  
    <logger name="org.codehaus" level="WARN" />  
    <logger name="org.jgroups" level="WARN" />  
    <logger name="org.springframework" level="WARN" />  
    <logger name="java.sql.Connection" level="WARN" />  
    <logger name="java.sql.PreparedStatement" level="WARN" />  
    <logger name="java.sql.ResultSet" level="WARN" />  
</configuration> 




上一篇:异常(throwable)                        下一篇:IDEA中使用SVN




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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

故障分析 | 一次规律的 MySQL 主从延迟跳变

作者&#xff1a;李彬 爱可生 DBA 团队成员&#xff0c;负责项目日常问题处理及公司平台问题排查。爱好有亿点点多&#xff0c;吉他、旅行、打游戏… 本文来源&#xff1a;原创投稿 *爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注…

WxGL应用实例:绘制高精度的3D太阳系模型

文章目录 1 坐标系的选择1.1 黄道坐标系1.2 三维空间直角坐标系 2 使用JPL星历表计算轨道2.1 日期时间2.2 特定时刻天体的位置2.3 天体运行轨道 3 太阳系模型3. 1 全家福3.2 时间、距离和半径的缩放3.3 黄道坐标系模型 天何所沓&#xff1f;十二焉分&#xff1f;日月安属&#…

拆解Open ODS View和HANA Composite Provider

这两个也不是新面孔了。 那么OODS和HCPR到底他俩怎么用&#xff1f;既然大家都是虚拟的&#xff0c;不占地方。那这俩infoprovider到底有啥区别&#xff1f; 首先就是目的不同。 HCPR是可以用Union和Join。也就是老的Multiprovider和InfoSet。Union就是说两个数据集的行能被…

UniLM模型简单介绍

目录 一、概要 二、深入扩展 2.1 预训练任务 2.2 模型精调 一、概要 如果将基于Transformer的双向语言模型&#xff08;如BERT模型中的掩码语言模型&#xff09;与单向的自回归语言模型&#xff08;如BART模型的解码器&#xff09;进行对比&#xff0c;可以发现&#xff0c…

常见的注册中心Nacos、Eureka

常见的注册中心 1.Eureka&#xff08;原生&#xff0c;2.0遇到瓶颈&#xff0c;停止维护&#xff09; 2.Zookeeper&#xff08;支持&#xff0c;专业的独立产品。例如&#xff1a;dubbo&#xff09; 3.Consul&#xff08;原生&#xff0c;GO语言开发&#xff09; 4.Nacos …

中国社科院与美国杜兰大学金融管理硕士项目——在职读研的日子里藏着我们未来无限可能

人生充满期待&#xff0c;梦想连接着未来。每一天都可以看作新的一页&#xff0c;要努力去成为最好的自己。在职读研的光阴里藏着无限的可能&#xff0c;只有不断的努力&#xff0c;不断的强大自己&#xff0c;未来会因为你的不懈坚持而发生改变&#xff0c;纵使眼前看不到希望…

算法---统计参与通信的服务器

题目 这里有一幅服务器分布图&#xff0c;服务器的位置标识在 m * n 的整数矩阵网格 grid 中&#xff0c;1 表示单元格上有服务器&#xff0c;0 表示没有。 如果两台服务器位于同一行或者同一列&#xff0c;我们就认为它们之间可以进行通信。 请你统计并返回能够与至少一台其…

【C语言】调试工具GDB简述

一、说明 GDB&#xff08;GNU Debugger&#xff09;是UNIX及UNIX-like下的强大调试工具&#xff0c;可以调试ada, c, c, asm, minimal, d, fortran, objective-c, go, java,pascal等语言。本文介绍GDB启动调试的方式。 二、Ubuntu上安装gdb。 在root用户权限下&#xff1a; roo…

【通过蓝牙滚动文本和Android控制】

【通过蓝牙滚动文本和Android控制】 1. 概述2. MAX72193. 电路原理图4. MAX7219基本Arduino代码5. 88 LED矩阵滚动Arduino代码6. 用于通过蓝牙控制 88 LED 矩阵的安卓应用程序1. 概述 我们将做三个例子,第一个例子我们将解释MAX7219的基本工作原理,在第二个例子中,我们将看…

scala控制抽象之传名参数(名调用)

我们在用scala定义函数时&#xff0c;一般参数都是各种类型的值&#xff0c;这是常见的值调用 但偶尔也有需要把代码块作为参数传入的情况&#xff08;名调用&#xff09; 匿名函数经常可以作为函数的参数传入&#xff0c;非匿名函数也行&#xff08;函数作为返回值返回就更常见…

都说软件测试不行了,真的是这样吗?

最近在各大平台经常会听到大家说这样的话&#xff1a; 现在公司都不招人&#xff0c;测试员根本找不到工作 简历石沉大海、面试机会也没有&#xff0c;软件测试是不是不行了 软件测试行情到底如何&#xff1f; 作为软件员在如今的情况下又该怎么做&#xff1f; 其实现在所…

ai生成文章 免费-自动生成文章

原创文章自动生成器 随着人工智能技术的快速发展&#xff0c;越来越多的创新产品得以应用到我们的日常工作中。其中&#xff0c;原创文章自动生成器是一种高效、智能的工具&#xff0c;它可以帮助企业快速生成符合要求的优质文章。在本文中&#xff0c;我将向您介绍原创文章自…

数据结构算法leetcode刷题练习(1)

给定一个三角形 triangle &#xff0c;找出自顶向下的最小路径和。 每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 1 的两个结点。也就是说&#xff0c;如果正位于当前行的下标 i &#xff0c;那么下一…

4.2 插值多项式的求法

学习目标&#xff1a; 我会采取以下几个步骤来学习插值多项式的求法&#xff1a; 学习预备知识&#xff1a;插值多项式的求法需要掌握一定的数学知识&#xff0c;例如多项式函数的定义、导数、微积分、线性代数等等。因此&#xff0c;学习插值多项式的求法前&#xff0c;需要先…

掘金AIGC时代,开发者更需要什么样的大模型?

当前&#xff0c;火热的AI大模型领域需要一些冷思考。 自去年年底ChatGPT掀起一轮AIGC热潮以来&#xff0c;国内科技企业扎堆发布大模型和类ChatGPT产品。截止2023年4月&#xff0c;已公开宣布发布或即将发布AI大模型的企业达数十家。多模态大模型的能力不断迭代&#xff0c;市…

2023年自动化测试真有那么重要吗?内卷严重,测试技能水涨船高......

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 学习自动化测试有…

应用现代化语境下的技术重塑:谁在帮助企业自我革命?

文丨智能相对论 作者丨沈浪 在数字经济时代&#xff0c;应用现代化正在成为一个共识。在IDC发布的《IDC FutureScape&#xff1a;全球云计算2022年预测-中国启示》报告中&#xff0c;应用现代化就位居首位。同时&#xff0c;IDC也预测&#xff0c;到2025年&#xff0c;数字经…

更新 WinForms | InitializeComponent 的现代代码生成

当你使用 Visual Studio 中的 WinForms Designer 来创建一个 WinForms 表单或用户控件时&#xff0c;它并没有像 XML 或 HTML 那样的特殊定义或文件格式来表示用户界面。从一开始&#xff0c;WinForms 使用的唯一格式就是程序代码。在 WinForms Visual Basic 项目中定义的表单或…

ONES 联合中国信通院发布《中国企业软件研发管理白皮书》

4月20日&#xff0c;由 ONES 与中国信通院联合发起的《中国企业软件研发管理白皮书》发布会暨「软件质效沙龙一北京站」正式举行。发布会上&#xff0c;ONES 与中国信通院云计算与大数据研究所的各位领导、行业专家及众多软件从业者一起&#xff0c;聚焦研发管理热点动态&#…

【hello C++】内存管理

目录 前言&#xff1a; 1. C/C内存分布 2. C语言动态内存管理方式 3. C内存管理方式 3.1 new / delete 操作内置类型 3.2 new和delete操作自定义类型 4. operator new与operator delete函数 4.1 operator new与operator delete函数 5. new和delete的实现原理 5.1 内置类型 5.2…