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

ISDP010_基于DDD架构实现收银用例主成功场景

信息系统开发实践 | 系列文章传送门
ISDP001_课程概述
ISDP002_Maven上_创建Maven项目
ISDP003_Maven下_Maven项目依赖配置
ISDP004_创建SpringBoot3项目
ISDP005_Spring组件与自动装配
ISDP006_逻辑架构设计
ISDP007_Springboot日志配置与单元测试
ISDP008_SpringBoot Controller接口文档与测试
ISDP009_基于DDD架构设计ISDP的处理销售用例
ISDP010_基于DDD架构实现收银用例主成功场景

1 面向DDD重构mis-pos模块

重要说明:由于代码量增加,且经常需要重构。笔记将难以展示项目完整代码。本章笔记开始只展示部分代码。完整代码详见笔记最后项目仓库分支代码。

参考上篇分析与设计制品,参考DDD架构,重构的mis-pos模块的架构分层。

根据DDD架构分为application、domain、infrastructure三个包。
在这里插入图片描述

2 基础设施层

基础设施层暂时还没有写太多的类。只是添加了SaleFactory用于实例化Sale。

引入Hutool工具类,用于生成订单的雪花ID。

        <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.20</version></dependency>

编写SaleFactory,实例化Sale并设置初始化值。

package edu.scau.mis.pos.infrastructure.factory;import cn.hutool.core.util.IdUtil;
import edu.scau.mis.pos.domain.entity.Sale;
import edu.scau.mis.pos.domain.enums.SaleStatusEnum;
import org.springframework.stereotype.Component;import java.math.BigDecimal;
import java.util.Date;/*** Sale工厂类*/
@Component
public class SaleFactory {public Sale initSale(){Sale sale = new Sale();sale.setSaleNo("so-" + IdUtil.getSnowflakeNextId());sale.setSaleStatus(SaleStatusEnum.CREATED);sale.setTotalAmount(BigDecimal.ZERO);sale.setTotalQuantity(0);sale.setSaleTime(new Date());return sale;}}

3 领域层

在DDD架构中,领域层是重点关注层。

为了简化Setter和getter编写,引入了Lombok。

        <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>

3.1 SaleProduct实体类

SaleProduct实体类包含了业务逻辑方法getSubTotal,计算每个订单明细的小计。

package edu.scau.mis.pos.domain.entity;import edu.scau.mis.pos.domain.enums.SaleProductStatusEnum;
import lombok.Data;import java.math.BigDecimal;/*** 订单-产品明细实体类*/
@Data
public class SaleProduct {private Long saleProductId;private Long saleId;private Long productId;private Product product;private Integer saleQuantity;private BigDecimal salePrice;private SaleProductStatusEnum saleProductStatus;/*** 计算小计* @return*/public BigDecimal getSubTotal() {return salePrice.multiply(new BigDecimal(saleQuantity));}
}

3.2 支付实体类

支付类暂时还没有写业务逻辑方法。后期考虑通过适配器,连接第三方支付。

package edu.scau.mis.pos.domain.entity;import com.fasterxml.jackson.annotation.JsonFormat;
import edu.scau.mis.pos.domain.enums.PaymentStatusEnum;
import edu.scau.mis.pos.domain.enums.PaymentStrategyEnum;
import lombok.Data;import java.math.BigDecimal;
import java.util.Date;/*** 支付实体类*/
@Data
public class Payment {private Long paymentId;private Long paymentSaleId;private PaymentStrategyEnum paymentStrategy;private String paymentNo;private BigDecimal paymentAmount;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private Date paymentTime;private PaymentStatusEnum paymentStatus;}

3.3 Sale聚合根

Sale类是收银领域层的聚合根。

该类内聚了两个业务逻辑方法,分别为添加订单明细和计算总金额。

package edu.scau.mis.pos.domain.entity;import com.fasterxml.jackson.annotation.JsonFormat;
import edu.scau.mis.pos.domain.enums.SaleStatusEnum;
import lombok.Data;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** 销售实体类* 聚合根*/
@Data
public class Sale {private Long saleId;private String saleNo;private BigDecimal totalAmount;private Integer totalQuantity;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private Date saleTime;private Payment payment;private List<SaleProduct> saleProducts = new ArrayList<>();private SaleStatusEnum saleStatus;/*** 计算总金额* @return*/public BigDecimal getTotal(){totalAmount = BigDecimal.ZERO;totalQuantity = 0;for(SaleProduct saleProduct: saleProducts){totalAmount = totalAmount.add(saleProduct.getSubTotal());totalQuantity = totalQuantity + saleProduct.getSaleQuantity();}return totalAmount;}/*** 添加订单明细* @param product* @param saleQuantity* @return*/public List<SaleProduct> makeLineItem(Product product, Integer saleQuantity) {// 判断商品是否已录入,未录入则新增。已录入则修改数量。if(!isEntered(product.getProductSn(),saleQuantity)){SaleProduct saleProduct = new SaleProduct();saleProduct.setProduct(product);saleProduct.setSaleQuantity(saleQuantity);saleProduct.setSalePrice(product.getProductPrice());saleProducts.add(saleProduct);}return saleProducts;}/*** 判断商品是否已录入* 业务逻辑:如果已录入,则修改数量,否则添加saleLineItem* @param productSn* @param saleQuantity* @return*/private boolean isEntered(String productSn, Integer saleQuantity){boolean flag = false;for(SaleProduct sp : saleProducts){if(productSn.equals(sp.getProduct().getProductSn())) {flag = true;Integer quantityOriginal = sp.getSaleQuantity();sp.setSaleQuantity(quantityOriginal + saleQuantity);}}return flag;}
}

3.4 领域服务类SaleService

主要用于生成支付功能。ISDP项目POS系统设计支持挂单功能。

package edu.scau.mis.pos.domain.service.impl;import cn.hutool.core.util.IdUtil;
import edu.scau.mis.pos.domain.entity.Payment;
import edu.scau.mis.pos.domain.entity.Sale;
import edu.scau.mis.pos.domain.enums.PaymentStatusEnum;
import edu.scau.mis.pos.domain.enums.PaymentStrategyEnum;
import edu.scau.mis.pos.domain.service.ISaleService;
import org.springframework.stereotype.Service;import java.math.BigDecimal;
import java.util.Date;/*** 领域服务*/
@Service
public class SaleServiceImpl implements ISaleService {@Overridepublic Payment makePayment(Sale sale, String paymentStrategy, BigDecimal paymentAmount) {Payment payment = new Payment();payment.setPaymentStrategy(PaymentStrategyEnum.valueOf(paymentStrategy));payment.setPaymentNo(paymentStrategy + "-" + IdUtil.getSnowflakeNextId());payment.setPaymentAmount(paymentAmount);payment.setPaymentTime(new Date());payment.setPaymentStatus(PaymentStatusEnum.PAID);// TODO: 根据不同支付策略调用不同外部接口return payment;}
}

3.5 其他

Domain层还有仓库、枚举等包。由于暂时还没有使用数据库和Redis,仓库代码暂时没写。

写了一些枚举类。由于只是教学项目,没有设计过多状态。

package edu.scau.mis.pos.domain.enums;/*** 订单状态枚举*/
public enum SaleStatusEnum {CREATED("0","已预订"),SUBMITTED("1","已提交"),PAID("2","已支付");private String value;private String label;SaleStatusEnum(String value, String label) {this.value = value;this.label = label;}public String getLabel() {return label;}public String getValue() {return value;}/*** 根据匹配value的值获取Label** @param value* @return*/public static String getLabelByValue(String value){for (SaleStatusEnum s : SaleStatusEnum.values()) {if(value.equals(s.getValue())){return s.getLabel();}}return "";}/*** 获取StatusEnum** @param value* @return*/public static SaleStatusEnum getStatusEnum(String value){for (SaleStatusEnum s : SaleStatusEnum.values()) {if(value.equals(s.getValue())){return s;}}return null;}
}

支付策略枚举类

package edu.scau.mis.pos.domain.enums;/*** 支付策略枚举*/
public enum PaymentStrategyEnum {WECHAT("wechat","微信支付"),ALIPAY("alipay","支付宝"),CASH("cash","现金");private String value;private String label;PaymentStrategyEnum(String value, String label) {this.value = value;this.label = label;}public String getLabel() {return label;}public String getValue() {return value;}/*** 根据匹配value的值获取Label** @param value* @return*/public static String getLabelByValue(String value){for (PaymentStrategyEnum s : PaymentStrategyEnum.values()) {if(value.equals(s.getValue())){return s.getLabel();}}return "";}/*** 获取StatusEnum** @param value* @return*/public static PaymentStrategyEnum getStrategyEnum(String value){for (PaymentStrategyEnum s : PaymentStrategyEnum.values()) {if(value.equals(s.getValue())){return s;}}return null;}
}

4 应用层

4.1 应用服务类SaleApplicationService

编写SaleApplicationService类。该类主要负责跨领域协作。

目前主要就两个领域Sale(SaleProduct、Payment)和Product(Category)。

如果使用微服务,可以分别针对这两个领域创建两个微服务模块。

package edu.scau.mis.pos.application.service;import edu.scau.mis.pos.application.assembler.SaleAssembler;
import edu.scau.mis.pos.application.dto.command.EnterItemCommand;
import edu.scau.mis.pos.application.dto.command.MakePaymentCommand;
import edu.scau.mis.pos.application.dto.vo.*;
import edu.scau.mis.pos.domain.entity.Payment;
import edu.scau.mis.pos.domain.entity.Product;
import edu.scau.mis.pos.domain.entity.Sale;
import edu.scau.mis.pos.domain.entity.SaleProduct;
import edu.scau.mis.pos.domain.enums.SaleStatusEnum;
import edu.scau.mis.pos.domain.service.IProductService;
import edu.scau.mis.pos.infrastructure.factory.SaleFactory;
import edu.scau.mis.pos.domain.service.ISaleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class SaleApplicationService {@Autowiredprivate IProductService productService;@Autowiredprivate ISaleService saleService;@Autowiredprivate SaleFactory saleFactory;@Autowiredprivate SaleAssembler saleAssembler;private Sale currentSale; // 后期改成Redis缓存CurrentSale/*** 开始一次新销售* @return*/public SaleVo makeNewSale(){SaleVo saleVo = new SaleVo();currentSale = saleFactory.initSale();// TODO:引入Redis缓存return saleAssembler.toSaleVo(currentSale);}/*** 录入商品* @param command* @return*/public SaleAndProductListVo enterItem(EnterItemCommand command){SaleAndProductListVo saleAndProductListVo = new SaleAndProductListVo();Product product = productService.selectProductBySn(command.getProductSn());List<SaleProduct> saleProducts = currentSale.makeLineItem(product, command.getSaleQuantity());currentSale.getTotal();List<SaleProductVo> saleProductVoList = saleProducts.stream().map(saleProduct -> new SaleProductVo(saleProduct.getProduct().getProductSn(), saleProduct.getProduct().getProductName(), saleProduct.getSalePrice(), saleProduct.getSaleQuantity())).toList();saleAndProductListVo.setSaleVo(saleAssembler.toSaleVo(currentSale));saleAndProductListVo.setSaleProductVoList(saleProductVoList);return saleAndProductListVo;}/*** 结束销售* 计算优惠、持久化订单等* @return*/public SaleVo endSale(){currentSale.setSaleStatus(SaleStatusEnum.SUBMITTED);// TODO: 持久化Sale和SaleProduct,添加事务注解return saleAssembler.toSaleVo(currentSale);}/*** 完成支付* @param command* @return*/public SaleAndPaymentVo makePayment(MakePaymentCommand command){SaleAndPaymentVo saleAndPaymentVo = new SaleAndPaymentVo();// TODO: 挂单--根据saleNo获取SalePayment payment = saleService.makePayment(currentSale,command.getPaymentStrategy(), command.getPaymentAmount());currentSale.setPayment(payment);currentSale.setSaleStatus(SaleStatusEnum.PAID);// TODO: 持久化Sale和Payment,添加事务注解// payment.setPaymentSaleId(sale.getSaleId());saleAndPaymentVo.setSaleVo(saleAssembler.toSaleVo(currentSale));saleAndPaymentVo.setPaymentVo(saleAssembler.toPaymentVo(payment));return saleAndPaymentVo;}
}

4.2 数据传输对象DTO

ISDP项目采用CQRS思想,该层编写大量的数据传输对象DTO。笔记只展示部分代码。详细参加项目仓库。

EnterItemCommand参考代码如下。

后期将使用Redis缓存currentSale,设计saleNo作为key。保留saleNo备用。

package edu.scau.mis.pos.application.dto.command;import lombok.Data;import java.io.Serializable;/*** 输入订单明细命令*/
@Data
public class EnterItemCommand implements Serializable {private String saleNo;private String productSn;private Integer saleQuantity;
}

MakePaymentCommand代码参考如下:

同上,saleNo暂时不需要。

package edu.scau.mis.pos.application.dto.command;import lombok.Data;import java.io.Serializable;
import java.math.BigDecimal;/*** 创建支付命令*/
@Data
public class MakePaymentCommand implements Serializable {private String saleNo;private BigDecimal paymentAmount;private String paymentStrategy;
}

SaleVo类

package edu.scau.mis.pos.application.dto.vo;import lombok.Data;import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class SaleVo implements Serializable {private String saleNo;private BigDecimal totalAmount;private Integer totalQuantity;private Date saleTime;private String saleStatus;
}

SaleAndPaymentVo

package edu.scau.mis.pos.application.dto.vo;import lombok.Data;import java.io.Serializable;
@Data
public class SaleAndPaymentVo implements Serializable {private SaleVo saleVo;private PaymentVo paymentVo;
}

4.3 对象转换器SaleAssembler

面向接口层主要使用DTO对象,因此不可避免涉及到DTO与领域对象的转换。

package edu.scau.mis.pos.application.assembler;import edu.scau.mis.pos.application.dto.vo.PaymentVo;
import edu.scau.mis.pos.application.dto.vo.SaleVo;
import edu.scau.mis.pos.domain.entity.Payment;
import edu.scau.mis.pos.domain.entity.Sale;
import org.springframework.stereotype.Component;/*** 订单转换器* 实现DTO与Entity的转换*/@Component
public class SaleAssembler {public SaleVo toSaleVo(Sale sale){SaleVo saleVo = new SaleVo();saleVo.setSaleNo(sale.getSaleNo());saleVo.setTotalAmount(sale.getTotalAmount());saleVo.setTotalQuantity(sale.getTotalQuantity());saleVo.setSaleTime(sale.getSaleTime());saleVo.setSaleStatus(sale.getSaleStatus().getLabel());return saleVo;}public PaymentVo toPaymentVo(Payment payment){PaymentVo paymentVo = new PaymentVo();paymentVo.setPaymentId(payment.getPaymentId());paymentVo.setPaymentSaleId(payment.getPaymentSaleId());paymentVo.setPaymentNo(payment.getPaymentNo());paymentVo.setPaymentAmount(payment.getPaymentAmount());paymentVo.setPaymentTime(payment.getPaymentTime());paymentVo.setPaymentStrategy(payment.getPaymentStrategy().getLabel());paymentVo.setPaymentStatus(payment.getPaymentStatus().getLabel());return paymentVo;}
}

5 接口层

5.1 Controller接口

SaleController参考如下:

package edu.scau.mis.web.controller;import edu.scau.mis.pos.application.dto.command.EnterItemCommand;
import edu.scau.mis.pos.application.dto.command.MakePaymentCommand;
import edu.scau.mis.pos.application.dto.vo.SaleAndPaymentVo;
import edu.scau.mis.pos.application.dto.vo.SaleAndProductListVo;
import edu.scau.mis.pos.application.dto.vo.SaleVo;
import edu.scau.mis.pos.application.service.SaleApplicationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/sale")
public class SaleController {@Autowiredprivate SaleApplicationService saleApplicationService;@GetMapping("/makeNewSale")public ResponseEntity<SaleVo> makeNewSale(){return ResponseEntity.ok(saleApplicationService.makeNewSale());}@PostMapping("/enterItem")public ResponseEntity<SaleAndProductListVo> enterItem(@RequestBody  EnterItemCommand enterItemCommand){return ResponseEntity.ok(saleApplicationService.enterItem(enterItemCommand));}@GetMapping("/endSale")public ResponseEntity<SaleVo> endSale(){return ResponseEntity.ok(saleApplicationService.endSale());}@PostMapping("/makePayment")public ResponseEntity<SaleAndPaymentVo> makePayment(@RequestBody MakePaymentCommand makePaymentCommand){return ResponseEntity.ok(saleApplicationService.makePayment(makePaymentCommand));}
}

5.2 接口测试

使用Knife4j对SaleController接口进行测试,简单验证后端业务逻辑。

5.2.1 makeNewSale接口

该接口目前只是初始化currentSale数据。
在这里插入图片描述

5.2.2 enterItem接口

接口接收产品编号和订购数量。

接口返回订单和订购商品集合的json数据。

在这里插入图片描述

5.2.3 endSale接口

该接口暂时未写太多业务逻辑,只是提交订单,更新订单状。

后期将会从redis中清除缓存currentSale,然后持久化currentSale数据。
在这里插入图片描述

5.2.4 makePayment接口

接口接收支付金额和支付方式两个参数。

接口返回订单和支付json数据。
在这里插入图片描述
本章笔记基于上篇的分析与设计模型,编写DDD架构基础设施层、领域层、应用层和接口层的代码。实现了收银用例的4个主要步骤makeNewSale、enterItem、endSale和makePayment。

下一篇笔记将应用适配器模式调用支付宝沙箱支付接口。

本笔记项目仓库地址:
https://gitcode.com/tiger2704/isdp-boot3/tree/isdp010

相关文章:

ISDP010_基于DDD架构实现收银用例主成功场景

信息系统开发实践 &#xff5c; 系列文章传送门 ISDP001_课程概述 ISDP002_Maven上_创建Maven项目 ISDP003_Maven下_Maven项目依赖配置 ISDP004_创建SpringBoot3项目 ISDP005_Spring组件与自动装配 ISDP006_逻辑架构设计 ISDP007_Springboot日志配置与单元测试 ISDP008_SpringB…...

如何注册华为云国际版账户:详细步骤指南

华为云作为全球知名的云计算服务提供商&#xff0c;提供了丰富的云服务和解决方案。无论是企业还是个人开发者&#xff0c;注册华为云国际版账户都是开启云计算之旅的第一步。我们九河云通过本文将为您详细介绍华为云国际版的注册流程。 第一步&#xff1a;访问华为云国际版官网…...

存储过程实现多个分类不同计算规则得到对应的分类、月份和款号

该存储过程 PRO_MON_MDCODE 实现多个分类不同计算规则得到对应的分类、月份和款号,其中线下分类的款最早出现时间会在20230101,最晚是当前月份后12月,电商的款取商品维表的23,24,25年商品年份的A款,其他业务分类逻辑(A-线上,B电商公司,C品牌公司)的款最早出现时间会在2…...

【LeetCode】906、超级回文数

【LeetCode】906、超级回文数 文章目录 一、通过数据量猜解法 枚举 数学 回文1.1 通过数据量猜解法 枚举 数学 回文1.2 多语言解法 二、打表法 一、通过数据量猜解法 枚举 数学 回文 1.1 通过数据量猜解法 枚举 数学 回文 减小数据规模: 先构成回文, 再平方, 再判断是否是范围…...

使 el-input 内部的内容紧贴左边

<el-inputv-model"form.invitor"placeholder"PC端的自动取当前账号的手机号"readonlyclass"no-border-input" />::v-deep(.no-border-input .el-input__inner) { border: none; box-shadow: none; padding-left: 0; /* 确保内容紧贴左边 *…...

【ES6复习笔记】模板字符串(3)

介绍 模板字符串是 ES6 引入的一种新的字符串声明方式&#xff0c;它使用反引号&#xff08;&#xff09;来定义字符串&#xff0c;而不是单引号&#xff08;&#xff09;或双引号&#xff08;"&#xff09;。模板字符串可以包含变量、表达式和换行符&#xff0c;这使得它…...

Linux学习

Linux Linux目录结构 Linux只有一个顶级目录&#xff0c;称之为&#xff1a;根目录 /在Linux系统中表示 出现在开头的/表示&#xff1a;根目录 出现在后面的/表示&#xff1a;层次关系 Linux命令基础 什么是命令、命令行 命令&#xff1a;即Linux操作指令&#xff0c;是系…...

【PostgreSQL使用】最新功能逻辑复制槽的failover,大数据下高可用再添利器

逻辑复制的failover ​专栏内容&#xff1a; postgresql入门到进阶手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. ✅ &#x1f52…...

MongoDB 创建用户、User、Role 相关 操作

创建用户 # db.createUser() Creates a new user.详细 查看 db.createUser() - MongoDB Manual v8.0 设置用户 Role&#xff08;创建用户时也可以设置&#xff09; # db.grantRolesToUser() Grants a role and its privileges to a user. 详细 查看 db.grantRolesToUser(…...

在 Vue3 项目中实现计时器组件的使用(Vite+Vue3+Node+npm+Element-plus,附测试代码)

一、概述 记录时间 [2024-12-26] 本文讲述如何在 Vue3 项目中使用计时器组件。具体包括开发环境的配置&#xff0c;ViteVue 项目的创建&#xff0c;Element Plus 插件的使用&#xff0c;以及计时器组件的创建和使用。 想要直接实现计时器组件&#xff0c;查看文章的第四部分。…...

Redis单线程快的原因

基于内存操作&#xff1a;Redis将数据存储在内存中&#xff0c;使得数据的读写速度极快&#xff0c;这是其性能优势的主要原因。单线程避免上下文切换&#xff1a;在多线程环境下&#xff0c;CPU核数有限&#xff0c;线程上下文切换会带来性能损耗。Redis采用单线程&#xff0c…...

基于SpringBoot的“在线BLOG网”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“在线BLOG网”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 在线BLOG网结构功能图 管理员登录功能界面 用户信息…...

重温设计模式--6、享元模式

文章目录 享元模式&#xff08;Flyweight Pattern&#xff09;概述享元模式的结构C 代码示例1应用场景C示例代码2 享元模式&#xff08;Flyweight Pattern&#xff09;概述 定义&#xff1a; 运用共享技术有效地支持大量细粒度的对象。 享元模式是一种结构型设计模式&#xff0…...

springboot-starter版本升级es版本问题

一、背景说明 版本漏洞处理&#xff0c;springboot版本升级&#xff0c;es版本暂不升级&#xff0c;但是pom引用中es版本一直为7.17.15高版本&#xff0c;不想显示声明版本&#xff0c;定位具体问题&#xff0c;最后还是重新定义了版本进行处理。 二、异常情况 这里看4.4.18是…...

嵌入式科普(25)Home Assistant米家集成意味着IOT的核心是智能设备

目录 一、概述 二、一张图说尽HA 三、HA的相关资料 四、米家集成划重点 五、总结 一、概述 小米Home Assistant 米家集成开源一周star近15k&#xff0c;迭代4个版本&#xff0c;12个贡献者 本文科普一下Home Assistant&#xff08;简称HA&#xff09;、米家集成&#xff…...

前端Python应用指南(四)Django实战:创建一个简单的博客系统

《写给前端的python应用指南》系列&#xff1a; &#xff08;一&#xff09;快速构建 Web 服务器 - Flask vs Node.js 对比&#xff08;二&#xff09;深入Flask&#xff1a;理解Flask的应用结构与模块化设计&#xff08;三&#xff09;Django vs Flask&#xff1a;哪种框架适…...

webrtc获取IceCandidate流程

在WebRTC(Web Real-Time Communication)中,ICECandidate是一个关键概念,它用于描述在建立点对点(P2P)连接时可以考虑的潜在通信端点。以下是关于WebRTC中ICECandidate的详细解释: 一、ICECandidate的定义 ICECandidate对象通常包含以下关键属性: foundation:用于唯一…...

快速入门Spring AI Alibaba

文章目录 前言一、环境准备二、获取API Key三、代码示例pomapplication.ymlcontroller 前言 Spring Cloud Alibaba AI 以 Spring AI 为基础&#xff0c;并在此基础上&#xff0c;基于 Spring AI 0.8.1 版本 API 完成同义系列大模型的接入实现阿里云同义系列大模型全面适配。 在…...

【mysql】MVCC及实现原理

【mysql】MVCC及实现原理 【一】介绍【1】什么是MVCC【2】什么是当前读和快照读【3】当前读&#xff0c;快照读和MVCC的关系【4】MVCC 能解决什么问题&#xff0c;好处&#xff08;1&#xff09;数据库并发场景有三种&#xff0c;分别为&#xff1a;&#xff08;2&#xff09;M…...

C++ —— 模板类与函数

C —— 模板类与函数 模板类可以用于函数的参数和返回值&#xff0c;有三种形式&#xff1a; 普通函数&#xff0c;参数和返回值是模板类的实例化版本。函数模板&#xff0c;参数和返回值是某种的模板类。函数模板&#xff0c;参数和返回值是任意类型&#xff08;支持普通类和…...

【笔记】下载mysql5.7

MySQL5.7安装超详细步骤(保姆级教程)_mysql5.7下载安装-CSDN博客 下载与安装 初次登录以及改密码 MySQL 5.7 安装教程&#xff08;全步骤图解教程&#xff09;_mysql5.7的安装教程-CSDN博客...

让 AMD GPU 在大语言模型推理中崭露头角:机遇与挑战

在当今科技飞速发展的时代&#xff0c;大语言模型&#xff08;LLM&#xff09;的兴起彻底改变了人工智能领域的格局。从智能客服到文本生成&#xff0c;从知识问答到代码编写辅助&#xff0c;大语言模型的应用无处不在&#xff0c;深刻影响着我们的生活和工作。然而&#xff0c…...

Linux运维常见命令

vi/vim快捷键使用 1)拷贝当前行 yy ,拷贝当前行向下的5行 5yy&#xff0c;并粘贴&#xff08;输入p&#xff09;。 2)删除当前行 dd ,删除当前行向下的5行5dd 3)在文件中查找某个单词 [命令行下 /关键字&#xff0c;回车查找 ,输入n就是查找下一个 ] 4)设置文件的行号&…...

前端真实面试题自用

一、写在前面 笔者&#xff0c;经过计算机学硕考研的失败后&#xff0c;想谋求一份前端工作实在是太难了。一方面&#xff0c;确实曾经学习过的东西很久没有拾起&#xff0c;另一方面&#xff0c;对于前端面经还是记忆不深刻&#xff0c;特地写此贴记录笔者在真实前端面试中遇…...

人工智能与云计算的结合:如何释放数据的无限潜力?

引言&#xff1a;数据时代的契机 在当今数字化社会&#xff0c;数据已成为推动经济与技术发展的核心资源&#xff0c;被誉为“21世纪的石油”。从个人消费行为到企业运营决策&#xff0c;再到城市管理与国家治理&#xff0c;每个环节都在生成和积累海量数据。然而&#xff0c;数…...

初始 ShellJS:一个 Node.js 命令行工具集合

一. 前言 Node.js 丰富的生态能赋予我们更强的能力&#xff0c;对于前端工程师来说&#xff0c;使用 Node.js 来编写复杂的 npm script 具有明显的 2 个优势&#xff1a;首先&#xff0c;编写简单的工具脚本对前端工程师来说额外的学习成本很低甚至可以忽略不计&#xff0c;其…...

benchmarksql5.0 测试工具如何在达梦上能够跑起来?

(1)添加驱动程序文件&#xff1a; lib文件夹下创建一个dm文件夹&#xff0c;并在dm文件夹下放置达梦数据库的驱动程序&#xff1a;DmJdbcDriver8.jar (2)引用驱动程序文件所在目录: 在文件benchmarksql-5.0/run/funcs.sh中的function setCP()函数中&#xff1b; 也就是在文件…...

amazon广告授权

amazon授权资料地址 Amazon Advertising Advanced Tools Center postman地址&#xff1a;Amazon Advertising Advanced Tools Center...

设计模式与游戏完美开发(2)

更多内容可以浏览本人博客&#xff1a;https://azureblog.cn/ &#x1f60a; 该文章主体内容来自《设计模式与游戏完美开发》—蔡升达 第二篇 基础系统 第四章 游戏主要类——外观模式&#xff08;Facade&#xff09; 一、游戏子功能的整合 一个游戏程序常常由内部数个不同的…...

WebRTC服务质量(10)- Pacer机制(02) RoundRobinPacketQueue

WebRTC服务质量&#xff08;01&#xff09;- Qos概述 WebRTC服务质量&#xff08;02&#xff09;- RTP协议 WebRTC服务质量&#xff08;03&#xff09;- RTCP协议 WebRTC服务质量&#xff08;04&#xff09;- 重传机制&#xff08;01) RTX NACK概述 WebRTC服务质量&#xff08;…...

VSCode调试

目录 C/C远程本地调试插件配置参考 C/C远程本地调试 测试源码&#xff1a;https://github.com/jrhee17/ssl-study 插件 Remote - SSH C/C 配置 .vscode/launch.json {"version": "0.2.0","configurations": [{"name": "afte…...

【ES6复习笔记】解构赋值(2)

介绍 解构赋值是一种非常方便的语法&#xff0c;可以让我们更简洁地从数组和对象中提取值&#xff0c;并且可以应用于很多实际开发场景中。 1. 数组的解构赋值 数组的解构赋值是按照一定模式从数组中提取值&#xff0c;然后对变量进行赋值。下面是一个例子&#xff1a; con…...

01 - 初识 Spring

初识Spring 企业级应用 企业级应用是指那些为商业组织、⼤型企业而创建并部署的解决⽅案及应用。这些⼤型的企业级应用结构复 杂、涉及的外部资源众多&#xff0c;事务密集&#xff0c;数据规模⼤&#xff0c;用户数量多&#xff0c;有较强的安全性考虑和较⾼的性能要求。 …...

重装荣耀X14笔记本电脑踩坑记

这几天趁着有国补搞了台荣耀 X14笔记本电脑。到手后第一件事情对我来说当然是要重装成Windows 11 LTSC版。所以按以往的经验做了个USB启动安装盘&#xff0c;但发现上电后按F12能进入启动设备选择&#xff0c;可是USB分类下没有任何设备。重启按F2进入设置界面&#xff0c;关闭…...

华为管理变革之道:奋斗文化与活力

目录 企业文化是什么&#xff1f; 为什么活下去是华为的文化&#xff1f; 活下来&#xff0c;是华为公司的最低纲领&#xff0c;也是华为公司的最高纲领&#xff01; 资源终会枯竭&#xff0c;唯有文化才能生生不息 企业文化之一&#xff1a;以客户为中心 企业文化之二&a…...

代码随想录算法训练营第十五天-二叉树-110.平衡二叉树

所谓平衡二叉树是指任意子树的高度差不超过1目前所学习的有关二叉树的问题&#xff0c;都是基于二叉树的遍历顺序来实现的 #include <iostream> #include <sstream> #define LEN 10009struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(): val(0…...

各种网站(学习资源、常用工具及其他,持续更新中~)

欢迎围观笔者的个人博客~ 也欢迎通过RSS网址https://kangaroogao.github.io/atom.xml进行订阅~ 大学指南 上海交通大学生存手册中国科学技术大学人工智能与数据科学学院本科进阶指南USTC不完全入学指南大学生活质量指北科研论 信息搜集 AI信息搜集USTC飞跃网站计算机保研 技…...

【gunicorn -k gevent 参数gevent说明,主要CPU密集和I/O密集型】

CPU 密集型和I/O 密集型是两种不同的计算任务类别&#xff0c;它们的性能瓶颈来源不同&#xff1a; 1. CPU 密集型 定义 CPU 密集型任务是指主要消耗 CPU 计算资源 的任务。这类任务需要大量的计算操作&#xff0c;而很少涉及 I/O 操作&#xff08;如网络或磁盘的读写&#x…...

快速理解24种设计模式

简单工厂模式 建立产品接口类&#xff0c;规定好要实现方法。 建立工厂类&#xff0c;根据传入的参数&#xff0c;实例化所需的类&#xff0c;实例化的类必须实现指定的产品类接口 创建型 单例模式Singleton 保证一个类只有一个实例&#xff0c;并提供一个访问他它的全局…...

5G -- 5G网络架构

5G组网场景 从4G到5G的网络演进&#xff1a; 1、UE -> 4G基站 -> 4G核心网 * 部署初中期&#xff0c;利用存量网络&#xff0c;引入5G基站&#xff0c;4G与5G基站并存 2、UE -> (4G基站、5G基站) -> 4G核心网 * 部署中后期&#xff0c;引入5G核心网&am…...

硬件开发笔记(三十二):TPS54331电源设计(五):原理图BOM表导出、元器件封装核对

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/144753092 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…...

UE5 崩溃问题汇总!!!

Using bundled DotNet SDK version: 6.0.302 ERROR: UnrealBuildTool.dll not found in "..\..\Engine\Binaries\DotNET\UnrealBuildTool\UnrealBuildTool.dll" 在你遇到这种极奇崩溃的BUG &#xff0c;难以解决的时候。 尝试了N种方法&#xff0c;都不行的解决方法。…...

美国站群服务器如何帮助实现有效的多域名管理?

国站群服务器以其丰富的IP资源、高性能硬件和灵活的配置选项&#xff0c;成为多域名管理的理想选择。特别是在需要针对不同域名实现SEO优化、业务分离或多站点运营的场景中&#xff0c;美国站群服务器提供了高效且实用的解决方案。以下是如何利用美国站群服务器实现有效的多域名…...

VMware的三种网络模式——在NAT模式下开放接口为局域网内其他主机提供服务

众所周知 VMware 有三种常用的网络通讯模式&#xff0c;分别是&#xff1a;Bridged&#xff08;桥接模式&#xff09;、NAT&#xff08;网络地址转换模式&#xff09;、Host-Only&#xff08;仅主机模式&#xff09;&#xff0c;它们各有不同的用法。 Bridged 桥接模式是与主机…...

【漏洞复现】灵当CRM datapdf.php 任意文件读取漏洞

免责声明 请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。工具来自网络,安全性自测,如有侵权请联系删除。本次测试仅供学习使用,如若非法他用,与平台和本文作…...

MySql详细教程-从入门到进阶(超实用)

基础篇 通用语法及分类 DDL: 数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库、表、字段&#xff09;DML: 数据操作语言&#xff0c;用来对数据库表中的数据进行增删改DQL: 数据查询语言&#xff0c;用来查询数据库中表的记录DCL: 数据控制语言&#xff0c;用…...

【C语言练习(17)—输出杨辉三角形】

C语言练习&#xff08;17&#xff09; 文章目录 C语言练习&#xff08;17&#xff09;前言题目题目解析整体代码 前言 杨辉三角形的输出可以分三步&#xff0c;第一步构建一个三角形、第二步根据规律将三角形内容填写、第三步将三角形以等腰的形式输出 题目 请输出一个十行的…...

服务器压力测试怎么做

在部署任何Web应用程序或服务之前&#xff0c;进行服务器压力测试&#xff08;也称为负载测试&#xff09;是确保系统能够处理预期用户流量的关键步骤。通过模拟大量并发请求&#xff0c;可以评估服务器的性能、稳定性和响应时间&#xff0c;识别潜在瓶颈&#xff0c;并优化资源…...

深度学习中的正则化

深度学习中的正则化(regularization)旨在防止过拟合并提高模型对未知数据的泛化能力。正则化是一种通过在给定的训练集上适当地拟合函数并避免过度拟合来减少误差的技术。 通过对模型参数添加约束&#xff0c;正则化鼓励模型学习更简单、更稳健的模式&#xff0c;从而降低其对噪…...

深入了解 React:从入门到高级应用

深入了解 React&#xff1a;从入门到高级应用 React 是由 Facebook 开发并维护的一个开源 JavaScript 库&#xff0c;用于构建用户界面。自2013年发布以来&#xff0c;React 在前端开发领域迅速崛起&#xff0c;成为最受欢迎的 UI 构建工具之一。无论是小型的单页应用&#xf…...