最近在写的支付模块

news2024/9/24 5:31:21

最近再写支付模块就到处借鉴 旨在回顾一下。

1.确认订单功能

使用场景是:用户在选择好购物车后,或者是直接选择商品后(选择商品封装为购物车)

这样做是根据尚硅谷来学习的 目前需要这些属性,原因是在确认订单页面后 展现一个最优惠的状态 

1.1实体类

    /**
     * 用户id
     */
    @ApiModelProperty("用户id")
    private Integer userId;

    /**
     * 购物车列表
     */
    @ApiModelProperty("购物车中已选中商品")
    private List<CartInfo> cartItemsList;

    @ApiModelProperty("最优惠的优惠券id")
    private Integer userCouponsId;

    /**
     * 总金额
     */
    @ApiModelProperty("总金额")
    private Double totalAmount;

    /**
     * 优惠金额
     */
    @ApiModelProperty("优惠金额")
    private Double discount;

    /**
     * 实付金额
     */
    @ApiModelProperty("实付金额")
    private Double actuallyPay;

1.2确认订单实现类

期间做了一些修改 之前是设置的有购物车状态 这些步骤都是在后端处理 

后来又采用了前端传递购物车属性 美其名曰叫 减少io次数 缓解数据库压力

通过传入的userId 查找 订单列表 购物车列表

期间有个redis操作 是根据时间 来生成 后续在生成订单时会用到

 public OrderConfirmVo confirmOrder(CartConfirmDto cartConfirmDto) {
        //获取用户id参数 以方便后续使用
        //获取用户地址列表
        Integer userId = cartConfirmDto.getUserId();
        List<Addresses> addressesList = addressesDao.getByUserId(userId);
        //获取购物车中已经选中的商品
        List<CartInfo> cartItemsList = cartConfirmDto.getCartItemsList();
//        List<CartItems> cartItemsList = cartItemsDao.querySelectedCartItems(userId);
        if (cartItemsList.isEmpty()){
            throw new PorkException("您购物车中未选中商品",500);
        }
        for (CartInfo cartInfo : cartItemsList) {
            Integer productId = cartInfo.getProductId();
            Products products = productsDao.queryById(productId);
            cartInfo.setMainPhoto(products.getMainPhoto());
            cartInfo.setName(products.getName());
            Integer flavorId = cartInfo.getFlavorId();
            String flavorDescription = flavorsService.queryNameById(flavorId);
            cartInfo.setFlavorDescription(flavorDescription);
        }
        //生成订单唯一标示
        String orderNo = System.currentTimeMillis()+"";
        redisTemplate.opsForValue().set(RedisConst.ORDER_REPEAT+orderNo,orderNo,24, TimeUnit.HOURS);
        //1.获取最优惠优惠券
        //2.先获取订单价格
        //3.找到实付金额
//        Double totalPrice = cartItemsDao.getActuallyPay(userId);
//        UserCoupons userCoupon = userCouponsDao.queryOptimalUserCoupon(totalPrice, userId);
//        Double discount = userCoupon.getCoupons().getDiscount();
//        Double actuallyPay = totalPrice - discount;
        Double totalPrice = cartConfirmDto.getTotalAmount();
        Integer userCouponId = cartConfirmDto.getUserCouponsId();
        Double discount = cartConfirmDto.getDiscount();
        Double actuallyPay = cartConfirmDto.getActuallyPay();
        UserCoupons userCoupon = userCouponsDao.queryById(userCouponId);
        //查询可用优惠券
        List<UserCoupons> userCoupons = userCouponsDao.queryAvailableUserCoupons(totalPrice, userId);
        //进行封装
        OrderConfirmVo orderConfirmVo = new OrderConfirmVo(userId,totalPrice,userCoupon,discount,actuallyPay,orderNo,userCoupons,addressesList,cartItemsList);

        return orderConfirmVo;
    }

1.3返回类

    */
    @ApiModelProperty("用户id")
    private Integer userId;

    /**
     * 总金额
     */
    @ApiModelProperty("总金额")
    private Double totalAmount;

    @ApiModelProperty("最优惠的优惠券")
    private UserCoupons userCoupons;

    /**
     * 优惠金额
     */
    @ApiModelProperty("优惠金额")
    private Double discount;

    /**
     * 实付金额
     */
    @ApiModelProperty("实付金额")
    private Double actuallyPay;

    /**
     * 订单号
     */
    @ApiModelProperty("订单号")
    private String orderNo;

    /**
     * 用户所有优惠券
     */
    @ApiModelProperty("用户优惠券")
    private List<UserCoupons> userCouponsList;
    /**
     * 用户地址
     */
    @ApiModelProperty("用户地址列表")
    private List<Addresses> addressesList;

    /**
     * 购物车列表
     */
    @ApiModelProperty("购物车列表")
    private List<CartInfo> cartItemsList;

2.生成订单

2.1请求实体类

生成订单后里面的属性

 @ApiModelProperty(value = "使用预生产订单号防重")
    private String orderNo;

    @ApiModelProperty(value = "用户id")
    private Integer userId;

    @ApiModelProperty(value = "下单时所使用的地址信息")
    private Integer addressesId;

    @ApiModelProperty(value = "下单选中的优惠券id")
    private Integer userCouponId;

    @ApiModelProperty(value = "订单备注")
    private String comment;


    @ApiModelProperty(value = "所选中商品")
    private List<CartInfo> cartItemsList;

    @ApiModelProperty(value = "最后订单总价")
    private Double totalPrice;
    @ApiModelProperty(value = "优惠金额")
    private Double discount;
    @ApiModelProperty("订单实付金额")
    private Double ActuallyPay;

2.2生成订单方法实体类

使用lua脚本来保证原子性 

如果redis中有相同orderNo 则说明正常提交订单 然后把redis删除

期间也有锁单 

2.2.1检查锁

    @Override
    public Boolean checkAndLock(List<ProductStockVo> productStockVoList, String orderNo) {
        //1.判断productStockVoList是否为空
        if (CollectionUtils.isEmpty(productStockVoList)){
            throw new PorkException(ResultCodeEnum.DATA_ERROR);
        }
        //2.遍历productStockVoList得到每个商品,验证库存并锁定库存,具备原子性
        productStockVoList.stream().forEach(productStockVo -> {
            this.checkLock(productStockVo);
        });
        //3.只要有一个商品锁定失败,所有锁定成功的商品都解锁 用于检查流中是否至少有一个元素满足指定的条件
        boolean flag = productStockVoList.stream()
                .anyMatch(productStockVo -> !productStockVo.getIsLock());
        if (flag){
            //所有锁定成功的商品都解锁
            productStockVoList.stream().filter(ProductStockVo::getIsLock)
                    .forEach(productStockVo -> {
                        flavorsDao.unlockStock(productStockVo.getFlavorId(),productStockVo.getSkuNum());
                    });
            return false;
        }
//4 如果所有商品都锁定成功了,redis缓存相关数据,为了方便后面解锁和减库存
        redisTemplate.opsForValue()
                .set(RedisConst.SROCK_INFO+orderNo,productStockVoList,33, TimeUnit.MINUTES);
        return true;
    }

2.2.2获得公平锁

    private void checkLock(ProductStockVo productStockVo) {
        //获取锁 公平锁:谁等待时间长给谁发锁
        RLock rLock = this.redissonClient.getFairLock(RedisConst.SKUKEY_PREFIX+productStockVo.getFlavorId());
        rLock.lock();
        try {
            //验证库存
            Flavors flavors = flavorsDao.checkStock(productStockVo.getFlavorId(),productStockVo.getSkuNum());
            //判断没有满足条件商品,设置isLock值为false,返回
            if (flavors == null){
                productStockVo.setIsLock(false);
                return;
            }
            //又满足条件商品,锁定库存 update rows 影响行数
            Integer rows =  flavorsDao.lockStock(productStockVo.getFlavorId(),productStockVo.getSkuNum());
            if (rows == 1) {
                productStockVo.setIsLock(true);
            }
        }finally {
            //解锁
            rLock.unlock();
        }
    }

2.2.3提交订单 

  public OrderGenerateInfo submitOrder(OrderSubmitVo orderSubmitVo) {
        //第一步拿出userId确定给那个用户设置订单
        Integer userId = orderSubmitVo.getUserId();
        //第二步 订单不能重复提交,重复提交验证
        //通过redis + lua 脚本实现  //lua脚本保证原子性
        //1.获取传递过来的orderNo
        String orderNo = orderSubmitVo.getOrderNo();
        if (orderNo.isEmpty()){
            throw new PorkException(ResultCodeEnum.ILLEGAL_REQUEST);
        }
        //2.拿着orderNo到redis中查询   此lua脚本解析 如果redis中存在的值 = 这一个值 那么 这个值 , 不过没有存在 就返回0 然后结束
        String script = "if(redis.call('get', KEYS[1]) == ARGV[1]) then return redis.call('del', KEYS[1]) else return 0 end";
        //3.如果redis有相同orderNo,表示正常提交订单 ,把redis的orderNo删除
        Boolean flag = (Boolean) redisTemplate
                .execute(new DefaultRedisScript(script, Boolean.class),
                Arrays.asList(RedisConst.ORDER_REPEAT + orderNo),orderNo);
        //4.如果redis没有相同orderNo,表示重复提交了,不能再往后进行
        if (!flag){
            throw new PorkException(ResultCodeEnum.REPEAT_SUBMIT);
        }
        //第三步 验证库存 并且 锁定库存(订单在30分钟内锁定库存 没有真正减库存)
        //获取当前购物车商品
        List<CartInfo> cartItemsList = orderSubmitVo.getCartItemsList();
        //新建一个锁单Vo 然后把商品信息封装到 Vo里面
        if (!CollectionUtils.isEmpty(cartItemsList))
        {
           List<ProductStockVo> productStockVoList =
                   cartItemsList.stream().map(item ->{
                    ProductStockVo productStockVo = new ProductStockVo();
                    productStockVo.setFlavorId(item.getFlavorId());
                    productStockVo.setSkuNum(item.getQuantity());
                    return productStockVo;
                }).collect(Collectors.toList());
            //验证库存,保证具备原子性 解决超卖问题
            Boolean isLockSuccess = flavorsService.checkAndLock(productStockVoList, orderNo);
        if (!isLockSuccess){
            throw new PorkException(ResultCodeEnum.ORDER_STOCK_FALL);
        }
        }
        //第四步 下单过程
        OrderGenerateInfo orderGenerateInfo = this.saveOrder(orderSubmitVo);
        //对已生成订单的购物车进行删除
        List<Integer> cartIdList = cartItemsList.stream()
                .map(CartInfo::getId)
                .collect(Collectors.toList());
        cartItemsDao.deleteBatchIds(cartIdList);

        //1.向两张表中添加数据 order_info order_item

        //返回订单id
return orderGenerateInfo;
    }
  

2.2.4保存订单

  @Transactional(rollbackFor = {Exception.class})
    public OrderGenerateInfo saveOrder(OrderSubmitVo orderSubmitVo) {
        Integer userId = orderSubmitVo.getUserId();
        List<CartInfo> cartItemsList = orderSubmitVo.getCartItemsList();
        if (CollectionUtils.isEmpty(cartItemsList)){
            throw new PorkException(ResultCodeEnum.DATA_ERROR);
        }

        List<String> goodInfoList = new ArrayList<String>();
        String goodInfo = "";
        for (CartInfo cartInfo : cartItemsList) {
            Integer flavorId = cartInfo.getFlavorId();
            Integer productId = cartInfo.getProductId();
            Integer quantity = cartInfo.getQuantity();
            String productName = productsService.queryNameById(productId);
            String flavorName = flavorsService.queryNameById(flavorId);
            goodInfo = productName+":"+flavorName+"*"+quantity;
            goodInfoList.add(goodInfo);
        }
        //查数据 顾客收货地址
        Integer addressesId = orderSubmitVo.getAddressesId();
        Addresses addresses = addressesDao.queryById(addressesId);
        if (addresses == null){
            throw new PorkException(ResultCodeEnum.DATA_ERROR);
        }
        String recipientName = addresses.getRecipientName();
        String recipientPhone = addresses.getRecipientPhone();
        String province = addresses.getProvince();
        String city = addresses.getCity();
        String district = addresses.getDistrict();
        String detail = addresses.getDetail();
        String orderAddress = province + city + district + detail;
        //计算金额
        Double totalPrice = orderSubmitVo.getTotalPrice();
        Double discount = orderSubmitVo.getDiscount();
        Double actuallyPay = orderSubmitVo.getActuallyPay();
        //原金额
//        Double totalAmount = cartItemsDao.getActuallyPay(userId);
//        Double discount = 0.00;
//        Double actuallyPay = totalAmount;
//        Integer couponId = 0;
        Integer userCouponId = orderSubmitVo.getUserCouponId();
//        UserCoupons userCoupons = userCouponsDao.queryById(userCouponId);
        //把优惠券设置为已使用
        userCouponsDao.update(userCouponId);
//        if (userCoupons!=null){
//            couponId = userCoupons.getCouponId();
//        }


        //优惠券金额
//        if (userCouponId != null){
//            UserCoupons userCoupons = userCouponsDao.queryById(userCouponId);
//          couponId = userCoupons.getCouponId();
//             discount = couponsDao.queryById(couponId).getDiscount();
//        }
//        //实付金额
//        actuallyPay = totalPrice - discount;
        //封装订单项
        List<OrderItems> orderItemsList = new ArrayList<>();
        for (CartInfo cartItems : cartItemsList) {
            OrderItems orderItem = new OrderItems();
            orderItem.setProductId(cartItems.getProductId());
            orderItem.setFlavorId(cartItems.getFlavorId());
            orderItem.setQuantity(cartItems.getQuantity());
            orderItem.setPrice(cartItems.getPrice());
            orderItem.setStatus(0);
            orderItemsList.add(orderItem);
        }
        Orders order = new Orders();
        order.setUserId(userId);
        order.setTotalAmount(totalPrice);
        order.setStatus(0);
        order.setConsignee(recipientName);
        order.setPhone(recipientPhone);
        order.setAddress(orderAddress);
        order.setDiscount(discount);
        order.setOrderNo(orderSubmitVo.getOrderNo());
        order.setComment(orderSubmitVo.getComment());
        order.setActuallyPay(actuallyPay);
        order.setCouponId(userCouponId);
        order.setGoodInfo(String.join(", ", goodInfoList));
        //添加数据到订单基本表
        ordersDao.insert(order);

        //添加订单里面的订单项
        orderItemsList.forEach(orderItems -> {
            orderItems.setOrderId(order.getId());
            orderItemsDao.insert(orderItems);
        });

        //如果当前订单使用优惠券更新优惠券状态
        if (order.getCouponId()!= null){
            userCouponsDao.update(userCouponId);
        }
        //在redis中记录用户购物数量
        //hash类型   key(userId)  -  field(skuId)-value(skuNum)
        String orderSkuKey = RedisConst.ORDER_SKU_MAP + orderSubmitVo.getUserId();
        BoundHashOperations<String, String, Integer> hashOperations = redisTemplate.boundHashOps(orderSkuKey);
        cartItemsList.forEach(cartInfo -> {
            if(hashOperations.hasKey(cartInfo.getFlavorId().toString())) {
                Integer orderSkuNum = hashOperations.get(cartInfo.getFlavorId().toString()) + cartInfo.getQuantity();
                hashOperations.put(cartInfo.getFlavorId().toString(), orderSkuNum);
            }
        });
        redisTemplate.expire(orderSkuKey, DateUtil.getCurrentExpireTimes(), TimeUnit.SECONDS);
        //设置订单过期时间 30分钟后取消订单
        long orderTimeOut = 1;
        String keyRedis = String.valueOf(StrUtil.format("{}:{}",RedisConst.REDIS_ORDER_KEY_IS_PAY_0,order.getId()));
        //设置过期时间
        redisTemplate.opsForValue().set(keyRedis,order.getOrderNo(),orderTimeOut,TimeUnit.MINUTES);
        //订单id
        OrderGenerateInfo orderGenerateInfo  = new OrderGenerateInfo(order.getId(),orderTimeOut);
        return orderGenerateInfo;
    }

3.讲讲Redis过期键监听器

redis过期键监听器 实现对键的监听 

如果该键过期了,则进行注册过的操作

3.1配置监听器

像只注册了订单服务的话 你就只能使用订单服务 

若使用其他服务的话 也要进行集成

@Configuration
@AllArgsConstructor
public class RedisListenerConfig {

	private final RedisTemplate<String, String> redisTemplate;
	private final RedissonConfig redisConfigProperties;
	private final OrdersService ordersService;

//	private final OrderItemsService orderItemsService;

	@Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {

		RedisMessageListenerContainer container = new RedisMessageListenerContainer();
		container.setConnectionFactory(connectionFactory);
		container.addMessageListener(new RedisKeyExpirationListener(redisTemplate, redisConfigProperties, ordersService), new PatternTopic(StrUtil.format("__keyevent@{}__:expired", redisConfigProperties.getDatabase())));
		return container;
	}
}

3.2配置redis 开启监听器

3.3写监听器

@Component
public class RedisKeyExpirationListener implements MessageListener {

    private RedisTemplate<String, String> redisTemplate;
    private RedissonConfig redisConfigProperties;

    private OrdersService ordersService;

//    private OrderItemsService orderItemsService;

    public RedisKeyExpirationListener(RedisTemplate<String, String> redisTemplate,
                                      RedissonConfig redisConfigProperties,
                                      OrdersService orderInfoService
                                     ){
        this.redisTemplate = redisTemplate;
        this.redisConfigProperties = redisConfigProperties;
        this.ordersService = orderInfoService;
//        this.orderItemsService = orderItemsService;
    }
    @Override
    public void onMessage(Message message, byte[] bytes) {
        RedisSerializer<?> serializer = redisTemplate.getValueSerializer();
        String channel = String.valueOf(serializer.deserialize(message.getChannel()));
        String body = String.valueOf(serializer.deserialize(message.getBody()));
        //key过期监听
        if(StrUtil.format("__keyevent@{}__:expired", redisConfigProperties.getDatabase()).equals(channel)){
            //订单自动取消
            if(body.contains(RedisConst.REDIS_ORDER_KEY_IS_PAY_0)) {
                body = body.replace(RedisConst.REDIS_ORDER_KEY_IS_PAY_0, "");
                String[] str = body.split(":");
                String wxOrderId = str[1];
                System.out.println(wxOrderId);
                Orders orders = ordersService.queryById(Integer.valueOf(wxOrderId));
                if(orders != null && orders.getStatus() == 0){//只有待支付的订单能取消
                    //TODO 订单取消 库存增加 减优惠券
//                    orderItemsService.toCancel(orders.getId());
                    ordersService.cancelOrder(orders.getId());
                    System.out.println("订单id:"+orders.getId()+"已删除");
                }
            }

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

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

相关文章

如何采集淘宝商品评论?

采集商品评论对于企业和消费者都至关重要。它不仅帮助企业了解产品优势与不足&#xff0c;指导产品改进和市场策略调整&#xff0c;还能通过积极回应顾客反馈增强品牌忠诚度。对消费者而言&#xff0c;真实客观的评价是决策的重要参考&#xff0c;有助于避开潜在问题&#xff0…

Apache Tomcat 7下载、安装、环境变量配置 详细教程

Apache Tomcat 7下载、安装、环境变量配置 详细教程 Apache Tomcat 7下载Apache Tomcat 7 安装Apache Tomcat 7 环境变量配置启动 Apache Tomcat 7测试Tomcat7是否启动成功 Apache Tomcat 7下载 1、下载地址&#xff0c;找到Archives 链接: 官网下载地址 2、找到Tomcat 7&…

Linux查看系统线程数

Linux查看系统线程数 查看线程数查看进程内的线程统计线程数 查看线程数 想要查看Linux操作系统允许的最大线程数&#xff0c;可以通过命令 ulimit -a返回配置项的详细说明&#xff1a; # core文件的最大值为100blocks core file size (blocks, -c) 0# 进程的数…

[区间概率预测]CNN-BiLSTM-Attention-ABKDE多变量时序预测 基于改进自适应核密度估计实现区间预测

[区间概率预测]CNN-BiLSTM-Attention-ABKDE多变量时序预测 基于改进自适应核密度估计实现区间预测 【原创区间概率预测】CNN-BiLSTM-Attention-ABKDE多变量时序预测 基于卷积神经网络-双向长短期记忆神经网络-注意力机制结合自适应带宽核函数密度估计的多变量时序预测【点预测…

【51单片机仿真】基于51单片机设计的温度检测与高低温报警系统仿真源码设计文档演示视频——文末资料下载

基于51单片机设计的温度检测与高低温报警系统仿真设计 演示视频 基于51单片机设计的温度检测与高低温报警系统仿真 系统功能简介 1、实时温度测量&#xff0c;可调整温度值 2、显示测量的温度值&#xff0c;按键切换可查看高温和低温报警值 3、可通过按键输入报警最高值以及最…

8/8总结

1.三分 | 函数 虽然提示很明显了&#xff0c;但是还是没掌握套路&#xff0c;看了题解才会的&#xff0c;估计也有四分&#xff0c;就是三次方的形式。 例子&#xff1a; 2 1 2 0 0 2 2 0 0 2 -4 2AC: #include<bits/stdc.h> using namespace std; const int maxn1001…

动态规划(一)

目录 &#xff08;一&#xff09;递归到动规的一般转化方法 &#xff08;二&#xff09;动规解题的一般思路 1. 将原问题分解为子问题 2. 确定状态 3. 确定一些初始状态&#xff08;边界状态&#xff09;的值 4. 确定状态转移方程 &#xff08;三&#xff09;能用动规解…

【Android Studio】Webview 内核升级得三种方法

【Android Studio】Webview 内核升级得三种方法 前言X5 腾讯组件crosswalk开源项目webview升级加载的内核&#xff08;完美解决&#xff09;总结 前言 在APP 中进行网页加载&#xff0c;一般采用原生自带的Webview 组件&#xff0c;但在需要加载高版本网页的时候&#xff0c;有…

工业三防平板助力MES系统打造工厂移动式生产管理

随着工业4.0时代的到来&#xff0c;智能制造、数字化车间等概念层出不穷&#xff0c;生产过程的可视化管理也成为了企业提升效率、优化生产的关键。而工业三防平板&#xff0c;凭借其坚固耐用、功能强大、便携易用等特性&#xff0c;成为了实现生产过程可视化管理的重要利器&am…

SQL注入实例(sqli-labs/less-21)

与第20关无异&#xff0c;只多了一步base64加密 0、初始页面 1、确定闭合字符 2、爆库名 3、爆表名 4、爆列名 5、查询最终目标

POS刷卡开发源码之语音播报-CyberWinApp-SAAS 本地化及未来之窗行业应用跨平台架构

一、终端语音提醒的好处 1. 增强信息传递的有效性&#xff1a;在人们忙碌或者注意力分散时&#xff0c;语音提醒能够直接穿透噪音和干扰&#xff0c;确保重要信息被准确接收。 2. 提高操作的便捷性&#xff1a;用户无需停下手中的工作去查看屏幕或阅读文字&#xff0c;直接通过…

算法——动态规划:0/1 背包问题

文章目录 一、问题描述二、解决方案1. DP 状态的设计2. 状态转移方程3. 算法复杂度4. 举例5. 实现6. 滚动数组6.1 两行实现6.2 单行实现6.3 优缺点 三、总结 一、问题描述 问题的抽象&#xff1a;给定 n n n 种物品和一个背包&#xff0c;第 i i i 个物品的体积为 c i c_i …

NET8中WebAPI使用JWT入门教程

目录 1、JWT2、具体实现3、代码下载 1、JWT 现在在各类API的开发中&#xff0c;token已经是必备了。例如&#xff1a;微信公众号开发中&#xff0c;第一个方法就是获取token。JWT具体的定义及组成部分大家可以到网上找找&#xff0c;这儿给一个简单的描述&#xff1a;JWT 令牌…

yaml语法+yaml配置文件

yaml语法 k:(空格)v > 表示一对键值对空格必须有 yaml拥有严格的空格缩进格式控制&#xff0c;以空格的缩进来控制层级关系&#xff1b;只要是左对齐的一列数据&#xff0c;都是同一个层级的 spring:thymeleaf:cache: true# 检查模板是否存在&#xff0c;然后再呈现check…

通义灵码-阿里云推出的AI智能编码助手

通义灵码体验地址 标题通义灵码是什么&#xff1f; 通义灵码是由阿里巴巴推出的基于通义大模型的智能编码辅助工具&#xff0c;提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码注释生成、代码解释、研发智能问答、异常报错排查等能力&#xff0c;并针对阿里云…

Bug 解决 | 前端无法正确请求后端接口并得到响应?

目录 1、配置问题 2、代码问题 3、网络问题 前端请求后端接口发现得到的响应不对&#xff0c;或者通过 f12 明明看到了后端的响应&#xff0c;但是前端页面无法正常的展示出来。 这种情况该怎么排查呢&#xff1f;这篇我们就来好好的理一理&#xff01; 1、配置问题 1&am…

浅谈取样器插件之jp@gc - UDP Request

浅谈取样器插件之jpgc - UDP Request JPgc - UDP Request允许用户在性能测试中发送UDP&#xff08;User Datagram Protocol&#xff09;数据包。这对于测试那些依赖UDP协议进行通信的应用程序和服务特别有用&#xff0c;比如某些物联网&#xff08;IoT&#xff09;设备、在线游…

我在高职教STM32——I2C通信入门(2)

大家好,我是老耿,高职青椒一枚,一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次,同行应该都懂的,老师在课堂上教学几乎是没什么成就感的。正是如此,才有了借助CSDN平台寻求认同感和成就感的想法。在这里,我准备陆续把自己花了很多心思设计的教学课件分…

QT输入组、QT显示组

目录 QT输入组 ​编辑 Combo Box&#xff08;下拉菜单部件&#xff09; Font Combo Box&#xff08;显示系统中可用的字体&#xff09; Line Edit&#xff08;行编辑器&#xff09; Text Edit&#xff08;文本编辑器&#xff09; Plain Text Edit&#xff08;纯文本编辑…

干货实操分享:6个禁用外来u盘的方法

禁用外来U盘是保护计算机系统和数据安全的重要措施之一。以下是六个禁用外来U盘的方法&#xff0c;旨在帮助您有效防止未经授权的U盘接入计算机&#xff1a; 1. 使用组策略编辑器&#xff08;Windows系统&#xff09; 步骤&#xff1a; 打开“运行”对话框&#xff0c;输入g…