第4章 客户端-Java客户端Jedis

1.获取Jedis
maven配置加入项目中

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.8.2</version>
</dependency>

2.Jedis的基本使用
Jedis的使用方法非常简单,只要下面三行代码就可以实现get功能:

import redis.clients.jedis.Jedis;public class JedisTest {public static void main(String[] args) {Jedis jedis=null;try {//1. 生成一个Jedis对象,这个对象负责和指定Redis实例进行通信jedis = new Jedis("59.110.35.177", 6379);jedis.auth("password");// 1.string// 输出结果:OKjedis.set("hello", "world");// 输出结果:worldjedis.get("hello");// 输出结果:1jedis.incr("counter");// 2.hashjedis.hset("myhash", "f1", "v1");jedis.hset("myhash", "f2", "v2");// 输出结果:{f1=v1, f2=v2}jedis.hgetAll("myhash");// 3.listjedis.rpush("mylist", "1");jedis.rpush("mylist", "2");jedis.rpush("mylist", "3");// 输出结果:[1, 2, 3]jedis.lrange("mylist", 0, -1);// 4.setjedis.sadd("myset", "a");jedis.sadd("myset", "b");jedis.sadd("myset", "a");// 输出结果:[b, a]jedis.smembers("myset");// 5.zsetjedis.zadd("myzset", 99, "tom");jedis.zadd("myzset", 66, "peter");jedis.zadd("myzset", 33, "james");// 输出结果:[[["james"],33.0], [["peter"],66.0], [["tom"],99.0]]jedis.zrangeWithScores("myzset", 0, -1);}catch (Exception e){e.printStackTrace();}finally {if (jedis != null) {jedis.close();}}}
}

参数除了可以是字符串,Jedis还提供了字节数组的参数,例如:

public String set(final String key, String value)
public String set(final byte[] key, final byte[] value)
public byte[] get(final byte[] key)
public String get(final String key)

有了这些API的支持,就可以将Java对象序列化为二进制,当应用需要获取Java对象时,使用get(final byte[]key)函数将字节数组取出,然后反序列化为Java对象即可。和很多NoSQL数据库(例如Memcache、Ehcache)的客户端不同,Jedis本身没有提供序列化的工具,也就是说开发者需要自己引入序列化的工具。序列化的工具有很多,例如XML、Json、谷歌的Protobuf、Facebook的Thrift等等,对于序列化工具的选择开发者可以根据自身需求决定,下面以protostuff(Protobuf的Java客户端)为例子进行说明。
1)protostuff的Maven依赖:

<protostuff.version>1.0.11</protostuff.version>
<dependency><groupId>com.dyuproject.protostuff</groupId><artifactId>protostuff-runtime</artifactId><version>${protostuff.version}</version>
</dependency>
<dependency><groupId>com.dyuproject.protostuff</groupId><artifactId>protostuff-core</artifactId><version>${protostuff.version}</version>
</dependency>

2)定义实体类:

// 俱乐部
public class Club implements Serializable {
private int id; // id
private String name; // 名称
private String info; // 描述
private Date createDate; // 创建日期
private int rank; // 排名
// 相应的getter setter不占用篇幅
}

3)序列化工具类ProtostuffSerializer提供了序列化和反序列化方法:

package com.sohu.tv.serializer;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import java.util.concurrent.ConcurrentHashMap;
//序列化工具
public class ProtostuffSerializer {private Schema<Club> schema = RuntimeSchema.createFrom(Club.class);public byte[] serialize(final Club club) {final LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);try {return serializeInternal(club, schema, buffer);} catch (final Exception e) {throw new IllegalStateException(e.getMessage(), e);} finally {buffer.clear();}}public Club deserialize(final byte[] bytes) {try {Club club = deserializeInternal(bytes, schema.newMessage(), schema);if (club != null ) {return club;}} catch (final Exception e) {throw new IllegalStateException(e.getMessage(), e);}return null;}private <T> byte[] serializeInternal(final T source, final Schema<T>schema, final LinkedBuffer buffer) {return ProtostuffIOUtil.toByteArray(source, schema, buffer);}private <T> T deserializeInternal(final byte[] bytes, final T result, finalSchema<T> schema) {ProtostuffIOUtil.mergeFrom(bytes, result, schema);return result;}
}

4)测试。
生成序列化工具类:

ProtostuffSerializer protostuffSerializer = new ProtostuffSerializer();

生成Jedis对象:

Jedis jedis = new Jedis("127.0.0.1", 6379);

序列化:

String key = "club:1";
// 定义实体对象
Club club = new Club(1, "AC", "米兰", new Date(), 1);
// 序列化
byte[] clubBtyes = protostuffSerializer.serialize(club);
jedis.set(key.getBytes(), clubBtyes);

反序列化:

byte[] resultBtyes = jedis.get(key.getBytes());
// 反序列化[id=1, clubName=AC, clubInfo=米兰, createDate=Tue Sep 15 09:53:18 CST 2015, rank=1]
Club resultClub = protostuffSerializer.deserialize(resultBtyes);

总体代码为:

import redis.clients.jedis.Jedis;
import java.util.Date;
public class redisSerializerTest {public static void main(String[] args) {ProtostuffSerializer protostuffSerializer = new ProtostuffSerializer();Jedis jedis=null;try {//1. 生成一个Jedis对象,这个对象负责和指定Redis实例进行通信jedis = new Jedis("59.110.35.177", 6379);jedis.auth("1.tiantian");String key = "club:1";// 定义实体对象Club club = new Club(1, "AC", "米兰", new Date(), 1);// 序列化byte[] clubBtyes = protostuffSerializer.serialize(club);jedis.set(key.getBytes(), clubBtyes);// 反序列化[id=1, clubName=AC, clubInfo=米兰, createDate=Tue Sep 15 09:53:18 CST 2015, rank=1]byte[] resultBtyes = jedis.get(key.getBytes());Club resultClub = protostuffSerializer.deserialize(resultBtyes);}catch (Exception e){e.printStackTrace();}finally {if (jedis != null) {jedis.close();}}}
}

3.Jedis连接池使用
以上是Jedis的直连方式,所谓直连是指Jedis每次都会新建TCP连接,使用后再断开连接,对于频繁访问Redis的场景显然不是高效的使用方式,如下图所示
在这里插入图片描述
因此生产环境中一般使用连接池的方式对Jedis连接进行管理,如下图所示,所有Jedis对象预先放在池子中(JedisPool),每次要连接Redis,只需要在池子中借,用完了在归还给池子。
在这里插入图片描述
客户端连接Redis使用的是TCP协议,直连的方式每次需要建立TCP连接,而连接池的方式是可以预先初始化好Jedis连接,所以每次只需要从Jedis连接池借用即可,而借用和归还操作是在本地进行的,只有少量的并发同步开销,远远小于新建TCP连接的开销。另外直连的方式无法限制Jedis对象的个数,在极端情况下可能会造成连接泄露,而连接池的形式可以有效的保护和控制资源的使用。但是直连的方式也并不是一无是处,表4-1给出两种方式各自的优劣势。
在这里插入图片描述
Jedis提供了JedisPool这个类作为对Jedis的连接池,同时使用了Apache的通用对象池工具common-pool作为资源的管理工具,下面是使用JedisPool操作Redis的代码示例:
1)Jedis连接池(通常JedisPool是单例的):

// common-pool连接池配置,这里使用默认配置,后面小节会介绍具体配置说明
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
// 初始化Jedis连接池
JedisPool jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379);

2)获取Jedis对象不再是直接生成一个Jedis对象进行直连,而是从连接池直接获取,代码如下:

Jedis jedis = null;
try {// 1. 从连接池获取jedis对象jedis = jedisPool.getResource();// 2. 执行操作jedis.get("hello");
} catch (Exception e) {logger.error(e.getMessage(),e);
} finally {if (jedis != null) {// 如果使用JedisPool,close操作不是关闭连接,代表归还连接池jedis.close();}
}

这里可以看到在finally中依然是jedis.close()操作,为什么会把连接关闭呢,这不和连接池的原则违背了吗?但实际上Jedis的close()实现方式如下:

public void close() {// 使用Jedis连接池if (dataSource != null) {if (client.isBroken()) {this.dataSource.returnBrokenResource(this);} else {this.dataSource.returnResource(this);}// 直连} else {client.close();}
}

参数说明:

  • dataSource!=null代表使用的是连接池,所以jedis.close()代表归还连接给连接池,而且Jedis会判断当前连接是否已经断开。
  • dataSource=null代表直连,jedis.close()代表关闭连接。
    前面GenericObjectPoolConfig使用的是默认配置,实际它提供有很多参数,例如池子中最大连接数、最大空闲连接数、最小空闲连接数、连接活性检测,等等,例如下面代码:
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
// 设置最大连接数为默认值的5倍
poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 5);
// 设置最大空闲连接数为默认值的3倍
poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 3);
// 设置最小空闲连接数为默认值的2倍
poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MIN_IDLE * 2);
// 设置开启jmx功能
poolConfig.setJmxEnabled(true);
// 设置连接池没有连接后客户端的最大等待时间(单位为毫秒)
poolConfig.setMaxWaitMillis(3000);

上面几个是GenericObjectPoolConfig几个比较常用的属性,表4-2给出了Generic-ObjectPoolConfig其他属性及其含义解释。
在这里插入图片描述
总体代码为:

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;public class jedisPoolTest {public static void main(String[] args) {GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();// 设置最大连接数为默认值的5倍poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 5);// 设置最大空闲连接数为默认值的3倍poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 3);// 设置最小空闲连接数为默认值的2倍poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MIN_IDLE * 2);// 设置开启jmx功能poolConfig.setJmxEnabled(true);// 设置连接池没有连接后客户端的最大等待时间(单位为毫秒)poolConfig.setMaxWaitMillis(3000);// 初始化Jedis连接池JedisPool jedisPool = new JedisPool(poolConfig, "59.110.35.177", 6379,200,"1.tiantian");Jedis jedis = null;try {// 1. 从连接池获取jedis对象jedis = jedisPool.getResource();// 2. 执行操作String result = jedis.get("hello");System.out.println(result);} catch (Exception e) {e.printStackTrace();} finally {if (jedis != null) {// 如果使用JedisPool,close操作不是关闭连接,代表归还连接池jedis.close();}}}
}

4.Jedis中Pipeline使用
Jedis支持Pipeline特性,我们知道Redis提供了mget、mset方法,但是并没有提供mdel方法,如果想实现这个功能,可以借助Pipeline来模拟批量删除,虽然不会像mget和mset那样是一个原子命令,但是在绝大数场景下可以使用。下面代码是mdel删除的实现过程。
这里为了节省篇幅,没有写try catch finally,没有关闭jedis。

public void mdel(List<String> keys) {Jedis jedis = new Jedis("127.0.0.1");// 1)生成pipeline对象Pipeline pipeline = jedis.pipelined();// 2)pipeline执行命令,注意此时命令并未真正执行for (String key : keys) {pipeline.del(key);}// 3)执行命令pipeline.sync();
}

说明如下:

  • 利用jedis对象生成一个pipeline对象,直接可以调用jedis.pipelined()。
  • 将del命令封装到pipeline中,可以调用pipeline.del(String key),这个方法和jedis.del(String key)的写法是完全一致的,只不过此时不会真正的执行命令。
  • 使用pipeline.sync()完成此次pipeline对象的调用。
    除了pipeline.sync(),还可以使用pipeline.syncAndReturnAll()将pipeline的命令进行返回,例如下面代码将set和incr做了一次pipeline操作,并顺序打印了两个命令的结果:
Jedis jedis = new Jedis("127.0.0.1");
Pipeline pipeline = jedis.pipelined();
pipeline.set("hello", "world");
pipeline.incr("counter");
List<Object> resultList = pipeline.syncAndReturnAll();
for (Object object : resultList) {System.out.println(object);
}

输出结果为:

OK
1

总体代码为:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import java.util.List;
import java.util.Set;
public class JedisPipelineTest {public static void main(String[] args) {Jedis jedis=null;try {jedis = new Jedis("59.110.35.177", 6379);jedis.auth("1.tiantian");Set<String> keys = jedis.keys("*");// 1)生成pipeline对象Pipeline pipeline = jedis.pipelined();// 2)pipeline执行命令,注意此时命令并未真正执行for (String key : keys) {pipeline.del(key);}// 3)执行命令pipeline.sync();pipeline.set("hello", "world");pipeline.incr("counter");List<Object> resultList = pipeline.syncAndReturnAll();for (Object object : resultList) {System.out.println(object);}} catch (Exception e){e.printStackTrace();}finally {if (jedis != null) {
// 如果使用JedisPool,close操作不是关闭连接,代表归还连接池jedis.close();}        }}
}

5.Jedis的Lua脚本使用
Jedis中执行Lua脚本和redis-cli十分类似,Jedis提供了三个重要的函数实现Lua脚本的执行:

Object eval(String script, int keyCount, String... params)
Object evalsha(String sha1, int keyCount, String... params)
String scriptLoad(String script)

eval函数有三个参数,分别是:

  • script:Lua脚本内容。
  • keyCount:键的个数。
  • params:相关参数KEYS和ARGV。
    以一个最简单的Lua脚本为例子进行说明:
return redis.call('get',KEYS[1])

在redis-cli中执行上面的Lua脚本,方法如下:

127.0.0.1:6379> eval "return redis.call('get',KEYS[1])" 1 hello
"world"

在Jedis中执行,方法如下:

String key = "hello";
String script = "return redis.call('get',KEYS[1])";
Object result = jedis.eval(script, 1, key);
// 打印结果为world
System.out.println(result)

scriptLoad和evalsha函数要一起使用,首先使用scriptLoad将脚本加载到Redis中,代码如下:

String scriptSha = jedis.scriptLoad(script);

evalsha函数用来执行脚本的SHA1校验和,它需要三个参数:

  • scriptSha:脚本的SHA1。
  • keyCount:键的个数。
  • params:相关参数KEYS和ARGV。
    执行效果如下:
Stirng key = "hello";
Object result = jedis.evalsha(scriptSha, 1, key);
// 打印结果为world
System.out.println(result);

总体来说,Jedis的使用还是比较简单的,重点注意以下几点即可:
1)Jedis操作放在try catch finally里更加合理。
2)区分直连和连接池两种实现方式优缺点。
3)jedis.close()方法的两种实现方式。
4)Jedis依赖了common-pool,有关common-pool的参数需要根据不同的使用场景,各不相同,需要具体问题具体分析。
5)如果key和value涉及了字节数组,需要自己选择适合的序列化方法。
总体代码为:

import redis.clients.jedis.Jedis;
public class JedisLuaTest {public static void main(String[] args) {Jedis jedis=null;try {//1. 生成一个Jedis对象,这个对象负责和指定Redis实例进行通信jedis = new Jedis("59.110.35.177", 6379);jedis.auth("1.tiantian");String key = "hello";String script = "return redis.call('get',KEYS[1])";Object result = jedis.eval(script, 1, key);// 打印结果为worldSystem.out.println(result);String scriptSha = jedis.scriptLoad(script);System.out.println(scriptSha);Object result1 = jedis.evalsha(scriptSha, 1, key);// 打印结果为worldSystem.out.println(result1);}catch (Exception e){e.printStackTrace();}finally {if (jedis != null) {jedis.close();}}}
}

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

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

相关文章

首次30米空间分辨率生成中国年度耕地栅格数据1986-2021

中国1986-2021年30米分辨率年度耕地数据集 数据介绍 精确、详细且及时的耕地范围信息对于粮食安全保障和环境可持续性至关重要。然而&#xff0c;由于农业景观的复杂性和足够训练样本的缺乏&#xff0c;在大范围下进行高时空分辨率的耕地动态监测仍然具有挑战性&#xff0c;尤其…

洞察用户需求,Xinstall数据统计App让你的App运营如虎添翼

在互联网时代&#xff0c;App推广和运营面临着前所未有的挑战。流量红利逐渐衰退&#xff0c;用户获取成本不断攀升&#xff0c;如何确保在多变的互联网环境下&#xff0c;迅速搭建起能时刻满足用户需求的运营体系&#xff0c;成为众多企业急待解决的问题。今天&#xff0c;我们…

docker部署FastDFS整合Springboot

文章目录 1、FastDFS是什么&#xff1f;2、搭建docker环境3、部署fastdfs4、整合springboot5、接口测试参考文章 1、FastDFS是什么&#xff1f; FastDFS是一个开源的轻量级分布式文件系统&#xff0c;它对文件进行管理&#xff0c;功能包括&#xff1a;文件存储、文件同步、文…

聚星文社官网

推文工具可以帮助你将小说内容简洁明了地转化为推文形式&#xff0c;以便更好地在社交媒体上进行宣传和推广。以下是一些建议的小说推文工具&#xff1a; 聚星文社 字数统计工具&#xff1a;使用字数统计工具&#xff0c;如Microsoft Word或在线字数统计器&#xff0c;来确保你…

[JS]对象

介绍 对象是一种无序的数据集合, 可以详细的描述某个事物 事物的特征在对象中用属性来表示, 事物的行为在对象中用方法来表示 使用 创建对象 let 对象名 {属性名&#xff1a;值&#xff0c;方法名&#xff1a;函数&#xff0c; } let 对象名 new Object(); 对象名.属性…

工业网关的功能与作用解析-天拓四方

在工业4.0和智能制造的时代背景下&#xff0c;工业网关作为连接现场设备与云端平台的桥梁&#xff0c;正发挥着日益重要的作用。它不仅为工业设备的远程监控和管理提供了可能&#xff0c;还为企业实现数字化转型和智能化升级提供了有力支持。本文将对工业网关的功能与作用进行解…

Python:基于TSFEL库对时间序列进行特征分析

1. TSFEL 时间序列作为主要TSFEL提取方法的输入传递&#xff0c;要么作为先前加载在内存中的数组传递&#xff0c;要么存储在数据集中的文件中。 由于TSFEL可以处理多维时间序列&#xff0c;因此随后应用了一套预处理方法&#xff0c;以确保信号质量足够和时间序列同步&#xf…

AI音乐大模型:深度剖析创意与产业的双重变革

随着AI技术的飞速发展&#xff0c;音乐大模型在最近一个月内纷纷上线&#xff0c;这一变革性技术不仅颠覆了传统的音乐创作方式&#xff0c;更是对整个音乐产业及创意产业带来了深远的影响。本文将从多个维度出发&#xff0c;深度剖析AI音乐大模型对创意与产业的双重变革。 一、…

ONLYOFFICE 8.1:引领桌面办公新潮流,功能升级全面提升

目录 一、ONLYOFFICE是什么&#xff1f; 二、功能完善的PDF编辑器 三、幻灯片版式升级 四、改进从右至左显示 五、新的本地化选项 六、多媒体功能增强 七、应用价值探讨 一、ONLYOFFICE是什么&#xff1f; ONLYOFFICE 是一款功能强大的办公套件&#xff0c;旨在提供全面…

acme.sh泛证书申请

说明: 1、想每个项目都接入域名+端口访问,所以通过acme.sh申请泛域名证书 2、阿里云域名解析,并且指定公网ip地址对应的公共Nginx服务 3、acme.sh证书只有3个月,所以要用shell自动续签证书 4、阿里云域名已解析,所以二级域名、三级域名能正常解析,如下图所示, 一、阿里云…

charles破解

一、Charles官网下载安装包二、安装charles三、charles破解 一、Charles官网下载安装包 根据自己电脑系统 官网下载即可。 链接: https://www.charlesproxy.com/download/latest-release/ 二、安装charles 点击下载的安装包&#xff0c;然后进行安装。 三、charles破解 打…

服务器如何实现SSH免密码登录?

目录 一、服务器和电脑的区别二、什么是SSH三、什么是免密码登录四、服务器如何实现SSH免密码登录 一、服务器和电脑的区别 服务器和电脑是两种不同类型的计算机系统&#xff0c;它们在设计、功能和用途上存在明显的区别。首先&#xff0c;从硬件配置上看&#xff0c;服务器通…

MySQL学习(3):SQL语句之DDL

1.SQL通用语法与分类 &#xff08;1&#xff09;通用语法 &#xff08;2&#xff09;分类 2.DDL 2.1数据库操作 show DATABASES; #查询所有数据库select DATABASE(); #查询当前数据库create DATABASE 数据库名称 [default charest 字符集] [collate 排列规则]; #default cha…

时序分析(二):input delay分析

一、IO接口分析基本模型 数据按照同步方式可分为系统同步和源同步方式两种。所谓系统同步指发送端和接收端共用一个时钟源&#xff1b;源同步指发送端提供数据同步时钟&#xff0c;接收端根据该时钟进行数据接收。现在多数通信中使用源同步方式&#xff0c;例如以太网、ADC等。…

洗地机怎么选择最好?四大洗地机精选放心入手

在当今生活节奏飞快的社会中&#xff0c;人们越来越渴望拥有一款高性能、实用方便的家用洗地机&#xff0c;能够帮助我们节省大量的清洁时间。因为洗地机它是吸尘器的升级版&#xff0c;清洁力比扫地机器人更强&#xff0c;洗地机通过高速旋转的风机&#xff0c;产生超大吸力&a…

Unity之HTC VIVE Cosmos环境安装(适合新手小白)(一)

提示&#xff1a;能力有限&#xff0c;错误之处&#xff0c;还望指出&#xff0c;不胜感激&#xff01; 文章目录 前言一、unity版本电脑配置相关关于unity版本下载建议&#xff1a;0.先下载unity Hub1.不要用过于旧的版本2.不要下载最新版本或者其他非长期支持版本 二、官网下…

生命在于学习——Python人工智能原理(4.4)

三、Python的数据类型 3.2 Python的组合数据类型 特点&#xff1a;表示多个元素的组合&#xff0c;可以包含不同类型的元素&#xff0c;甚至是其他的组合数据类型。 在内存中通常需要额外的空间来存储元素间的关系。 组合数据类型能够将多个同类型或不同类型的数据组织起来&a…

出版发行企业从传统分销到网格化营销的变革之路(AMT企源)

引言&#xff1a; 本文为该系列文章的第一篇&#xff0c;旨在介绍当前出版发行行业&#xff0c;尤其是各省级新华书店集团围绕“综合教育服务”和“大文化消费服务”两个领域的业务布局下&#xff0c;如何实现营销模式创新、营销组织创新&#xff0c;以推动新华书店集团从传统…

浮动IP绑定主机步骤

文章目录 1&#xff0c;查看本机的原有IP2&#xff0c;绑定浮动IP3&#xff0c;验证绑定情况4&#xff0c;解绑浮动IP 1&#xff0c;查看本机的原有IP ifconfig得到本机的ip是192.168.10.128 2&#xff0c;绑定浮动IP ifconfig ens33:1 192.168.10.10 netmask 255.255.255.0…

墨迹天气与AI数据湖的集成案例(集易连平台)

客户介绍 客户方为国内某皮具生产企业&#xff0c;年设计版型数千款&#xff0c;全国销售门店数一千多家&#xff0c;年销售额达20亿。该AI项目目的是将订单数据、用户行为分析、天气数据、门店位置、客流量等等一系列数据作为AI大模型的输入&#xff0c;经过大模型的训练和…