微服务-商城订单服务项目

文章目录

    • 一、需求
    • 二、分析
    • 三、设计
    • 四、编码
      • 4.1 商品服务
      • 4.2 订单服务
      • 4.3 分布式事务
      • 4.4 订单超时

商品、购物车
商品服务:
1.全品类购物平台
image.png
image.png
image.png
image.png
image.png
SPU:Standard Product Unit 标准化产品单元。是商品信息聚合的最小单位。是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。通俗点讲,属性值、特性相同的商品就可以称为一个SPU。通俗的说法:商品属性
SKU:Stock Keeping Unit,库存进出计量的基本单元,可以是以件,盒,托盘等为单位。通俗的说法:影响商品库存的属性。
SPU包含SKU
一个商品有100个属性,SPU,2个属性影响库存,2个SKU
购物车服务:
加减号的性能:Redis缓存->更新Redis->MQ->更新Mysql

一、需求

image.png
实现订单业务:预览、下单、订单超时、取消订单、更新订单状态、我的订单
下单(超卖)、超时(回滚)、取消(回滚)
image.png

二、分析

订单状态:

  1. 待付款:代表买家下单了但是还没有付款。
  2. 待发货(同待接单):代表买家付款了卖家还没有发货。
  3. 已发货(同待收货):代表卖家已经发货并寄出商品了。
  4. 已完成(同待评价):代表买家已经确认收到货了。
  5. 已关闭(同已取消):代表订单过期了买家也没付款、或者卖家关闭了订单。
  6. 已超时:超过一定时间,没有付款

订单的核心接口:
下单:购物车选择
下单:商品详情-立即购买
下单接口
订单超时-MQ的延迟队列
订单取消接口
查询我的订单
更改订单状态接口

三、设计

数据库设计:


CREATE TABLE `t_items`  (
`id` int(11) primary key auto_increment,
`name` varchar(20) ,
`no` varchar(10)
) comment '10.商品类型表';

CREATE TABLE `t_goods`  (
`id` int(11) primary key AUTO_INCREMENT,
`item_id` int(11) comment '类型id',
`title` varchar(256) comment '名称',
`promo_words` varchar(2048) comment '描述',
`small_pic` varchar(100) comment '图片',
`price` decimal(10, 2) comment '价格',
`create_time` datetime,
`status` char(1) comment '状态',
`stock_num` int(11) comment '库存数量'
) comment '11.商品表';

CREATE TABLE `t_cart`  (
`id` int(11) primary key auto_increment,
`uid` int,
`gid` int,
`gjprice` decimal(10, 2) comment '加入时价格',
`num` int
) comment '12.购物车表';

CREATE TABLE `t_order`  (
`id` int(11) primary key auto_increment,
`uid` int,
`uaid` int comment '用户收货地址',
`total_money` decimal(10, 2) comment '总金额',
`pay_money` decimal(10, 2) comment '支付金额',
`free_money` decimal(10, 2) comment '优惠金额',
`pay_type` int comment '支付类型',
`flag` int comment '订单状态',
`create_time` datetime comment '创建时间',
`update_time` datetime comment '更新时间'
) comment '13.订单表';

CREATE TABLE `t_orderitem`  (
`id` int(11) primary key auto_increment,
`oid` int,
`gid` int,
`price` decimal(10, 2) comment '价格',
`num` int
) comment '14.订单详情表';

CREATE TABLE `t_orderlog`  (
`id` int(11) primary key auto_increment,
`oid` int,
`type` int comment '对应订单状态类型',
`info` varchar(50) comment '内容',
`create_time` datetime
) comment '15.订单状态变化表';

难点:
1.超卖 -锁
2.数据一致性–事务
3.超时-MQ死信机制
4.性能-MQ削峰填谷

锁:保证多个线程,同时只能有一个访问
事务:保证多个SQL语句,要么都成功要么都失败

四、编码

4.1 商品服务

DDD领域驱动模型

image.png
什么时候可以使用DDD领域驱动:大型互联网
业务:快速变化
需求变更快,需求迭代快,业务扩展快的项目。
开发人员:3-5年经验
需要熟练应用过很多设计模式,有了这些经验才能理解为什么这么设计,才能不偷懒的去做这件事,否则很容易对领域造成污染。
时间:更充分
需要有充分的时间去划分业务,设计领域,需要更多的类,编写更多代码量
DDD领域驱动设计的分包:

  • gate: 对外暴露的服务
    • rest:对外暴露的rest服务
  • application:应用服务层
  • domain:领域层
    • item:商品分类
    • goods:商品
  • infra:基础设施层
    • repo:仓储实现
    • mapper: 数据库交互

ORM框架:操作数据库的框架
Mybatis(Mybatis-plus)、Hibernate(曾经的王者)、Spring Data JPA
SSH框架:Struts2+Spring+Hibernate
SSM框架:SpringMVC+Spring+Mybatis
SSS框架:SpringMVC+Spring+Spring Data JPA
SpringBoot框架:Spring+SpringMVC+Mybatis(Spring Data JPA)
Spring Data JPA:Spring开发的一套操作数据库的框架
Spring Data系列框架,都是Spring封装操作数据的各种框架的组合
比如:
操作Mysql数据库:Spring Data JPA
操作Redis数据库:Spring Data Redis
操作ElasticSearch:Spring Data ElasticSearch
Spring Data JPA基于Java 的JPA技术,实现的操作数据库的框架,基于注解实现数据库的操作
特性:自动生成对应表,封装了单表的操作,多种实现方式(JPQL、方法名解析查询、原生SQL、CRUD接口)
使用步骤:
1.依赖jar包

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2.实现配置

spring:
  application:
    name: GoodsServer-xph
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  datasource:
    url: jdbc:mysql://110.40.192.129:3310/db_cloud
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: zzjava
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      initial-size: 15
      max-active: 100
      min-idle: 15
      max-wait: 60000
      web-stat-filter:
        enabled: true
        url-pattern: "/*"
        exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
      stat-view-servlet:
        url-pattern: "/druid/*"
        reset-enable: false
        login-username: admin
        login-password: zzjava
        enabled: true
  jpa:
    database: mysql
    hibernate:
      ddl-auto: update

3.编写实体类

@Data
@Entity //标识 映射类
@Table(name = "t_goods")//设置表名
public class Goods {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private Integer itemId;
    private String title;
    private String promoWords;
    private String smallPic;
    private Date createTime;
    private Integer status;
    private Integer stockNum;
}

4.编写持久
创建接口继承JpaRepository

public interface GoodsDao extends JpaRepository<Goods,Integer> {
   //查询 JQPL:面向对象查询语言 表->类
    @Query(value = "from Goods")
    List<Goods> selectAll();
    //方法名解析查询:按照约定,编写方法名,就会自动生成SQL语句
    Goods getById(int id);
    //模糊查询
    List<Goods> getByTitleLike(String title);
    //原生SQL语句
    @Modifying//执行DML类型
    @Query(value = "update t_goods set stock_num=stock_num+:num where id=:id",nativeQuery = true)
    int updateStock(int num,int id);
}

5.使用
Spring Data JPA的核心:
1.接口:JpaRepository<实体类名,注解的数据类型>
提供:单表的增删改查分页和排序
2.JPQL:面向对象查询语言
Spring Data JPA-封装的面向对象查询语句
表名—>类名
字段—>属性
@Query 注解

@Query(value = "from Goods")
List<Goods> selectAll();

比如:
sql:select * from t_goods
jpql:from Goods
3.方法名解析查询
根据规则,合理的命名方法名,可以自动根据方法名生成SQL语句
image.png
image.png
4.原生SQL语句
可以在注解@Query上面写SQL语句,但是需要设置属性:nativeQuery = true。否则只能写jpql
如果执行的sql语句是DML类型,那么必须使用一个注解:@Modifying//执行DML类型

@Modifying//执行DML类型
@Query(value = "update t_goods set stock_num=stock_num+:num where id=:id",nativeQuery = true)
int updateStock(int num,int id);

4.2 订单服务

搬砖
下单接口–>考虑实现订单超时
下单接口的第一版实现:

@Service
public class OrderServiceImpl implements OrderService {
    @Resource
    private OrderDao dao;
    @Resource
    private OrderLogDao logDao;
    @Resource
    private OrderItemDao itemDao;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private GoodsProvider goodsProvider;
    @Resource
    private CouponProvider couponProvider;
    
    
    //难点:1.超卖-锁 2.多服务调用-数据一致性-事务 3.性能-Redis MQ 4.订单超时
    @Override
    public R save(OrderAddDto dto,int uid) {
        //下单业务-流程
        //1.查询商品 跨服务远程调用
        R rgoods=goodsProvider.single(dto.getGid());
        if(RCode.成功.getCode()==rgoods.getCode()){
            GoodsDto goodsDto= (GoodsDto) rgoods.getData();
            
            //2.验证库存 校验商品是否存在并查验商品状态
            if(goodsDto!=null && SystemConfig.GOODS_STATUS_UP==goodsDto.getStatus()){
                //检查库存 普通锁
                Lock lock=new ReentrantLock();
                lock.lock();
                try {
                    if (goodsDto.getStockNum() >= dto.getNum()) {
                        //库存够
                        
                        //3.生成订单
                        Order order = new Order();
                        order.setFlag(OrderFlag.待付款.getCode());
                        order.setTotalMoney(goodsDto.getPrice() * dto.getNum());
                        //优惠金额=积分抵扣+优惠券减免
                        order.setFreeMoney(dto.getScore() / 100.0);
                        //4.查询优惠信息,计算优惠
                        boolean isCoupon = false;
                        UserCouponDto couponDto = couponProvider.detail(dto.getUcid());
                        if (couponDto != null) {
                            //前端已经校验,为什么后端还需要校验,防止绕过前端
                            // 验证优惠券是否可用 1.有没有失效 2.满减规则 3.范围
                            if (couponDto.getCategory() == 51) {
                                //满减 满一定金额。才可以使用优惠券
                                if (order.getTotalMoney() >= couponDto.getLimitmoney()) {
                                    order.setFreeMoney(order.getFreeMoney() + couponDto.getDiscount());
                                    isCoupon = true;
                                }
                            } else if (couponDto.getCategory() == 52) {
                                //折扣 满一定金额才可以才可以打折
                                if (order.getTotalMoney() >= couponDto.getLimitmoney()) {
                                    order.setFreeMoney(order.getFreeMoney() + order.getTotalMoney() * couponDto.getDiscount());
                                    isCoupon = true;
                                }
                            } else if (couponDto.getCategory() == 53) {
                                //立减
                                order.setFreeMoney(order.getFreeMoney() + couponDto.getDiscount());
                                isCoupon = true;
                            }
                        }
                        //设置支付金额
                        order.setPayMoney(order.getTotalMoney() - order.getFreeMoney());
                        
                        order.setCreateTime(new Date());
                        order.setUaid(dto.getUaid());
                        order.setUpdateTime(new Date());
                        //操作数据库,新增订单
                        if (dao.insert(order) > 0) {
                            
                            //4.扣减库存
                            goodsProvider.update(new GoodsStockDto(goodsDto.getId(), dto.getNum()));
                            
                            //5.积分抵扣
                            if (dto.getScore() > 0) {
                                //MQ
                                rabbitTemplate.convertAndSend("",
                                                              RabbitMQConstConfig.Q_USERSCORE,
                                                              new MqMsgBo(SnowFlowUtil.getInstance().nextId(), RabbitMQConstConfig.MQTYPE_ORDERADD,
                                                                          new UserMqBo(uid, dto.getScore(), SystemConfig.USER_OP_SIGN, "", "")));
                            }
                            
                            //6.优惠券使用
                            if (isCoupon) {
                                couponProvider.update(couponDto.getId(), SystemConfig.USER_COUPON_USED);
                            }
                            
                            //7.新增订单详情
                            OrderItem item = new OrderItem(order.getId(), dto.getGid(), goodsDto.getPrice(), dto.getNum());
                            itemDao.insert(item);
                            //8.记录订单流水
                            logDao.insert(new OrderLog(order.getId(), OrderFlag.待付款.getCode(), "商品详情下单成功!"));
                            
                            return RUtil.ok(order);
                        }
                    } else {
                        //库存不够
                        return RUtil.fail("亲,商品库存不足!");
                    }
                }finally {
                    lock.unlock();
                }
                //分布式锁
                
                
            }else {
                return RUtil.fail("亲,商品不存在!");
            }
        }
        return RUtil.fail("亲,商品服务异常!");
    }
}

查询我的订单
取消订单

4.3 分布式事务

事务、分布式事务:解决数据操作(DML)的一致性
分布式事务:解决多个服务嵌套调用(涉及到数据库的数据改变),保证要么都成功,要么都失败
比如:订单服务,远程调用商品服务、优惠券服务,保证三个服务要么都成功,要么都失败!
为什么需要使用分布式事务?
因为在服务的嵌套调用的时候,每个服务都有自己的Connection,所以之前的事务,只能保证同一个Connection下操作的一致性。
什么时候使用分布式事务:
服务嵌套调用,且服务(>1)都涉及到了DML语句的执行
为什么说:分布式事务是世界性难题?
原因:CAP

分布式事务解决方案:
1.2PC
1.准备阶段
2.确认阶段:提交或回滚
2.3PC
1.准备阶段
2.预提交阶段
3.确认阶段:提交或回滚
3.TCC
try:尝试执行
confrim:尝试成功,确认
cancel:尝试失败,取消
4.基于MQ
订单业务实现分布式事务:
订单服务:
1.依赖jar包

<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <version>2021.1</version>
</dependency>

2.实现配置
image.png
3.入口方法上开启全局事务
所有被分布式事务协调的方法都需要本地事务的支持
image.png
商品服务:
1.依赖jar包

<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <version>2021.1</version>
</dependency>

2.实现配置
image.png
3.涉及方法上开启本地事务
image.png
优惠券服务:
1.依赖jar包

<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <version>2021.1</version>
</dependency>

2.实现配置
image.png
3.涉及方法上开启本地事务
image.png
默认使用的是Seata中的XA模式的事务提交方案,运行前务必保证nacos的运行和Seata-Server的运行
启动Seata-Server:sh seata-server.sh -p 8091 -m file

4.4 订单超时

image.png
代码示例:

// 下单->Redis->MQ->数据同步+延迟队列
    @Override
    public R save2(OrderAddDto dto, int uid) {
        R rgoods=goodsProvider.single(dto.getGid());
        if(RCode.成功.getCode()==rgoods.getCode()) {
            GoodsDto goodsDto = (GoodsDto) rgoods.getData();

            //2.验证库存 校验商品是否存在并查验商品状态
            if (goodsDto != null && SystemConfig.GOODS_STATUS_UP == goodsDto.getStatus()) {
                //检查库存 普通锁
                Lock lock = new ReentrantLock();
                lock.lock();
                try {
                    if (goodsDto.getStockNum() >= dto.getNum()) {
                        //生成订单 存储Redis--MQ--Mysql
                        Order order = new Order();
                        order.setNo(SnowFlowUtil.getInstance().nextId());
                        order.setFlag(OrderFlag.待付款.getCode());
                        order.setCreateTime(new Date());
                        order.setUaid(dto.getUaid());
                        order.setUid(uid);
                        order.setUpdateTime(new Date());
                        order.setTotalMoney(goodsDto.getPrice() * dto.getNum());
                        if(dto.getUcid()>0){
                            //有优惠券
                            UserCouponDto couponDto = couponProvider.detail(dto.getUcid());
                            order.setFreeMoney(couponDto.getCategory()==52?order.getTotalMoney()-(order.getTotalMoney() * couponDto.getDiscount()):couponDto.getDiscount());
                        }
                        if(dto.getScore()>0){
                            //有积分抵扣
                            order.setFreeMoney(order.getFreeMoney()+dto.getScore()/100.0);
                        }
                        order.setPayMoney(order.getTotalMoney()-order.getFreeMoney());

                        //扣减库存
                        R r=goodsProvider.update(new GoodsStockDto(goodsDto.getId(), -dto.getNum()));
                        if(r.getCode()==RCode.成功.getCode()){

                            //订单存储到Redis中 类型 有效期 数据 同步
                            RedissonUtils.setHash(RedisKeyConfig.ORDER_ADD,order.getNo()+"",order);

                            //基于MQ发送消息
                            rabbitTemplate.convertAndSend(RabbitMQConstConfig.EX_ORDERADD,"",
                                    new MqMsgBo(SnowFlowUtil.getInstance().nextId(), RabbitMQConstConfig.MQTYPE_ORDERSYNC,
                                            new OrderSyncDto(order.getNo()+"",dto.getUcid(),dto.getGid(),dto.getNum(),goodsDto.getPrice())));


                            //.积分抵扣
                            if (dto.getScore() > 0) {
                                //MQ
                                rabbitTemplate.convertAndSend("",
                                        RabbitMQConstConfig.Q_USERSCORE,
                                        new MqMsgBo(SnowFlowUtil.getInstance().nextId(), RabbitMQConstConfig.MQTYPE_ORDERADD,
                                                new UserMqBo(uid, dto.getScore(), SystemConfig.USER_OP_SIGN, "", "")));
                            }
                            return RUtil.ok();
                        }else {
                            return RUtil.fail("亲,网络异常,商品服务库存问题!");
                        }
                    }
                } finally {
                    lock.unlock();
                }
            }
        }
        return RUtil.fail("亲,下单失败!");
    }

    @Override
    public R queryMy(int uid, int flag) {
        QueryWrapper<Order> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("uid",uid);
        if(flag>0){
            queryWrapper.eq("flag",flag);
        }
        queryWrapper.orderByDesc("id");
        return RUtil.ok(dao.selectList(queryWrapper));
    }
    //后台调用-发货
    @Override
    public R updateFlag(OrderFlagDto dto) {
        if(dao.updateFlag(dto.getOid(),dto.getFlag())>0){
            return RUtil.ok();
        }else {
            return RUtil.fail();
        }
    }

    @Transactional
    @GlobalTransactional //分布式事务
    @Override
    public R cancel(String no,int uid) {
        //1.查询订单状态,防止
        Order order=dao.selectOne(new QueryWrapper<Order>().eq("no",no).eq("uid",uid));
        if(order!=null){
            //验证订单状态
            if(order.getFlag()==OrderFlag.待付款.getCode()){
                //超时了,取消订单
                //更改订单状态
                if(dao.updateFlag(order.getId(),OrderFlag.已关闭.getCode())>0){
                    //查询订单详情
                    List<OrderItem> items=itemDao.selectList(new QueryWrapper<OrderItem>().eq("oid",order.getId()));
                    items.forEach(oi->{
                        //释放库存
                        goodsProvider.update(new GoodsStockDto(oi.getGid(),oi.getNum()));
                    });
                    //释放优惠券
                    OrderLog couponlog=logDao.selectOne(new QueryWrapper<OrderLog>().eq("oid",order.getId()).eq("type",100));
                    if(couponlog!=null){
                        //用了优惠券,释放
                        couponProvider.update(Integer.parseInt(couponlog.getInfo()),SystemConfig.USER_COUPON_NO);
                    }
                    //释放积分
                    OrderLog scorelog=logDao.selectOne(new QueryWrapper<OrderLog>().eq("oid",order.getId()).eq("type",101));
                    if(scorelog!=null){
                        //用了积分,释放
                        userProvider.updateScore(order.getUid(),Integer.parseInt(scorelog.getInfo()),SystemConfig.SCORETYPE_ORDERCANCEL);
                    }
                    //记录日志
                    logDao.insert(new OrderLog(order.getId(), OrderFlag.已超时.getCode(), "订单超时,自动取消!"));
                }
            }
        }
        return RUtil.fail("订单取消失败!");
    }

如果感觉有用点个关注,一键三连吧!蟹蟹!!!
在这里插入图片描述

各位看官》创作不易,点个赞!!!
诸君共勉:看花不是花,看雪不是雪
免责声明:本文章仅用于学习参考

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Biotin-PEG2-Thiol,生物素-PEG2-巯基,应用于抗体标记、蛋白质富集等领域

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;Biotin-PEG2-Thiol&#xff0c;生物素-PEG2-巯基&#xff0c;Biotin PEG2 Thiol&#xff0c;生物素 PEG2 巯基 一、基本信息 【产品简介】&#xff1a;Biotin PEG2 Thiol can bind with antibodies to prepare biot…

第12课-在网络上写作,让你事半功倍的14个独家秘诀

公众号文章写作方向要专一&#xff0c;太杂的内容很难留住用户&#xff0c;这就要求我们早起尽快确定自己擅长的领域&#xff0c;然后不断精进。 在写作的过程中确定自己的写作风格&#xff0c;而写作风格的确立需要长时间的写作积累&#xff0c;会经历迷茫和混乱&#xff0c;…

数据库管理-第156期 Oracle Vector DB AI-07(20240227)

数据库管理156期 2024-02-27 数据库管理-第156期 Oracle Vector DB & AI-07&#xff08;20240227&#xff09;1 Vector相关DDL操作可以在现有的表上新增vector数据类型的字段&#xff1a;可以删除包含vector数据类型的列&#xff1a;可以使用CTAS的方式&#xff0c;从其他有…

centos7系统crond 离线安装

CentOS 7的crond离线安装步骤如下&#xff1a; 下载cronie和crontabs的离线安装包。可以从rpmfind等网站下载与CentOS 7系统版本相匹配的cronie和crontabs离线安装包。 将下载的离线安装包传输到CentOS 7服务器上。 依次执行以下命令进行安装&#xff1a; 安装cronie&#…

【喜讯】优积科技获上海市室内装饰行业“装配式装修示范单位”

2023年12月29日下午&#xff0c;上海市室内装饰行业协会第九届第三次会员大会暨第五次理事会在金茂大厦隆重举行。上海市民政局社会团体管理处副处长姜琦、上海市经济和信息化委员会综合规划处副处长赵广君、上海市工经联党委副书记、执行副会长黄国伟等领导应邀出席会议。出席…

CSS3技巧37:JS+CSS3 制作旋转图片墙

开学了就好忙啊&#xff0c;Three.js 学习的进度很慢。。。 备课备课才是王道。 更一篇 JS CSS3 的内容&#xff0c;做一个图片墙。 其核心要点是把图片摆成这个样子&#xff1a; 看上去这个布局很复杂&#xff0c;其实很简单。其思路是&#xff1a; 所有图片放在一个 div.…

kubectl 声明式资源管理方式

目录 介绍 YAML 语法格式 命令 应用yaml文件指定的资源 删除yaml文件指定的资源 查看资源的yaml格式信息 查看yaml文件字段说明 查看 api 资源版本标签 修改yaml文件指定的资源 离线修改 在线修改 编写yaml文件 创建资源对象 查看创建的pod资源 创建service服务对…

07-Linux部署Nginx

Linux部署Nginx 简介 NGINX是一款高性能的HTTP和反向代理服务器&#xff0c;也是一个IMAP/POP3/SMTP代理服务器。它的特点包括占用内存少、并发能力强&#xff0c;因此在处理高负载和高并发的场景时表现优秀。NGINX由俄罗斯的程序设计师Igor Sysoev开发&#xff0c;最初是为俄…

Swagger3 使用详解

Swagger3 使用详解 一、简介1 引入依赖2 开启注解3 增加一个测试接口4 启动服务报错1.5 重新启动6 打开地址&#xff1a;http://localhost:8093/swagger-ui/index.html 二、Swagger的注解1.注解Api和ApiOperation2.注解ApiModel和ApiModelProperty3.注解ApiImplicitParams和Api…

如何在 Linux 上使用 dmesg 命令

文章目录 1. Overview2.ring buffer怎样工作&#xff1f;3.dmesg命令4.移除sudo需求5. 强制彩色输出6.使用人性化的时间戳7.使用dmesg的人性化可读时间戳8.观察实时event9.检索最后10条消息10.搜索特定术语11.使用Log Levels12.使用Facility Categories13.Combining Facility a…

【六袆-Golang】Golang:安装与配置Delve进行Go语言Debug调试

安装与配置Delve进行Go语言Debug调试 一、Delve简介二、win-安装Delve三、使用Delve调试Go程序[命令行的方式]四、使用Golang调试程序 Golang开发工具系列&#xff1a;安装与配置Delve进行Go语言Debug调试 摘要&#xff1a; 开发环境中安装和配置Delve&#xff0c;一个强大的G…

黑马程序员——接口测试——day03——Postman断言、关联、参数化

目录&#xff1a; Potman断言 Postman断言简介Postman常用断言 断言响应状态码断言包含某字符串断言JSON数据Postman断言工作原理Postman关联 简介实现步骤核心代码创建环境案例1案例2Postman参数化 简介数据文件简介编写数据文件 CSV文件JSON文件导入数据文件到postman读取数…

C语言-数据结构-顺序表

&#x1f308;个人主页: 会编辑的果子君 &#x1f4ab;个人格言:“成为自己未来的主人~” 目录 数据结构相关概念 顺序表 顺序表的概念和结构 线性表 顺序表分类 顺序表和数组的区别 顺序表分类 静态顺序表 动态顺序表 头插和尾插 尾插 数据结构相关概念 数据结构…

逆向案例二:关键字密文解密,自定义的加密解密。基于企名片科技的爬取。

import requests import execjsfor i in range(4):i i1url https://vipapi.qimingpian.cn/Activity/channelInformationByChannelNamedata {channel_name: 24新声,page: f{i},num: 20,unionid: W9wLD4rHIZrB3GLTUncmHgbZcEepR78xJa5Zit6XTMtata86DehdxDt/fDbcHeeJWqqIs6k…

Golang Redis:构建高效和可扩展的应用程序

利用Redis的闪电般的数据存储和Golang的无缝集成解锁协同效应 在当前的应用程序开发中&#xff0c;高效的数据存储和检索的必要性已经变得至关重要。Redis&#xff0c;作为一个闪电般快速的开源内存数据结构存储方案&#xff0c;为各种应用场景提供了可靠的解决方案。在这份完…

PHP请求示例获取淘宝商品详情数据API接口(按关键词搜索商品列表)

请求示例&#xff0c;API接口接入Anzexi58 item_get-获得淘宝商品详情 taobao.item_get 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥WeChat18305163218api_nameString是API接口名称&#xff08;包…

nodejs 实现pdf与图片互转

PDF转图片 效果图 代码 const path require(path); const pdf require(pdf-poppler); const fs require(fs); // PDF文件路径 const pdfFilePath ./path/test.pdf; // 转换选项 const opts { format: png, // 输出图片格式&#xff0c;可以是 jpeg, png, ppm…

东芝工控机维修东芝电脑PC机维修FA3100A

TOSHIBA东芝工控机维修电脑控制器PC机FA3100A MODEL8000 UF8A11M 日本东芝TOSHIBA IA controller维修SYU7209A 001 FXMC12/FXMC11;BV86R-T2GKR-DR7YF-8CPPY-4T3QD; CPU处理单元是可编程逻辑控制器的控制部分。它按照可编程逻辑控制器系统程序赋予的功能接收并存储从编程器键入…

组合模式(Composite Pattern)C++

上一节&#xff1a;桥接模式&#xff08;Bridge Pattern&#xff09; C 文章目录 0.理论1.目的与应用场景2.实现方式 1.实践 0.理论 组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;用于将对象组合成树形结构以表示“部分-整体”的层次结…

CodeSys中调用C语言写的动态库

文章目录 1.前言2.前期准备3.创建CodeSys库工程3.1.函数名必须包含_cext3.2.生成m4、c文件 4.搭建编译环境&#xff0c;编译出动态库*.so4.1.将ExtensionSDK文件夹拷贝到板子的一个目录中。4.2.创建工程目录&#xff0c;且将前面生成的m4、c文件拷贝到这个工程目录下4.3.执行ma…