后端微服务项目中出现的问题整理2022年11月

news2024/11/25 14:38:28

后端微服务项目中出现的问题整理2022年11月

  • 后端微服务项目中出现的问题整理2022年11月
    • 1.SpringBoot-Mail-Service(Spring邮箱服务)
      • 报错截图
      • 解决办法
        • 方法一:使用`@Resource`注解
        • 方法二:添加`(required=false)`
      • @Resource和@Autowired区别
    • 2.反射无法获取子类继承到的父类中的属性
      • 继承关系
        • 1.顶层Entity:BasicEntity
        • 2.子类:UserEntity
      • 原因说明
      • 解决
        • TimeMetaHandler时间填充策略类
    • 3.关于如何使用异步编排+Spring全局线程池
      • 1.构建全局线程池
      • 2.Service中引入全局线程池
      • 3.CompleteFuture使用全局线程池
    • 4.异步编排中return导致的后续任务接受值类型错误
      • 解决
        • 构建全局异常处理类

后端微服务项目中出现的问题整理2022年11月

1.SpringBoot-Mail-Service(Spring邮箱服务)

在使用Spring邮箱服务时发现@Autowired注入JavaMailSenderImpl的时候报错显示无法自动装配。找不到 ‘JavaMailSenderImpl’ 类型的 Bean。,当时自己直接解决了,但是还是想想整理一下

报错截图

在这里插入图片描述

解决办法

方法一:使用@Resource注解

@Resource
private JavaMailSenderImpl mailSender;

方法二:添加(required=false)

    @Autowired(required = false)
    private JavaMailSenderImpl mailSender;

@Resource和@Autowired区别

1、 @Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。

2、 @Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用

3、@Resource(这个注解属于J2EE的),默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入

来源:@Qgchun. javamailsenderimpl注入爆红

2.反射无法获取子类继承到的父类中的属性

使用反射的getDeclaredField方法只能获取到当前类中的属性无法获取到其父类中继承而来的属性所以会报noSuchFieldException
如下图:
我在最后这一环处理上出现了这个问题
在这里插入图片描述

即如下两行:

final Field createTime = autoFillObjectClass.getDeclaredField("createTime");
final Field updateTime = autoFillObjectClass.getDeclaredField("updateTime");

继承关系

1.顶层Entity:BasicEntity

顶层声明:createTime,updateTime和deleted三个通用属性

package cn.fly.commons.entity.common;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

/**
 * @author Syf200208161018
 * @date 2022/11/19 7:38
 * @ClassName:BasicEntity
 * @Effect:BasicEntity is used for basic entity
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BasicEntity {
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    public LocalDateTime createTime;
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    public LocalDateTime updateTime;
    @TableField(value = "deleted")
    public boolean deleted;
}

2.子类:UserEntity

子类中直接去继承顶层的BasicEntity

package cn.fly.commons.entity.common;

import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

/**
 * @author Syf200208161018
 * @date 2022/10/23 18:55
 * @ClassName:User
 * @Effect:User is used to user entity
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("user")
public class User extends BasicEntity{
    @TableId(value = "user_id",type = IdType.ASSIGN_ID)
    private Long userId;
    @TableField(value = "username")
    private String username;
    @TableField(value = "password")
    private String password;
    @TableField(value = "nickname")
    private String nickname;
    @TableField(value = "email")
    private String email;
}

原因说明

因为UserEntity继承了BasicEntity获取了createTime,updateTime属性但是反射的getDeclaredField无法获取父类中继承而来的属性所以出现无属性异常

解决

使用final Field[] fields = autoFillObjectClass.getFields();方法将所有的属性获取到,这个方法可以获取继承到的属性,但是继承的属性必须设置成public关键字修饰的

完整代码如下:

TimeMetaHandler时间填充策略类

package cn.fly.commons.handler.meta;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.stream.Stream;

/**
 * @author Syf200208161018
 * @date 2022/10/27 13:46
 * @ClassName:TimeMetaHandler
 * @Effect:TimeMetaHandler is used for 进行类中的创建时间和更新时间的填充代替Mybatis-plus的默认填充策略
 */
public class TimeMetaHandler {
    public static <T> T createTimeHandler(T autoFillObject) throws NoSuchFieldException, IllegalAccessException {
        final Class<?> autoFillObjectClass = autoFillObject.getClass();
        //获取属性上的注解,判断是否携带@TableField(value = "create_time" , fill = FieldFill.INSERT)
        final Field createTime = autoFillObjectClass.getDeclaredField("createTime");
        final FieldFill fill = createTime.getAnnotation(TableField.class).fill();
        if (FieldFill.INSERT.equals(fill)) {
            createTime.setAccessible(true);
            createTime.set(autoFillObject, LocalDateTime.now());
        }
        return autoFillObject;
    }

    public static <T> T updateTimeHandler(T autoFillObject) throws NoSuchFieldException, IllegalAccessException {
        final Class<?> autoFillObjectClass = autoFillObject.getClass();
        //find @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
        final Field updateTime = autoFillObjectClass.getDeclaredField("updateTime");
        final FieldFill fill = updateTime.getAnnotation(TableField.class).fill();
        if (FieldFill.INSERT_UPDATE.equals(fill)) {
            updateTime.setAccessible(true);
            updateTime.set(autoFillObject, LocalDateTime.now());
        }
        return autoFillObject;
    }

    /**
     * if you wanna unified insert createTime and updateTime you can use this
     *
     * @param autoFillObject
     * @param <T>
     * @return
     * @throws NoSuchFieldException
     */
    public static <T> T unifiedTimeHandler(T autoFillObject) throws NoSuchFieldException, IllegalAccessException {
        final Class<?> autoFillObjectClass = autoFillObject.getClass();
//        final Field createTime = autoFillObjectClass.getDeclaredField("createTime");
//        final Field updateTime = autoFillObjectClass.getDeclaredField("updateTime");
        Field createTime = null;
        Field updateTime = null;
        final Field[] fields = autoFillObjectClass.getFields();
        for (Field field : fields) {
            if (field.getName()=="createTime") {
                createTime = field;
            }
            if (field.getName()=="updateTime") {
                updateTime = field;
            }
        }
        final FieldFill createFill = createTime.getAnnotation(TableField.class).fill();
        final FieldFill updateFill = updateTime.getAnnotation(TableField.class).fill();
        if (FieldFill.INSERT.equals(createFill) && FieldFill.INSERT_UPDATE.equals(updateFill)) {
            createTime.setAccessible(true);
            updateTime.setAccessible(true);
            createTime.set(autoFillObject, LocalDateTime.now());
            updateTime.set(autoFillObject, LocalDateTime.now());
        }
        return autoFillObject;
    }
}

3.关于如何使用异步编排+Spring全局线程池

我们之前常常使用Spring框架的全局线程池+@Async注解实现异步任务,但是如果大家接触到异步编排的话其实能意识到这样的方法一定是没有异步编排做起来灵活易于控制的,所以我们自然想到异步编排结合全局线程池

1.构建全局线程池

一般我喜欢将全局线程池放置到commons模块中,构建如下:
我们使用ThreadPoolTaskExecutor对于线程池进行构建

/**
 * @author Syf200208161018
 * @date 2022/11/28 16:07
 * @ClassName:GlobalThreadPoolExecutor
 * @Effect:GlobalThreadPoolExecutor is used for 全局线程池
 */
@Configuration
public class GlobalThreadPoolExecutor {
    @Bean
    public ThreadPoolTaskExecutor globalThreadPool(){
        final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //设置核心线程数量
        executor.setCorePoolSize(3);
        //设置最大线程数
        executor.setMaxPoolSize(5);
        //设置队列中的最大可存储数量
        executor.setQueueCapacity(10);
        //设置线程名称前缀
        executor.setThreadNamePrefix("eprop-");
        //设置rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
        // 对拒绝task的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //加载
        executor.initialize();
        return executor;
    }
}

2.Service中引入全局线程池

如下使用@Resource注解即可引入

@Resource
    private ThreadPoolTaskExecutor globalThreadPoolExecutor;

3.CompleteFuture使用全局线程池

CompletableFuture.supplyAsync(() -> {
	//业务代码
}),globalThreadPoolExecutor);

4.异步编排中return导致的后续任务接受值类型错误

我们在使用异步编排的时候当发生有个地方需要return直接结束的使用其实就会引发这个问题
错误如下:

 //异步编排-----------------------------------------------------
            final CompletableFuture<Serializable> thread1 = CompletableFuture.supplyAsync(() -> {
                //获取当前用户的Team信息
                final Team res = epropTeamClient.getTeamByUserId(userId);
                //判断res返回值是否为空
                if (Objects.isNull(res)) {
                    return ResultJSONData.fail(ErrorCode.GET_TEAMINFO_FAIL.getCode(), SuccessMsg.GET_TEAMINFO_SUCCESS.getMsg());
                }
                //转换Team-->TeamMemberInfoBO
                return TeamConvertor.INSTANCE.convertTeamToTeamMemberInfoBO(res);
            }, globalThreadPoolExecutor).thenApply(res->{
                //获取到TeamId后进入TeamUser和TeamUserAuth两个表中进行查询
                //通过TeamId找到所有的团队成员id
                final List<TeamUser> teamMemberIdList = epropTeamClient.getTeamMemberIdList();
                final List<TeamUserInfoDTO> teamUserInfoDTOS = TeamConvertor.INSTANCE.convertTeamUserToTeamUserInfoDTO(teamMemberIdList);
                return teamUserInfoDTOS;
            });

我们可以看到在第一个任务中判断到res为空的时候就会做一个return,但是就是因为这个操作,导致我们后面的任务发生了问题,请看截图:
这里明显发现第二个任务的接收的参数的类型出现了问题,这就是return导致的,只要把return语句去除就会正常了!
在这里插入图片描述

解决

但是如何解决这个问题呢?
我们首先要记得大家尽量不要在CompletableFuture的线程任务中写return的业务语句(指的是结束整个异步编排结束返回)
然后我们要知道CompletableFuture中遇到异常会激发exceptionally方法,所以我们的处理应该是在最后加上如下语句:

.exceptionally(e->{
                e.printStackTrace();
                return null;
            });

完整代码:

final CompletableFuture<TeamMemberInfoBO> thread1 = CompletableFuture.supplyAsync(() -> {
                //获取当前用户的Team信息
                final Team res = epropTeamClient.getTeamByUserId(userId);
                //判断res返回值是否为空
                if (Objects.isNull(res)) {
                    Thread.currentThread().interrupt();
                    if (Thread.currentThread().isInterrupted()) {
                        throw new ThreadActivelyStopException(ErrorCode.GET_TEAMINFO_FAIL);
//                        return ResultJSONData.fail(ErrorCode.GET_TEAMINFO_FAIL.getCode(), SuccessMsg.GET_TEAMINFO_SUCCESS.getMsg());
                    }
                }
                //转换Team-->TeamMemberInfoBO
                final TeamMemberInfoBO teamMemberInfoBO = TeamConvertor.INSTANCE.convertTeamToTeamMemberInfoBO(res);
                //获取到TeamId后进入TeamUser和TeamUserAuth两个表中进行查询
                //通过TeamId找到所有的团队成员id
                final List<TeamUser> teamMemberIdList = epropTeamClient.getTeamMemberIdList(teamMemberInfoBO.getTeamId());
                final List<TeamUserInfoDTO> teamUserInfoDTOS = TeamConvertor.INSTANCE.convertTeamUserToTeamUserInfoDTO(teamMemberIdList);
                //通过UserId获取到用户信息
                for (TeamUserInfoDTO re : teamUserInfoDTOS) {
                    User memberInfo = userClient.getUserInfo(String.valueOf(re.getUserId()));
                    re.setUsername(memberInfo.getUsername());
                    teamMemberInfoBO.getTeamMemberList().add(re);
                }
                return teamMemberInfoBO;
            }, globalThreadPoolExecutor).thenApply((res) -> {
                //获取团队成员身份信息
                for (TeamUserInfoDTO dto : res.getTeamMemberList()) {
                    final List<TeamUserAuth> resList = epropTeamClient.getTeamUserAuthInfo(res.getTeamId(), dto.getUserId());
                    //若user_auth是0则是项目经理
                    for (TeamUserAuth teamUserAuth : resList) {
                        if(teamUserAuth.getUserAuth()==0){
                            res.setTeamLeader(dto.getUsername());
                        }
                    }
                    //转换
                    final List<TeamUserAuthDTO> teamUserAuthDTOS = TeamConvertor.INSTANCE.convertTeamUserAuthTODTO(resList);
                    dto.setAuthList(teamUserAuthDTOS);
                }
                return res;
            }).exceptionally(e->{
                e.printStackTrace();
                return null;
            });

这样的话当发现有异常的时候就会直接返回null了,也不会影响正常的返回

构建全局异常处理类

这里我们要说一下,我的异步编排跟Feign一起使用,所以也就是子模块业务出现错误会在子模块中报错,同时回到夫模块这里会显示Feign的调用模块错误500,这就表示我们的异步编排中出现了这个错误,我们就可以通过全局异常处理来抓取进行特殊的处理,但是整个项目里我并没有这样做,因为从逻辑上我返回了null其实已经是说明查不到这个数据了,但是在这里我还是要给大家扩展一下这个全局异常处理
以下是一个简单的示例:

/**
 * @author Syf200208161018
 * @date 2022/11/30 22:37
 * @ClassName:ThreadActivelyStopExceptionHandler
 * @Effect:ThreadActivelyStopExceptionHandler is used for
 */
@ControllerAdvice(annotations = {RestController.class})
@ResponseBody
public class ThreadActivelyStopExceptionHandler {

    @ExceptionHandler({ThreadActivelyStopException.class})
    public ResultJSONData handleException(ThreadActivelyStopException e){
        return ResultJSONData.fail(e.getErrorCode().getCode(),e.getErrorCode().getMsg());
    }
    @ExceptionHandler({NullPointerException.class})
    public ResultJSONData handleNullPointException(){
        return ResultJSONData.fail(ErrorCode.NULL_POINT_EXCEPTION_FAIL.getCode(),ErrorCode.NULL_POINT_EXCEPTION_FAIL.getMsg());
    }
}

我们使用@RestControllerAdvice扫描到对应注解所含有的方法,当出现错误的时候就会抓取到进行处理,这个处理大家就自由发挥了

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

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

相关文章

基于plc的自动洗碗机的设计(西门子)

目 录 摘 要 I Abstract II 1绪论 1 1.1全自动洗碗机的发展 1 1.2全自动洗碗机概述 2 1.2.1 全自动洗碗机的分类 2 1.2.2 全自动洗碗机的基本结构 3 1.2.3 全自动洗碗机的工作原理 4 1.3研究主要内容 4 2 全自动洗碗机机械设计 6 2.1 整体方案设计 6 2.2 各重要部件设计 6 2.2.…

TF-IDF

2.TF - IDF&#xff1a;作用&#xff1a;提取出来一句话中词的重要性&#xff0c;分成两个部分&#xff1a; tf: 词频(某一类中词条出现的次数 / 该类中所有词条数目) idf: 逆文档频率&#xff08;作用&#xff1a;去掉逗号&#xff0c;的等&#xff09;公式&#xff1a;idf l…

【第一阶段:java基础】第8章:面向对象编程高级-2(P394-P423)final、抽象类、接口、内部类

本系列博客是韩顺平老师java基础课的课程笔记&#xff0c;吐血推荐的一套全网最细java教程&#xff0c;获益匪浅 韩顺平java课程 目录&#xff08;P394-P423&#xff09; 1 final 2 抽象类 3 接口 4 内部类 1️⃣ 局部内部类 2️⃣&#x1f353;匿名内部类 3️⃣成员内部类 4️…

C++,顺序结构,选择结构,循环结构

目录 1.选择结构 1.1if语句 1.1.1单行if语句 1.1.2多行格式的if语句 1.1.3多条件if语句 1.1.4嵌套if语句 1.2三目运算符 1.3switch语句 2.循环结构 2.1while循环 2.2do..while语句 2.3for循环语句 2.4嵌套循环 3.跳转语句 3.1.1break 3.1.2continue 3.1.3goto语句 …

UDP-GlcNAc,UDPAG,尿苷二磷酸-N-乙酰基葡萄糖胺,UDP-N-乙酰葡糖胺

产品名称&#xff1a;UDP-GlcNAc 尿苷二磷酸-N-乙酰基葡萄糖胺&#xff0c;UDPAG&#xff0c;UDP-N-乙酰葡糖胺 别 名&#xff1a;5-二磷酸尿嘧啶核苷-N-乙酰半乳糖胺二钠盐;5′-二磷酸尿嘧啶核苷-N-乙酰半乳糖胺二钠盐 英文名&#xff1a;uridine 5-diphospho-N-acetyl-*g…

在家做副业可以做什么,做自媒体应该选择什么平台

今天分享五个&#xff0c;即使你在家里没有收入&#xff0c;自己就可以做的自媒体副业&#xff0c;给自己带来一些收益。 ​ 第一个自媒体副业是公众号&#xff0c;很多人多人都知道。很多人也喜欢看别人写的公众号。 其实微信官方账号注册很简单&#xff0c;不需要花钱有个邮…

Huggingface Transformers各类库介绍(Tokenizer、Pipeline)

目录前言0、transformers的安装以及介绍0-1、 介绍0-2、安装一、分词——transformers.AutoTokenizer1-0、相关参数介绍&#xff08;常用参数介绍&#xff09;1-1、加载、保存1-2、使用以及原理二、黑盒子——transformers.pipeline2-0、pipeline怎么理解&#xff1f;2-1、目前…

SpringCloud:Gateway之限流、熔断

目录 一、服务雪崩简介及压测实践演示 ​编辑 二、sentinel简单模式之流控QPS案例 什么是Sentinel ​ 安装Sentinel控制台 三、sentinel流控简单模式之并发线程数案例 四、sentinel流控之关联模式&链路模式 关联模式 链路模式 五、sentinel降级之平均响应时间&…

Mybatis入门

详细的Mybatis介绍/使用&#xff0c;可以访问&#xff1a; 地址&#xff1a;mybatis – MyBatis 3 | 简介 目录 一、Mybatis介绍 二、依赖 三、什么是rowmapper 四、Mybatis demo 演示 4.1 背景 4.2 JDBC执行sql的流程 &Mybatis 关键要素 4.3 项目的整体结构&…

kubernetes 实战学习

文章目录kubernetes 实战学习1. 资源创建方式2. Namespace3. Pod3.1 使用命令行创建一个 Pod3.2 使用 YAML 文件创建一个 pod3.3 查看 pod 日志3.4 查看 pod IP3.5 进入 pod 查看信息3.6 一个 pod 里同时运行多个容器3.7 pod 和宿主机之间文件拷贝4. Deployment4.1 deployment …

功能测试(一)—— web项目环境与测试流程、业务流程测试

目录 目标 一、web项目环境说明 【了解】 ​编辑 1.1 环境的定义 1.2 环境(服务器)的组成 1.3 面试题&#xff1a;你们公司有几套环境&#xff1f; 二、熟悉商城项目 【了解】 2.1 商城项目的核心业务 2.2 商城项目的核心功能模块 三、测试流程的应用 【重点】 3.1 需…

Java 基础数据类型占用内存空间和字符串编码简介(二)

Java 基础数据类型占用内存空间简介一 计算机简介1.基本概念2.CPU 三级缓存3.本机参数查看二 数据占用内存情况1.多线程Demo2.结果解析1.直接计算2.volatile 计算3.缓存行填充一 计算机简介 结合多线程计算机的硬件&#xff0c;从侧面理解数据存储如何影响我们的程序 1.基本概…

数据结构学习笔记(Ⅶ):查找

目录 1 查找 1.1 定义 1.2 查找操作 1.3 算法评价指标 2 查找算法 2.1 顺序查找 1.算法思想 2.实现 3.查找效率 4.算法优化 2.2 折半查找 1.算法思想 2.算法实现 3.查找判定树 4.折半查找效率 2.3 分块查找 1.算法思想 2.查找效率分析 3 B树 3.1 B树概念 3…

Java#30(扩展知识:可变参数与Collections)

目录 一.可变参数 二.Collections 1.Collections常用的API 一.可变参数 本质: 可变参数本质上是一个数组 作用: 在形参中接收多个数据 格式: 数据类型...参数名称 例如: int...a 代码示范: package Demo;public class Test {public static void main(String[] args) {int s…

单目标优化:蜣螂优化算法(Dung beetle optimizer,DBO)

蜣螂优化算法&#xff08;Dung beetle optimizer&#xff0c;DBO&#xff09;由Jiankai Xue和Bo Shen于2022年提出&#xff0c;该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁殖行为的启发所得。 一、蜣螂优化算法 1.1蜣螂滚球 &#xff08;1&#xff09;当蜣螂前行无障碍时…

redis基础3——配置文件核心参数实测+RDB持久化、AOF持久化核心参数详解

文章目录一、redis.conf配置文件详解1.1 查看配置文件位置1.2 启动需指定配置文件1.3 单位大小写不敏感1.4 引用其他配置文件&#xff08;包含&#xff09;1.4.1 测试参数存放前后位置1.4.1.1 反例1.4.1.2 正例1.4.2 测试引用参数有效性1.5 网络相关1.5.1 绑定IP1.5.2 保护模式…

全球领先飞瞳引擎™云服务全球两千+企业用户,集装箱识别集装箱箱况残损检测,正常箱号识别率99.98%以上,箱信息识别及铅封识别免费

全球领先飞瞳引擎™AI集装箱识别检测云服务全球两千企业用户&#xff0c;集装箱识别集装箱箱况残损检测&#xff0c;正常箱号识别率99.98%以上&#xff0c;箱信息识别及铅封识别免费。CIMCAI中集飞瞳是全球应用落地最广&#xff0c;规模最大&#xff0c;最先进的的港航人工智能…

链游新发展方向:告别高强度打金,回归游戏本质

2022 年伊始&#xff0c;加密领域最瞩目的项目要属区块链游戏了。随着 Axie Infinity、Genopets 和 Perion 等公司大获成功&#xff0c;区块链游戏生态系统逐渐进入主流圈。值得一提的是&#xff0c;游戏和 NFT 这两个备受关注的类别在 Web 3 世界中互相成就&#xff0c;创造出…

【简单总结】SLAM 算法的 Benchmark 及相关数据集的结果对比

前言与参考 主要是copy一下总结&#xff0c;方便自己后续找方案特定使用&#xff0c;所有的出处均在标题处和原链接跳转&#xff0c;此处仅做各个benchmark收集使用&#xff0c;如果有原作者觉得侵权&#xff0c;请联系我 将全力配合相关内容和链接删除 如果网友有其他更新的…

代码随想录刷题day51 309.最佳买卖股票时机含冷冻期;714.买卖股票的最佳时机含手续费

代码随想录刷题day51 309.最佳买卖股票时机含冷冻期&#xff1b;714.买卖股票的最佳时机含手续费 股票买卖&#xff0c;前两天的有点忘了正好也复习一下。 309.最佳买卖股票时机含冷冻期 309. 最佳买卖股票时机含冷冻期 - 力扣&#xff08;Leetcode&#xff09; 不是很好优…