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

news2024/11/17 19:37:59

图片

前言

大概故事是这样的,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
---------------------
 48
 48.1000000000000014
 48.8999999999999986
(3 rows)

PG12及后续版本的结果:

mydb=# select * from t1;
  a
------
 48
 48.1
 48.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.coloradmin.cn/o/1567777.html

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

相关文章

渐进式图片解决前端在页面中使用大图,图片体积过大导致页面出现白屏现象

1、演示 可以看到&#xff0c;图片还在拼命加载的时候&#xff0c; 页面上就已经有内容了 2、什么渐进式图片 图片一开始是模糊的&#xff0c;然后逐渐的开始变的清晰。如果页面上有一些大图&#xff0c;如果直接扔给浏览器的话那么图片的传输时间就会比较长&#xff0c;用户就…

Java对象Object对象头-MarkWord分析-hashCode

代码主要通过打印对象的内存布局来观察对象头在不同状态下的变化&#xff0c;进而分析对象头在不同情况下的内存布局情况。 System.out.println(ClassLayout.parseInstance(o).toPrintable());&#xff1a;这一行代码通过使用开源库 openjdk.jol 的 ClassLayout 类来解析对象 o…

算法思想堪比哲学,你知多少否?

对算法思想 - 分治算法的理解 分治算法是一种将复杂问题划分为规模较小的子问题&#xff0c;并递归地解决这些子问题&#xff0c;最后将它们的解合并为原问题的解的算法思想。 它具有以下几个关键步骤&#xff1a;分解、解决和合并。 通过将大问题分解为小问题&#xff0c;每个…

数据结构—堆

什么是堆 堆是一种特殊的树形结构&#xff0c;其中每个节点都有一个值。堆可以分为两种类型&#xff1a;最大堆和最小堆。在最大堆中&#xff0c;每个节点的值都大于等于其子节点的值&#xff1b;而在最小堆中&#xff0c;每个节点的值都小于等于其子节点的值。这种特性使得堆…

Linux实验过程

答案截图获取&#xff0c;代写&#xff1a; https://laowangall.oss-cn-beijing.aliyuncs.com/studentall.pdf 基本任务&#xff1a; 1.Linux操作系统安装 2.vi文本编辑 3. Linux用户及文件管理命令 4. Linux权限管理命令 5. Linux网络服务 提高任务&#xff1a; 1、Li…

vue3+elementPlus:实现数字滚动效果(用于大屏可视化)

自行封装注册一个公共组件 案例一&#xff1a; //成功案例&#xff1a; //NumberScroll.vue /* 数字滚动特效组件 NumberScroll */<template><span class"number-scroll-grow"><spanref"numberScroll":data-time"time"class&qu…

intellij idea 使用git的 cherry pick 摘取其他分支的comment

cherry pick 摘取其他分支的comment 如果想把 feature_v1.0 分支的comment 摘到 feature_v1.0_new 分支上&#xff0c; 先切换到 feature_v1.0_new分支&#xff0c;这一步不能少了。然后点击 下面菜单栏的 git&#xff0c;点击Local Changes旁边的 Log&#xff0c;这时能看到…

【Java】打包:JAR、EAR、WAR

打包&#xff1a;JAR、EAR、WAR war 是一个 Web 模块&#xff0c;其中需要包括 WEB-INF&#xff0c;是可以直接运行的 WEB 模块。而 jar 一般只是包括一些 class 文件&#xff0c;在声明了 main_class 之后是可以用 java 命令运行的。 它们都是压缩的包&#xff0c;拿 Tomcat …

SpringBoot登录校验(四)过滤器Filter

JWT令牌生成后&#xff0c;客户端发的请求头中会带有JWT令牌&#xff0c;服务端需要校验每个请求的令牌&#xff0c;如果在每个controller方法中添加校验模块&#xff0c;则十分复杂且冗余&#xff0c;所以引入统一拦截模块&#xff0c;将请求拦截下来并做校验&#xff0c;这块…

配置Pod使用PersistentVolume作为存储,PV类型为 hostPath

准备开始 在节点主机上创建一个 /mnt/data 目录&#xff1a; mkdir -p /mnt/data创建一个index.html文件 echo Hello from Kubernetes storage > /mnt/data/index.html创建PV 创建一个 hostPath 类型的 PersistentVolume。 Kubernetes 支持用于在单节点集群上开发和测试的…

第19次修改了可删除可持久保存的前端html备忘录:换了一个特别的倒计时时钟

第19次修改了可删除可持久保存的前端html备忘录:换了一个特别的倒计时时钟 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><met…

数据结构记录

之前记录的数据结构笔记&#xff0c;不过图片显示不了了 数据结构与算法(C版) 1、绪论 1.1、数据结构的研究内容 一般应用步骤&#xff1a;分析问题&#xff0c;提取操作对象&#xff0c;分析操作对象之间的关系&#xff0c;建立数学模型。 1.2、基本概念和术语 数据&…

glm2大语言模型服务环境搭建

一、模型介绍 ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本&#xff0c;在保留了初代模型对话流畅、部署门槛较低等众多优秀特性的基础之上&#xff0c;ChatGLM2-6B 引入了如下新特性&#xff1a; 更强大的性能&#xff1a;基于 ChatGLM 初代模型的开发经验&…

大数据实验三-HBase编程实践

目录 一&#xff0e;实验内容 二&#xff0e;实验目的 三&#xff0e;实验过程截图及说明 1、安装HBase 2、配置伪分布式模式&#xff1a; 3、使用hbase的shell命令来操作表&#xff1a; 4、使用hbase提供的javaAPI来编程实现类似操作&#xff1a; 5、实验总结及心得体会…

『VUE』10. 事件修饰符(详细图文注释)

目录 什么是事件修饰符?vuejs 不使用修饰符 原生js实现禁用事件对象的默认事件使用事件修饰符 .prevent使用事件修饰符 .stop使用事件修饰符 .self 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 什么是事件修饰符? vue 在 Vu…

『51单片机』蜂鸣器

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…

【研发日记】白话解读UDS协议(一)——19 04读取快照服务

文章目录 前言 19服务 04子服务 19 04协议 快照存储设计 快照发送设计 功能验证 分析和应用 总结 前言 近期在一个嵌入式软件开发项目中&#xff0c;要按照UDS标准开发相关功能&#xff0c;期间在翻阅UDS标准时&#xff0c;周围同事都说很多地方晦涩难懂。所以利用晚上…

ObjectiveC-08-OOP面向对象程序设计-类的分离与组合

本节用一简短的文章来说下是ObjectiveC中的类。类其实是OOP中的一个概念&#xff0c;概念上简单来讲类是它是一组关系密切属性的集合&#xff0c;所谓的关系就是对现实事物的抽象。 上面提到的关系包括很多种&#xff0c;比如has a&#xff0c; is a&#xff0c;has some等&…

基于Java,SSM,html,Vue在线视频播放管理系统网站设计

摘要 基于Java, SSM, HTML, Vue的在线视频播放管理系统网站设计是一个利用Spring框架、SpringMVC、MyBatis&#xff08;SSM&#xff09;和前端技术HTML与Vue.js实现的多功能Web应用。这个系统旨在为用户提供一个便捷、高效的平台来上传、管理和观看视频内容&#xff0c;同时兼…

Spring与SpringBoot的区别

Spring是一个开源的Java应用程序框架&#xff0c;旨在简化企业级Java应用程序的开发。它提供了一个轻量级的容器&#xff0c;用于管理应用程序中的各个组件&#xff08;如依赖注入、AOP等&#xff09;&#xff0c;并提供了丰富的功能和模块&#xff0c;用于处理数据库访问、事务…