挖一挖:PostgreSQL Java里的double类型存储到varchar精度丢失问题

图片

前言

大概故事是这样的,PostgreSQL数据库,表结构:

create table t1(a varchar);

然后使用标准的Java jdbc去插入数据,其基本代码如下:

import java.sql.*;
public class PgDoubleTest {public static void main(String[] args) {Connection connection = null;ResultSet resultSet = null;PreparedStatement ps= null;try {// 连接到数据库connection = DriverManager.getConnection("jdbc:postgresql://192.168.0.6:5432/mydb", "mydb", "test123");String sql="insert into t1 values(?)";ps = connection.prepareStatement(sql);ps.setObject(1,new Double(48));ps.execute();ps.setObject(1,new Double(48.1));ps.execute();ps.setObject(1,new Double(48.9));ps.execute();} catch (SQLException e) {e.printStackTrace();} finally {try {if (ps != null) {ps.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}
}

发现 PostgreSQL11和12及以后的版本,插入到表t1中的记录值不一样。

PG11中的结果:

mydb=# select * from t1;a
---------------------4848.100000000000001448.8999999999999986
(3 rows)

PG12及后续版本的结果:

mydb=# select * from t1;a
------4848.148.9
(3 rows)

这个问题如何分析?

分析

上边的Java代码片段,采用的都是完全相同的jdbc driver:

        <dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><version>42.7.3</version></dependency>

有几种可能性,驱动层根据服务器端不同的版本,发送的数据就完全不同。或者服务器端根据客户端来的数据,处理有所不同。

检查下SQL日志

我们分别打开:postgresql.conf,开启记录所有的SQL

log_statement = 'all' # none, ddl, mod, all

于是看到,PG11的日志是这样的:

2024-03-30 11:20:46.235 CST [13553] LOG:  execute <unnamed>: SET extra_float_digits = 3
2024-03-30 11:20:46.236 CST [13553] LOG:  execute <unnamed>: SET application_name = 'PostgreSQL JDBC Driver'
2024-03-30 11:20:46.262 CST [13553] LOG:  execute <unnamed>: insert into t1 values($1)
2024-03-30 11:20:46.262 CST [13553] DETAIL:  parameters: $1 = '48'
2024-03-30 11:20:46.265 CST [13553] LOG:  execute <unnamed>: insert into t1 values($1)
2024-03-30 11:20:46.265 CST [13553] DETAIL:  parameters: $1 = '48.1000000000000014'
2024-03-30 11:20:46.266 CST [13553] LOG:  execute <unnamed>: insert into t1 values($1)
2024-03-30 11:20:46.266 CST [13553] DETAIL:  parameters: $1 = '48.8999999999999986'
2024-03-30 11:21:11.696 CST [13555] LOG:  statement: select * from t1;

而PG12的日志是这样的:

2024-03-30 10:45:30.172 CST [2700] LOG:  execute <unnamed>: SET extra_float_digits = 3
2024-03-30 10:45:30.173 CST [2700] LOG:  execute <unnamed>: SET application_name = 'PostgreSQL JDBC Driver'
2024-03-30 10:45:30.197 CST [2700] LOG:  execute <unnamed>: insert into t1 values($1)
2024-03-30 10:45:30.197 CST [2700] DETAIL:  parameters: $1 = '48'
2024-03-30 10:45:30.199 CST [2700] LOG:  execute <unnamed>: insert into t1 values($1)
2024-03-30 10:45:30.199 CST [2700] DETAIL:  parameters: $1 = '48.1'
2024-03-30 10:45:30.200 CST [2700] LOG:  execute <unnamed>: insert into t1 values($1)
2024-03-30 10:45:30.200 CST [2700] DETAIL:  parameters: $1 = '48.9'

也就是说到了服务器端,绑定参数值的时候,就已经不同了。PG11里头,传的字符串值已经有了变化了。很有意思的东西。我们不忙着下结论。

既然Server端的log不能判定,我们可以看看driver层的详细的log信息。这个需要设置logging.properties. 详情可以参考文档:https://jdbc.postgresql.org/documentation/logging/

查看JDBC客户端driver层日志

PG12的相关日志有如下关键内容:

三月 31, 2024 3:49:55 下午 org.postgresql.Driver connect
详细: Connecting with URL: jdbc:postgresql://192.168.0.6:5555/mydb?loggerLevel=TRACE&loggerFile=jdbc.log
三月 31, 2024 3:49:55 下午 org.postgresql.jdbc.PgConnection <init>
详细: PostgreSQL JDBC Driver 42.7.3
三月 31, 2024 3:49:55 下午 org.postgresql.jdbc.PgConnection setDefaultFetchSize
详细:   setDefaultFetchSize = 0非常详细:  <=BE ParameterStatus(server_version = 12.11)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveParameterStatus
非常详细:  <=BE ParameterStatus(session_authorization = mydb)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveParameterStatus
非常详细:  <=BE ParameterStatus(standard_conforming_strings = on)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveParameterStatus
非常详细:  <=BE ParameterStatus(TimeZone = Asia/Shanghai)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl readStartupMessages
非常详细:  <=BE BackendKeyData(pid=8,855,ckey=-1,722,642,031)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细:  <=BE ReadyForQuery(I)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细:   simple execute, handler=org.postgresql.core.SetupQueryRunner$SimpleResultHandler@614ddd49, maxRows=0, fetchSize=0, flags=1,047
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细:  FE=> Parse(stmt=null,query="SET extra_float_digits = 3",oids={})
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细:  FE=> Bind(stmt=null,portal=null)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendExecute
非常详细:  FE=> Execute(portal=null,limit=1)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendSync
非常详细:  FE=> Sync
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE ParseComplete [null]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE BindComplete [unnamed]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveCommandStatus
非常详细:  <=BE CommandStatus(SET)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细:  <=BE ReadyForQuery(I)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细:   simple execute, handler=org.postgresql.core.SetupQueryRunner$SimpleResultHandler@711f39f9, maxRows=0, fetchSize=0, flags=1,047
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细:  FE=> Parse(stmt=null,query="SET application_name = 'PostgreSQL JDBC Driver'",oids={})
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
....
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细:  <=BE ReadyForQuery(I)
三月 31, 2024 3:49:55 下午 org.postgresql.jdbc.PgConnection <init>
非常详细:     types using binary send = OID_ARRAY,UUID,BYTEA,INT8,INT2,INT4,POINT,TIMESTAMP,BOX,TIMESTAMPTZ,NUMERIC,BYTEA_ARRAY,INT2_ARRAY,INT4_ARRAY,TEXT_ARRAY,TIMETZ,VARCHAR_ARRAY,INT8_ARRAY,TIME,FLOAT4,FLOAT8,FLOAT4_ARRAY,FLOAT8_ARRAY
三月 31, 2024 3:49:55 下午 org.postgresql.jdbc.PgConnection <init>
非常详细:     types using binary receive = OID_ARRAY,UUID,BYTEA,INT8,INT2,INT4,POINT,TIMESTAMP,BOX,TIMESTAMPTZ,NUMERIC,BYTEA_ARRAY,INT2_ARRAY,INT4_ARRAY,TEXT_ARRAY,TIMETZ,VARCHAR_ARRAY,INT8_ARRAY,DATE,TIME,FLOAT4,FLOAT8,FLOAT4_ARRAY,FLOAT8_ARRAY
三月 31, 2024 3:49:55 下午 org.postgresql.jdbc.PgConnection <init>
非常详细:     integer date/time = true
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细:   simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@2353b3e6, maxRows=0, fetchSize=0, flags=17
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细:  FE=> Parse(stmt=null,query="insert into t1 values($1)",oids={701})
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.0'::double precision)>,type=FLOAT8)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
非常详细:  FE=> Describe(portal=null)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendExecute
非常详细:  FE=> Execute(portal=null,limit=0)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendSync
非常详细:  FE=> Sync
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE ParseComplete [null]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE BindComplete [unnamed]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE NoData
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveCommandStatus
非常详细:  <=BE CommandStatus(INSERT 0 1)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细:  <=BE ReadyForQuery(I)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细:   simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@42f93a98, maxRows=0, fetchSize=0, flags=17
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细:  FE=> Parse(stmt=null,query="insert into t1 values($1)",oids={701})
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.1'::double precision)>,type=FLOAT8)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
非常详细:  FE=> Describe(portal=null)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendExecute
非常详细:  FE=> Execute(portal=null,limit=0)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendSync
非常详细:  FE=> Sync
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE ParseComplete [null]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE BindComplete [unnamed]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE NoData
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveCommandStatus
非常详细:  <=BE CommandStatus(INSERT 0 1)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细:  <=BE ReadyForQuery(I)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细:   simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@c46bcd4, maxRows=0, fetchSize=0, flags=17
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细:  FE=> Parse(stmt=null,query="insert into t1 values($1)",oids={701})
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.9'::double precision)>,type=FLOAT8)

我们看到上边有明显的:

非常详细:  <=BE ParameterStatus(server_version = 12.11)
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.0'::double precision)>,type=FLOAT8)
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.1'::double precision)>,type=FLOAT8)
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.9'::double precision)>,type=FLOAT8)
FE=> Parse(stmt=null,query="SET extra_float_digits = 3",oids={})

再看看PG11下边的详细日志:

三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl receiveParameterStatus
非常详细:  <=BE ParameterStatus(server_version = 11.22 [by Sean])
。。
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.0'::double precision)>,type=FLOAT8)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
非常详细:  FE=> Describe(portal=null)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendExecute
非常详细:  FE=> Execute(portal=null,limit=0)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendSync
非常详细:  FE=> Sync
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE ParseComplete [null]
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE BindComplete [unnamed]
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE NoData
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl receiveCommandStatus
非常详细:  <=BE CommandStatus(INSERT 0 1)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细:  <=BE ReadyForQuery(I)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细:   simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@42f93a98, maxRows=0, fetchSize=0, flags=17
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细:  FE=> Parse(stmt=null,query="insert into t1 values($1)",oids={701})
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.1'::double precision)>,type=FLOAT8)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
非常详细:  FE=> Describe(portal=null)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendExecute
非常详细:  FE=> Execute(portal=null,limit=0)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendSync
非常详细:  FE=> Sync
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE ParseComplete [null]
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE BindComplete [unnamed]
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细:  <=BE NoData
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl receiveCommandStatus
非常详细:  <=BE CommandStatus(INSERT 0 1)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细:  <=BE ReadyForQuery(I)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细:   simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@c46bcd4, maxRows=0, fetchSize=0, flags=17
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细:  FE=> Parse(stmt=null,query="insert into t1 values($1)",oids={701})
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.9'::double precision)>,type=FLOAT8)

找出关键的几行:

非常详细:  <=BE ParameterStatus(server_version = 11.22 [by Sean])
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.0'::double precision)>,type=FLOAT8)
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.1'::double precision)>,type=FLOAT8)
非常详细:  FE=> Bind(stmt=null,portal=null,$1=<('48.9'::double precision)>,type=FLOAT8)
FE=> Parse(stmt=null,query="SET extra_float_digits = 3",oids={})

比较后的总结、模拟重现与深挖

从驱动层来看,发送过去的内容或指令应该是一样的。只是Server端对于类似于如下的binding,分别有精度损失或没有精度损失:

$1=<('48.1'::double precision)>,type=FLOAT8)

我们看看PG11下边的一些行为:

show extra_float_digits;extra_float_digits
--------------------0
(1 row)select '48.1'::float8;float8
--------48.1
(1 row)SET extra_float_digits = 3;
SET
mydb=# select '48.9'::float8;float8
---------------------48.8999999999999986
(1 row)

看到了吗?在extra_float_digits = 3;时,结果就出来了。'48.8999999999999986'

而到了PG12,结果是这样:

mydb=# show extra_float_digits;extra_float_digits
--------------------1
(1 row)mydb=# select '48.1'::double precision;float8
--------48.1
(1 row)mydb=# SET extra_float_digits = 3;
SET
mydb=# select '48.1'::double precision;float8
--------48.1
(1 row)

所以, 从上边的分析来看,是server端对于extra_float_digits = 3时,在字符串转到float8 (double precision)时的行为不一样导致的。

至此,真相大白。

我们也可以看下参数extra_float_digits的真实含义:

https://postgresqlco.nf/doc/zh/param/extra_float_digits/ :Sets the number of digits displayed for floating-point values

这个参数调整用于文本输出浮点值的位数,包括float4,float8以及几何数据类型。

如果值为1(默认值)或更高,浮点值被输出为最短-精度格式;参见datatype-float。实际生成的位数只取决于输出的值,而不取决于此参数的值。float8 值最多需要 17 位数字,float4值最多需要9位数字。这种格式既快速又精确,在正确读取时精确地保留了原始的二进制浮点值。为了历史兼容性,允许的值最大为3。

如果值为零或负,则输出四舍五入为给定的十进制精度。使用的精度是根据此参数的值减小的类型((FLT_DIGDBL_DIG,视情况而定)的标准位数。(例如,指定 -1 将导致float4 值输出四舍五入为 5 位有效数字,而float8值四舍五入为 14 位。) 此格式较慢,不会保留二进制浮点值的所有位,但可能令人更易于阅读。

此参数的含义,以及其默认值,在 PostgreSQL 12 中发生了变化; 参见 datatype-float 以便进一步讨论。

我在:PostgreSQL, 留心对应的BigDecimal,Float,Double几种Java类型也有关于float8类型的详细介绍 。

总结

分析这类问题,在源码介入之前,通过两端的日志进行对比分析,往往也能抓到蛛丝马迹。进而可以进一步进行挖掘和分析。上边的Java代码,最后都可以通过简单的SQL片段来重现。

参考:

https://www.enterprisedb.com/blog/jdbc-logging-using-javautillogging

https://jdbc.postgresql.org/documentation/logging/

https://postgresqlco.nf/doc/zh/param/extra_float_digits/

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

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

相关文章

C语言TCP服务器模型 : select + 多线程与双循环单线程阻塞服务器的比较

观察到的实验现象: 启动三个客户端: 使用双循环阻塞服务器:只能accept后等待收发,同时只能与一个客户端建立连接,必须等已连接的客户端多次收发 明确断开后才能与下个客户端连接 使用IO多路复用select:可以同时接收所有的连接请求,并且连接状态一直是存活的,直到客户端关闭连…

53 v-bind 和 v-model 的实现和区别

前言 这个主要的来源是 偶尔的情况下 出现的问题 就比如是 el-select 中选择组件之后, 视图不回显, 然后 model 不更新等等 这个 其实就是 vue 中 视图 -> 模型 的数据同步, 我们通常意义上的处理一般是通过 模型 -> 数据 的数据同步, 比如 我们代码里面更新了 model.…

C#/.NET/.NET Core优秀项目和框架2024年3月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架&#xff08;每周至少会推荐两个优秀的项目和框架当然节假日除外&#xff09;&#xff0c;公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等&#xff08;打不开或者打开GitHub很慢的同学…

变更控制、变更类型

目录 1、变更控制 2、变更类型 1、变更控制 在软件开发过程中会有许多变更&#xff0c;如代码、配置、SQL、基线、构建版本、发布版本等变更。对于变更都要有一个控制机制&#xff0c;以保证所以变更都是可控的、可跟踪的、可重现的。对变更进行控制的机构称为变更控制委员会…

爬虫(Web Crawler)介绍与应用

## 摘要 本文将介绍什么是爬虫&#xff08;Web Crawler&#xff09;以及其在信息抓取、数据分析等领域的应用。我们将深入探讨爬虫的工作原理、设计特点以及开发过程中需要考虑的关键问题。 ## 一、什么是爬虫 爬虫是一种自动化程序或脚本&#xff0c;用于从互联网上抓取信息…

[HackMyVM]靶场Pipy

难度:easy kali:192.168.56.104 靶机:192.168.56.141 端口扫描 ┌──(root㉿kali2)-[~/Desktop] └─# nmap 192.168.56.141 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-31 20:10 CST Nmap scan report for 192.168.56.141 Host is up (0.00…

Vitepress部署到GitHub Pages,工作流

效果&#xff1a; 第一步&#xff1a; 部署 VitePress 站点 | VitePress 执行 npm run docs:build&#xff0c;npm run docs:preview&#xff0c;生成dist文件 第二步&#xff1a; 手动创建.gitignore文件&#xff1a; node_modules .DS_Store dist-ssr cache .cache .temp *…

Python100个库分享第5个—fuzzywuzzy

目录 专栏导读库介绍安装fuzz模块用法1&#xff1a;简单匹配&#xff08;Ratio&#xff09;fuzz模块用法2&#xff1a;推荐使用—非完全匹配&#xff08;Partial Ratio&#xff09;fuzz模块用法3&#xff1a;Token Sort Ratio&#xff09;process模块extract提取多条数据extrac…

55 npm run serve 和 npm run build 的分包策略

前言 这里我们来看一下 vue 这边 打包的时候的一些 拆分包的一些策略 我们经常会使用到 npm run build 进行服务的打包 然后 打包出来的情况, 可能如下, 可以看到 chunk-vendors 是进行了包的拆分, 我们这里就是 来看一下 这里 npm run build 的时候的, 一个分包的策略 测试…

Verilog基础【一】

文章目录 1.1 第一个verilog设计1.2 Verilog 简介1.3 Verilog环境搭建1.4 Verilog 设计方法设计方法设计流程 2.1 Verilog 基础语法格式注释标识符与关键字 2.2 Verilog 数值表示数值种类整数数值表示方法实数表示方法十进制&#xff1a;科学计数法&#xff1a; 字符串表示方法…

ubuntu23.10配置RUST开发环境

系统版本: gcc版本 下载rustup安装脚本: curl --proto https --tlsv1.2 https://sh.rustup.rs -sSf | sh下载完成后会自动执行 选择默认安装选项 添加cargo安装目录到环境变量 vim ~/.bashrc 默认已添加 使用环境变量立即生效 source ~/.bashrc 执行rust开发环境,在终端输入…

使用Pilotfish扩展Sui执行能力

Pilotfish第一个多机智能合约执行引擎&#xff0c;使Sui网络的验证节点可以利用多台机器&#xff0c;并在负载增加时自动扩展以执行更多的交易。这一目标实现不会影响可靠性或功能完整性。 Pilotfish可以从内部执行机器的故障中恢复&#xff0c;并支持Sui的全面动态操作。其流…

表白墙项目(JAVA实现)

1、在html里 class使用. id使用# 2、记得引入响应依赖&#xff08;举例lombok&#xff09; 3、messageController package com.example.demo.demos.web; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; i…

Springboot集成knife4j (swagger)

1、添加依赖 在pom.xml 文件中添加 knife4j-spring-boot-starter 的依赖 <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>3.0.3</version> </depe…

【千帆杯】K12教育常规赛 北京场线下交流会心得

千帆杯K12教育常规赛 北京场线下交流会心得 ​ 周日有幸参加了 百度智能云千帆AppBuilder北京场线下交流会 ( 活动链接 )&#xff0c;去线下组队创作了 K12教育 相关的智能体。参赛过程中认识了不少大佬与朋友&#xff0c;抱大佬队友的腿&#xff0c;他的 猜成语 应用获得了线…

【OS探秘】【虚拟化】【软件开发】VirtualBox 虚拟化软件卸载和重装

往期OS系列博文&#xff1a; 【OS探秘】【虚拟化】【软件开发】在Windows 11上安装mac OS虚拟机 【OS探秘】【虚拟化】【软件开发】在Windows 11上安装Kali Linux虚拟机 一、事出有因 近日&#xff0c;笔者的Oracle VM VirtualBox突然抽风了&#xff0c;虚拟机无法启动&…

(八)Gateway服务网关

Gateway服务网关 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。…

2_2.Linux中的远程登录服务

# 一.Openssh的功能 # 1.sshd服务的用途# #作用&#xff1a;可以实现通过网络在远程主机中开启安全shell的操作 Secure SHell >ssh ##客户端 Secure SHell daemon >sshd ##服务端 2.安装包# openssh-server 3.主配置文件# /etc/ssh/sshd_conf 4.…

Rhino.Inside.Revit根据直线创建剖面视图

Hello大家好&#xff01;我是九哥~ 今天简单分享一个小节点&#xff0c;根据Revit线构件的Location Line创建Revit剖面视图&#xff0c;主要用于快速创建线管、风道、墙等构件的详图视图。 效果如下&#xff1a; Rhino.Inside.Revit根据直线创建剖面视图 这次这个节点&#xff…

python中raise_for_status方法的作用

文章目录 说明示例1:基本使用示例2:多种异常说明 raise_for_status() 方法在 Python 的 requests 库中用于在发送 HTTP 请求后检查响应的状态码。如果响应的状态码表示请求未成功(即状态码不是 2xx),则该方法会抛出一个 HTTPError 异常。这允许你以一种更结构化的方式来处…