当前位置: 首页 > news >正文

支付系统设计五:对账系统设计01-总览

文章目录

  • 前言
  • 一、对账系统构建
  • 二、执行流程
  • 三、获取支付渠道数据
    • 1.接口形式
      • 1.1 后台配置
      • 1.2 脚本编写
        • 1.2.1 模板
        • 1.2.2 解析脚本
    • 2.FTP形式
      • 2.1 后台配置
      • 2.2 脚本编写
        • 2.2.1 模板
        • 2.2.2 解析脚本
  • 四、获取支付平台数据
  • 五、数据比对
    • 1. 比对模型
    • 2. 比对器
  • 总结


前言

从《支付系统设计一:支付系统产品化》系列中支付网关系统设计我们知道,在对接支付渠道的时候只需要产品经理进行后台渠道相关信息的配置,以及开发人员编写的模板、脚本就能够完成支付渠道的对接了,同样的,通过此模式也可以完成支付系统和支付渠道的对账。


一、对账系统构建

在这里插入图片描述

对账系统构建在网关系统的基础上,将网关应用单独部署几个节点,作为对账系统。

在这里插入图片描述
需要解决的问题有:

  1. 作为对账的网关节点不能向注册中心注册服务,对账节点只是用来完成对账功能。
    项目有两个主启动类包,demo-reconmain依赖demo-main,其中通过demo-reconmain主启动类启动需要配置:
  // 对账节点不注册服务System.setProperty("eureka.client.register-with-eureka", "false");
  1. 作为处理交易的网关节点不能消费对账任务,网关节点只是用来完成交易功能。
  // 对账节点消费对账任务以及刷新任务System.setProperty("paygw.rabbit.flag", buildRabbitFlag(RabbitFlagConsts.ALL, RabbitFlagConsts.RECON));

关于这块,见以前写的篇博客《多机房控制消息消费方实现》

即通过此设计,支付网关系统又可以作为对账系统,可以很巧妙的解决支付渠道侧对账数据获取的问题。

二、执行流程

在这里插入图片描述

三、获取支付渠道数据

不同的支付渠道获取对账文件的方式也各不相同,有的是推送FTP,有的是通过接口下载等,文件类型也有所不同,有的是TEXT,有的是CSV等,文件内容格式也是各不相同,所以我们同样的套路,不同处使用脚本实现,将渠道侧数据解析入临时表。

1.接口形式

1.1 后台配置

如兴业银行的对账文件通过接口下载,那么我们需要配置下载对账文件的通讯信息:

在这里插入图片描述

1.2 脚本编写

1.2.1 模板

cib_depute_recon_main.vm

##单付对账脚本
#set($umask  = "1000")
#set($version =  "1.0.2")##版本号
#set($mchtId=$data.merExtends.merId)##渠道商户号
#set($signType="RSA")##签名类型
#set($serialNo=$DateUtil.getCurrentDateTimeStr()) ##渠道请求流水号使用时间
#set($transTime=$DateUtil.getCurrentDateTimeStr())##交易时间
#set($checkType="1")##D+1对账文件
#set($checkDate= $DateUtil.format($data.reconStartDate,"yyyyMMdd"))##对账日期yyyyMMdd
#set($businessMap =
{"version":"$!version","mchtId":"$!mchtId","signType":"$!signType","serialNo":"$!serialNo","transTime":"$!transTime","checkType":"$!checkType","checkDate":"$!checkDate"
})
#set($certCodePrivate=$data.merExtends.certCodePrivate)##商户自己的私钥
#set($businessStr=$MapUtils.generateParamStr($businessMap))
#set($mac=$certService.sign($certCodePrivate,$businessStr))##获取签名
#set($signMap =
{"mac":"$!mac"
})
$umask$JSON.toJSONString($MapUtils.putAll($businessMap,$signMap))

cib_depute_recon_header.vm

#set($map =
{"Content-Type":"application/json;charset=UTF-8"
})
$map

1.2.2 解析脚本

/*** @author Kkk* @Describe: 兴业银行代付对账解析*/
class CIBDeputeReconParser extends AbstractReconDataFetchParser{def logger = LoggerFactory.getLogger(CIBDeputeReconParser.class)def resp_code_success = ["E0000"]public static final String ALGORITHM = "SHA1PRNG"/** 证书服务*/@AutowiredCertService certService/*** 查询结果处理*/@OverrideReconDataFetchResult parse4ReconData(PayGwContext context, Object message) {Map<String, Object> data = context.getMessageDescription().getDatas()ReconDataFetchResult fetchResult = new ReconDataFetchResult()try {//验证签名(必须)def flag = verifySign(context, message)if (!flag) {//签名通过返回解析后的数据,不包含签名类型和签名数据throw new Exception("[兴业银行-单笔代付对账请求] 返回参数,验签失败!")}Object result = JSON.parse(message)JSONObject jobj = (JSONObject) resultdef respCode= jobj.get("respCode");def respMsg= jobj.get("respMsg");if(!resp_code_success.contains(respCode)){fetchResult.setSuccess(false)fetchResult.setRemark("兴业银行对账失败["+respCode+"]["+respMsg+"]");return fetchResult}String fileContent= jobj.get("fileContent")String aesKey= jobj.get("aesKey")//使用私钥解密aesKeydef certCodePrivate = context.getMessageDescription().getData("merExtends").get("certCodePrivate")def aesK=certService.decryptBase64(certCodePrivate,aesKey)//用解密得到的aesKey解密fileContentbyte[] afterFileContent =this.AESDecode(fileContent,aesK)//将得到的fileContent解码byte[] bb1 = BASE64.decodeCib(new String(afterFileContent,"utf-8").toCharArray())//解压缩byte[] dedata = FileUtils.decompress(bb1)//流读取文件内容并入表保存InputStream is = new ByteArrayInputStream(dedata)BufferedReader bufferedReadertry{def tempStrLoggerUtil.info(logger, "兴业银行-单付对账-文件-开始解析")bufferedReader = new BufferedReader(new InputStreamReader(is,"UTF-8"))//解析第一行def str=bufferedReader.readLine()LoggerUtil.info(logger, "解析第一行str:{}",str)while ((tempStr = bufferedReader.readLine()) != null) {if (StringUtils.isNotBlank(tempStr)) {LoggerUtil.info(logger, "兴业对账文件解析内容:{}",tempStr)String[] transStr = tempStr.split("\\|")ReconTrans reconTrans = convert2ReconTrans(transStr)store(context, reconTrans)}}} catch (Exception e) {logger.error("兴业银行-单笔代付-对账异常", e)fetchResult.setSuccess(false)fetchResult.setRemark(e.getMessage())} finally {if (bufferedReader != null) {try {bufferedReader.close()} catch (IOException e1) {}}}fetchResult.setSuccess(true)data.put(PayGwConstant.PAYGW_TRANS_STATUS, TransStatusEnum.SUCCESS.getCode())fetchResult.setRemark("兴业银行-单笔代付对账成功。")return fetchResult}catch (PayGwException e){LoggerUtil.error(logger, "[兴业银行-单笔代付对账请求失败]",  e);fetchResult.setSuccess(false)fetchResult.setRemark(e.getErrorMsg())return fetchResult}catch (Exception e){LoggerUtil.error(logger,"[兴业银行-单笔代付对账请求失败]:{}--异常信息",e)fetchResult.setSuccess(false)fetchResult.setRemark("兴业银行-单笔代付对账失败,paygw解析数据异常")return fetchResult}}/*** 验签*/boolean verifySign(PayGwContext context, String resData) {def certCodePublic = context.getMessageDescription().getData("merExtends").get("certCodePublic")Map<String,String> resMap=MapUtils.covertToJSON(resData);String mac=resMap.get("mac");//获取签约值resMap.remove("mac");String oriSign=MapUtils.generateParamStr(resMap);boolean  vflag=  certService.checkSign(certCodePublic,mac,oriSign)logger.info("兴业银行-单笔代付对账请求,请求返回签名值({}),验签结果({})",mac,vflag)return vflag}/*** 构建对象*/private ReconTrans convert2ReconTrans(def transStr) {ReconTrans trans = new ReconTrans()trans.setInstReqNo(transStr[0])trans.setAcctNo(transStr[1])trans.setTransCode(TransactionEnum.DEPUTE.code)trans.setTransAmount(new BigDecimal(transStr[4]))String dataStr=transStr[5]if(StringUtils.isNotEmpty(dataStr)){Date d=DateUtil.parseDateTime(dataStr,"yyyyMMddHHmmss")trans.setTransDateTime(d)trans.setTransDate(d)}trans.setTransStatus(TransStatusEnum.SUCCESS.code())return trans}/*** 使用AES解密fileContent*/static byte[] AESDecode(String str,String num) throws Exception{KeyGenerator kg = KeyGenerator.getInstance("AES");SecureRandom sr = SecureRandom.getInstance(ALGORITHM);sr.setSeed(num.getBytes());kg.init(128, sr);SecretKey sk = kg.generateKey();byte[] raw = sk.getEncoded();SecretKey key = new SecretKeySpec(raw,"AES");Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, key);byte[] str_AES = cipher.doFinal(HexConvertorUtil.hex2Bytes(str));return str_AES;}
}

2.FTP形式

2.1 后台配置

如平安银行的对账文件通过FTP下载,那么我们需要配置下载对账文件的通讯信息:
在这里插入图片描述

在这里插入图片描述

2.2 脚本编写

2.2.1 模板

pingan_depute_recon_main.vm

#set($umask  = "1000")
#set($map =
{"fileName":$!data.fileNameCHK
})
$umask$!MapUtils.toJsonStr($map)

2.2.2 解析脚本

/*** @author Kkk* @Describe: 平安银行单付对账文件解析*/
class PANBANKDeputeReconFilesParser extends AbstractReconDataFetchParser {Logger logger = LoggerFactory.getLogger(PANBANKDeputeReconFilesParser.class)def success = true, remark = '平安银行单付对账入库成功。', panbank_success = "0000"@OverrideReconDataFetchResult parse4ReconData(PayGwContext context, Object message) {ReconDataFetchResult fetchResult = new ReconDataFetchResult()Map<String, Object> data = context.getMessageDescription().getDatas()//先设置结果的扩展字段JSONObject extend = JSON.parseObject(StringUtils.valueOf(data.get("extend1")))logger.info("平安银行单付对账解析文件,第四步解析前extend值为:{}",extend)if (StringUtils.isNotBlank(message) && message.length > 0) {//解析文件,并入库parseFile(context, message)extend.put("stepOrder", 6)fetchResult.setExtend1(extend.toString())fetchResult.setSuccess(success)fetchResult.setRemark(remark)logger.info("平安银行单付对账解析文件data:{}",data)data.put(PayGwConstant.PAYGW_TRANS_STATUS, TransStatusEnum.SUCCESS.getCode())logger.info("平安银行单付对账解析文件,并入库fetchResult.setRemark-4:{}--extend:{}",fetchResult.getRemark(),extend)return fetchResult}fetchResult.setSuccess(false)fetchResult.setRemark("平安银行单付对账失败,文件下载失败。")logger.info("平安银行单付对账fetchResult.setRemark-4:{}--extend:{}",fetchResult.getRemark(),extend)return fetchResult}/*** 解析对账文件*/void parseFile(PayGwContext context, byte[] absoluteFilePath) {def line = null//获取对账文件的文件流InputStream is = new ByteArrayInputStream(absoluteFilePath)try {//按行读取对账文件LineReader xline = new LineReader(new InputStreamReader(is, "GBK"))//获取渠道文件集合List<ReconTrans> list = new ArrayList<>()boolean firstLine = truewhile ((line = xline.readLine()) != null) {//按行转换成对账流水记录ReconTrans reconTrans = convert2ReconTrans(line, firstLine)//从此以后再无第一行firstLine = falseif (reconTrans == null) {continue}list.add(reconTrans)}//入库for (ReconTrans trans : list) {store(context, trans)}} catch (PayGwException e) {//更新success = falseremark = '平安银行单付对账失败,原因:' + e.getErrorMsg()LoggerUtil.error(logger, "文件读取异常:", e)} catch (Exception e) {//更新success = falseremark = '平安银行单付对账失败'LoggerUtil.error(logger, "文件读取异常:", e)}finally {IOUtils.closeQuietly(is)}}private ReconTrans convert2ReconTrans(def lineStr, boolean firstLine) {ReconTrans trans = new ReconTrans()def transStatusdef item = lineStr.split("\\|\\:\\:\\|", -1)def transDate = item[0]def instReqNo = item[3]def acctNo = item[5]def transAmt = new BigDecimal(item[6])//0000 成功 其余为失败def errorCode = item[10]//交易状态(平安银行对账文件全为成功数据)if (StringUtils.equals(errorCode, panbank_success)) {transStatus = TransStatusEnum.SUCCESS.code()} else {//其他状态不入库return null}trans.setTransStatus(transStatus)trans.setInstReqNo(instReqNo)trans.setTransCode(TransactionEnum.DEPUTE.code)//用户卡号trans.setAcctNo(acctNo)//交易金额trans.setTransAmount(transAmt)//交易日期trans.setTransDate(DateUtil.parseDate(transDate, "yyyyMMdd"))//交易时间,因对账文件中不存在交易时间,故将交易日期入库trans.setTransDateTime(DateUtil.parseDateTime(transDate, "yyyyMMdd"))return trans}
}

四、获取支付平台数据

直接使用SQL查询出对应支付渠道的对应的交易类型的交易数据。

五、数据比对

拉取两侧数据,构建数据比对模型放到内存中进行数据比对

1. 比对模型

/*** @author Kkk* @Describe: 对账-比对模型*/
public class CompareModel {/*** 唯一索引*/private String uniqueIndex;/*** 值*/private String value;/*** 业务流水ID*/private Long transId;
}

2. 比对器

/*** @author Kkk* @Describe: 对账-比较器定义*/
public interface IComparator {IComparator putOrigins(List<CompareModel> origins);IComparator putTargets(List<CompareModel> targets);CompareResult compare();
}

总结

后文详细展开具体实现。

相关文章:

支付系统设计五:对账系统设计01-总览

文章目录 前言一、对账系统构建二、执行流程三、获取支付渠道数据1.接口形式1.1 后台配置1.2 脚本编写1.2.1 模板1.2.2 解析脚本 2.FTP形式2.1 后台配置2.2 脚本编写2.2.1 模板2.2.2 解析脚本 四、获取支付平台数据五、数据比对1. 比对模型2. 比对器 总结 前言 从《支付系统设…...

阿里三面过了,却无理由挂了,HR反问一句话:为什么不考虑阿里?

进入互联网大厂一般都是“过五关斩六将”&#xff0c;难度堪比西天取经&#xff0c;但当你真正面对这些大厂的面试时&#xff0c;有时候又会被其中的神操作弄的很是蒙圈。 近日&#xff0c;某位测试员发帖称&#xff0c;自己去阿里面试&#xff0c;三面都过了&#xff0c;却被…...

办公智慧化风起云涌,华为MateBook X Pro 2023是最短距离

今年以来&#xff0c;我们几乎每个月&#xff0c;甚至每星期都可以看到大模型应用&#xff0c;在办公场景下推陈出新。 办公智慧化已成必然&#xff0c;大量智力工作正在被自动化。一个普遍共识是&#xff1a;AI能力范围之内的职业岌岌可危&#xff0c;AI 能力范围之外的职业欣…...

分布式项目 09.服务器之间的通信和三个工具类

项目的结构&#xff1a;1.通过Nginx首先把访问首页的请求发送到前端web服务器&#xff0c;2.web服务器会根据请求的url中的一些细节&#xff0c;来把相关的请求发送到相关的服务器中&#xff0c;3.相关的服务器会处理业务&#xff0c;并且返回结果到web服务器中&#xff0c;最后…...

C# 基本语法

C# 基本语法 C# 是一种面向对象的编程语言。在面向对象的程序设计方法中&#xff0c;程序由各种相互交互的对象组成。相同种类的对象通常具有相同的类型&#xff0c;或者说&#xff0c;是在相同的 class 中。 例如&#xff0c;以 Rectangle&#xff08;矩形&#xff09;对象为…...

做网络爬虫需要掌握哪些技术?

网络爬虫是指通过代码自动化地访问网页并收集数据的程序&#xff0c;要开发一个成功的爬虫&#xff0c;需要掌握以下技术&#xff1a; 1. HTTP 协议&#xff1a;了解 HTTP 请求和响应的基本内容&#xff0c;以及如何使用 HTTP 请求头和响应头来优化爬虫性能。 2. HTML/CSS/Ja…...

工作利器:三种简单方法将PPT转换成PDF

PDF是一种常用的文件格式&#xff0c;适合数据传输和阅读。在工作中&#xff0c;有时我们需要将PPT文件转换为PDF格式以方便使用。下面是几种将PPT转换为PDF的方法&#xff0c;其中方法二将修改为使用记灵在线工具进行转换。 方法一&#xff1a;直接将文件导出为PPT 一般来说…...

《设计模式》状态模式

《设计模式》状态模式 定义&#xff1a; 状态模式也称为状态机模式&#xff0c;允许对象在内部状态发生改变时改变它的行为&#xff0c;对象看起来好像修改了它的类。属于行为型模式。 状态模式的角色组成&#xff1a; State(抽象状态类)&#xff1a;定义一个接口用来封装与…...

2023年好用的设计图制作软件推荐

说到设计图制作软件&#xff0c;设计师当然最关注核心设计功能&#xff0c;包括预加载模板、图像数据库、界面和基本编辑功能。此外&#xff0c;还要考虑设计图制作软件是否可以协同工作。 1.即时设计 即时设计是一款「专业UI设计工具」&#xff0c;不受平台限制&#xff0c;…...

JavaNote_1.0.2_Spring

Spring框架定义 Spring Framework&#xff1a; Spring 最初的项目&#xff0c;包括六大模块&#xff1a;DAO、ORM、AOP、JEE、WEB、CORE。控制反转和面向切面编程是它的核心功能。 Spring Boot&#xff1a; 一套全新的基础框架&#xff0c;用来快速搭建Spring应用&#xff0c;…...

微服务多模块:Springboot+Security+Redis+Gateway+OpenFeign+Nacos+JWT (附源码)仅需一招,520彻底拿捏你

可能有些人会觉得这篇似曾相识&#xff0c;没错&#xff0c;这篇是由原文章进行二次开发的。 前阵子有些事情&#xff0c;但最近看到评论区说原文章最后实现的是单模块的验证&#xff0c;由于过去太久也懒得验证&#xff0c;所以重新写了一个完整的可以跑得动的一个。 OK&#…...

HNU数据结构与算法分析-作业4-图结构

1. (简答题) 【应用题】11.3 &#xff08;a&#xff09;画出所示图的相邻矩阵表示 &#xff08;b&#xff09;画出所示图的邻接表表示 &#xff08;c&#xff09;如果每一个指针需要4字节&#xff0c;每一项顶点的标号占用2字节&#xff0c;每一条边的权需要2字节&#xff0…...

AMPL IDE语法整理

文章目录 1、参数\集合和变量定义2、目标和约束的书写3、求解命令4、AMPL调用不同求解器的Options目录未完待续~ \qquad 最近再搞一些模型&#xff0c;需要用到AMPL中不同的求解器进行验证求解&#xff0c;故建立本博客&#xff0c;用于随时整理AMPL的相关语法和命令&#xff0…...

从0-1搭建支持gb28181协议搭建流媒体平台

系列文章目录 文章目录 系列文章目录前言一、搭建流程二、运行播放直播流效果: ![在这里插入图片描述](https://img-blog.csdnimg.cn/62b558f0213044f292be69da8cc29730.png)总结前言 一个基于C++开发的国标GB28181流媒体信令服务器。 采用SipServer+ZLMediaKit。可以搭建一个…...

数据结构与算法之栈: Leetcode 682. 棒球比赛 (Typescript版)

棒球比赛 https://leetcode.cn/problems/baseball-game/ 描述 你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成&#xff0c;过去几回合的得分可能会影响以后几回合的得分。 比赛开始时&#xff0c;记录是空白的。你会得到一个记录操作的字符串列表 ops&a…...

E-office Server_v9.0 漏洞分析

漏洞简介 泛微e-office是一款标准化的协同OA办公软件&#xff0c;实行通用化产品设计&#xff0c;充分贴合企业管理需求&#xff0c;本着简洁易用、高效智能的原则&#xff0c;为企业快速打造移动化、无纸化、数字化的办公平台。由于泛微 E-Office 未能正确处理上传模块中输入…...

MySQL数据库,JDBC连接数据库操作流程详细介绍

前言&#xff1a; 在学完 MySQL 和 Java 后&#xff0c;我们通常会尝试使用 Java编译器 连接 MySQL数据库&#xff0c;从而达到使用编译器来操作数据库的效果。连接的这个过程会用 JDBC 相关知识&#xff0c;因此我把 JDBC 包的下载及导入流程&#xff0c;以及 JDBC 的使用流程…...

libevent高并发网络编程 - 06_基于libevent的C++线程池实现

文章目录 1 功能简介线程池的初始化线程池执行流程 2 线程池类的设计线程类XThreadXThread.hXThread.cpp 线程池类XThreadPoolXThreadPool.hXThreadPool.cpp 任务基类taskXTask.h 3 自定义任务的例子自定义任务类ServerCMDServerCMD.hServerCMD.cpp 测试程序运行效果 1 功能简介…...

【Java EE 初阶】线程安全及死锁解决方案

目录 1.多线程下线程不安全的问题 1.使用多个线程对Array List集合进行添加操作并打印&#xff0c;查看结果 2.如何在多线程环境下使用线程安全的集合类 CopyOnWriteArrayList 3.多线程环境下使用队列 4.多线程环境下使用哈希表 1.HashTable线程安全 2.Concurrent Hash M…...

C语言函数大全-- _w 开头的函数(5)

C语言函数大全 本篇介绍C语言函数大全-- _w 开头的函数 1. _wspawnl 1.1 函数说明 函数声明函数功能int _wspawnl(int mode, const wchar_t* cmdname, const wchar_t* arglist, ...);启动一个新的进程并运行指定的可执行文件 参数&#xff1a; mode &#xff1a; 启动命令的…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...