基于常用设计模式的业务框架

news2025/1/23 3:12:50

前言

做开发也有好几年时间了,最近总结和梳理自己在工作中遇到的一些问题,工作中最容易写出BUG的需求就是改造需求了。一个成熟的业务系统是需要经过无数次迭代而成的,也意味着经过很多开发人员之手,最后到你这里,大部分时间都是在梳理代码,理解别人的用意。有的业务功能里面一堆IF嵌套嵌套,耦合度太过,理解起来比较费劲,也容易改出BUG。

不同人有不同的编码习惯,这没有办法,但如果系统中能用一些常用的设计模式来编码,那多多少少能增加可读性,降低耦合度,所以想做出几种常用的设计模式工具类,开发时可以直接使用,让我们更加专注于业务代码开发。

正文

框架基于常用的设计模式,策略模式、模板方法模式、工厂模式、责任链模式等,结合Spring IOC,Spring AOP,Springboot自动装配;

Github地址:点击查看

主要有4个通用的设计模式处理器:

通用策略模式处理器

业务场景

购买保险产品的费用计算方法有多种,按日计算、按月计算、按费率表计算。不同产品可选择的计费选项可能不一样,如下:

日计算(01):支持 A产品、B产品

月计算(02):支持 A产品、C产品

费率表计算(03):支持 A产品、B产品、C产品

代码演示

        //计算类型
        String calculateType="01";
        //产品编号
        String productNo="A";
        if(calculateType.equals("01")){
            if ("A,B".contains(productNo)){
                //按日计算
            }
        }else if(calculateType.equals("02")){
            if ("A,C".contains(productNo)){
                //按月计算
            }
        }else if(calculateType.equals("03")){
            if ("A,B,C".contains(productNo)){
                //按费率表计算
            }
        }

上面这种场景如果使用 if…else…处理的话,随着代码不断迭代,其可读性、调整成本会变得越来越大;

下面使用策略模式来演示:

定义处理器,继承策略处理器接口

import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.strategy.AbstractBHandle;
import com.zdc.business.business.wrapper.CommonBName;

import java.util.Arrays;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.strategy
 * @Date:2023/5/11 20:14
 * @Wechat:DDOS12345H
 * 按日计算
 */
@BComponent
public class Calculate01Handle extends AbstractBHandle<RequestDto,ResponseDto> {
    @Override
    public boolean before(RequestDto requestDto) {
        return true;
    }

    @Override
    public boolean after(RequestDto requestDto) {
        return true;
    }

    @Override
    public ResponseDto doExecute(RequestDto requestDto) {
        System.out.println("按日计算");
        return null;
    }

    @Override
    public CommonBName getName() {
        //定义该处理器的类型名称,以及支持的别名集;执行时按这两个维度匹配处理器
        return new CommonBName<String>("01", Arrays.asList("A","B"));
    }
}

import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.strategy.AbstractBHandle;
import com.zdc.business.business.wrapper.CommonBName;

import java.util.Arrays;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.strategy
 * @Date:2023/5/11 20:14
 * @Wechat:DDOS12345H
 * 按日计算
 */
@BComponent
public class Calculate02Handle extends AbstractBHandle<RequestDto,ResponseDto> {
    @Override
    public boolean before(RequestDto requestDto) {
        return true;
    }

    @Override
    public boolean after(RequestDto requestDto) {
        return true;
    }

    @Override
    public ResponseDto doExecute(RequestDto requestDto) {
        System.out.println("按月计算");
        return null;
    }

    @Override
    public CommonBName getName() {
        //定义该处理器的类型名称,以及支持的别名集;执行时按这两个维度匹配处理器
        return new CommonBName<String>("02", Arrays.asList("A","C"));
    }
}
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.strategy.AbstractBHandle;
import com.zdc.business.business.wrapper.CommonBName;

import java.util.Arrays;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.strategy
 * @Date:2023/5/11 20:14
 * @Wechat:DDOS12345H
 * 按日计算
 */
@BComponent
public class Calculate03Handle extends AbstractBHandle<RequestDto,ResponseDto> {
    @Override
    public boolean before(RequestDto requestDto) {
        return true;
    }

    @Override
    public boolean after(RequestDto requestDto) {
        return true;
    }

    @Override
    public ResponseDto doExecute(RequestDto requestDto) {
        System.out.println("按费率表计算");
        return null;
    }

    @Override
    public CommonBName getName() {
        //定义该处理器的类型名称,以及支持的别名集;执行时按这两个维度匹配处理器
        return new CommonBName<String>("03", Arrays.asList("A","B","C"));
    }
}

定义入参类、出参类;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.adapter
 * @Date:2023/5/10 20:48
 * @Wechat:DDOS12345H
 */
public class ResponseDto {
    //...
}
/**
 * @Author:猪大肠
 * @Package:com.example.btest.adapter
 * @Date:2023/5/10 20:48
 * @Wechat:DDOS12345H
 */
public class ResponseDto {
    //...
}

运行用例

import com.zdc.business.business.context.StrategyBContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.strategy
 * @Date:2023/5/10 19:21
 * @Wechat:DDOS12345H
 */
public class StartApp {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.example.btest");
        StrategyBContext strategyBContext = (StrategyBContext) applicationContext.getBean("strategyBContext");

        //计算类型
        String calculateType="01";
        //产品编号
        String productNo="A";
        RequestDto requestDto=new RequestDto();
        ResponseDto execute = strategyBContext.invoke(calculateType,productNo,requestDto,ResponseDto.class);

    }
}

在这里插入图片描述

通用适配器模式处理器

业务场景

现有公司A和公司B进行投保出单,出完单后需要通知相关人员。

公司A:需要邮件、短信通知投保人;

公司B:需要邮件、短信通知被保人,企信通知业务员;

代码演示

/**
 * @Author:猪大肠
 * @Package:com.example.btest.adapter
 * @Date:2023/5/10 20:48
 * @Wechat:DDOS12345H
 */
@Data
public class RequestDto {
	//定义请求参数
    String companyType;

}
/**
 * @Author:猪大肠
 * @Package:com.example.btest.adapter
 * @Date:2023/5/10 20:48
 * @Wechat:DDOS12345H
 */
public class ResponseDto {
    //定义相应参数
}

定义A公司适配器

import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IAdapterEnumBFactory;
import com.zdc.business.business.handle.adapter.AbstractHandlesAdapter;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.adapter
 * @Date:2023/5/10 20:46
 * @Wechat:DDOS12345H
 */
@BComponent
public class NotifyCompanyA extends AbstractHandlesAdapter<RequestDto, ResponseDto> {


    @Override
    public boolean isSupport(RequestDto context) {
        //该方法用于编写适配条件
        if (context.getCompanyType().equals("A")){

            return true;
        }
        return false;
    }

    @Override
    public ResponseDto execute(RequestDto context) {
        System.out.println("发邮件通知投保人");
        System.out.println("发短信通知投保人");
        return null;
    }

    @Override
    public IAdapterEnumBFactory getType() {
        //定义该适配器归属类型
        return ChannelIAdapterEnumBFactory.CHANNEL_NOTIFY;
    }
}

定义枚举参数

import com.zdc.business.business.factory.IAdapterEnumBFactory;
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.adapter
 * @Date:2023/5/10 22:30
 * @Wechat:DDOS12345H
 */
@Getter
@AllArgsConstructor

public enum  ChannelIAdapterEnumBFactory implements IAdapterEnumBFactory {
    CHANNEL_NOTIFY("notify",10,"公司消息通知处理器"),
    ;

    String type;
    int priorityOrder;
    String description;
}

定义B公司通知适配器

import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IAdapterEnumBFactory;
import com.zdc.business.business.handle.adapter.AbstractHandlesAdapter;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.adapter
 * @Date:2023/5/10 20:46
 * @Wechat:DDOS12345H
 */
@BComponent
public class NotifyCompanyB extends AbstractHandlesAdapter<RequestDto, ResponseDto> {


    @Override
    public boolean isSupport(RequestDto context) {
        //该方法用于编写适配条件
        if (context.getCompanyType().equals("B")){

            return true;
        }
        return false;
    }

    @Override
    public ResponseDto execute(RequestDto context) {
        System.out.println("发邮件通知投保人");
        System.out.println("发短信通知投保人");
        System.out.println("企信通知业务员");
        return null;
    }

    @Override
    public IAdapterEnumBFactory getType() {
        //定义该适配器归属类型
        return ChannelIAdapterEnumBFactory.CHANNEL_NOTIFY;
    }
}

入口代码

import com.zdc.business.business.context.AdapterBContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.adapter
 * @Date:2023/5/10 21:15
 * @Wechat:DDOS12345H
 */
public class StratApp {
    public static void main(String[] args) {
        //SpringBoot环境下可直接使用@Autowire
        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.example.btest");
        AdapterBContext adapterBContext = (AdapterBContext) applicationContext.getBean("adapterBContext");

        //假设当前是A公司投保
        RequestDto requestDto=new RequestDto();
        requestDto.setCompanyType("A");
        ResponseDto execute = adapterBContext.execute(ChannelIAdapterEnumBFactory.CHANNEL_NOTIFY.type, requestDto, ResponseDto.class);

    }
}

在这里插入图片描述

通用责任链模式处理器

业务场景

在录单系统中,录单员填写完资料,通常下一步需要提交审核,而在正式提交审核之前,系统需要校验数据是否符合要求。某些场景下不想完全卡主流程,通常会以软提示的方式在前端进行提醒;现有以下4种软提示校验(从上到下校验顺序):

在这里插入图片描述

为了提高体验,当系统抛出资料A校验后,录单员点击“是”进行重新提交,此时由于前面已经点击了“是”了,此时后端不应该再对点击”是“的校验器进行校验。通常这种需要给每个校验器都设置一个标识,当为“是”时,后端跳过校验,但如果校验场景较多时,那代码将难以维护。

现使用责任链模式来处理以上场景

代码演示

定义好请求参数类和相应参数类

import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.adapter
 * @Date:2023/5/10 20:48
 * @Wechat:DDOS12345H
 */
@Data
@AllArgsConstructor
public class RequestDto {
    String data;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.adapter
 * @Date:2023/5/10 20:48
 * @Wechat:DDOS12345H
 */
public class ResponseDto {
}

import com.zdc.business.business.factory.IChainsEnumBFactory;
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.chain
 * @Date:2023/5/11 21:04
 * @Wechat:DDOS12345H
 */
@Getter
@AllArgsConstructor
public enum OrderCheckEnumBFactory implements IChainsEnumBFactory {
        ORDER_CHECK_SOFT_A("order","checkA",0,"资料A校验器"),
        ORDER_CHECK_SOFT_B("order","checkB",1,"资料B校验器"),
        ORDER_CHECK_SOFT_C("order","checkC",2,"资料C校验器"),
    ;
	//处理器类型,标记所属链
    String type;
	//处理器名称
    String name;
	//优先级顺序
    int priorityOrder;
	//描述
    String description;
}

自定义异常类

import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.chain
 * @Date:2023/5/11 21:12
 * @Wechat:DDOS12345H
 */
@AllArgsConstructor
@Data
public class SoftTipException extends RuntimeException{
    private String code;
    private String desc;

}

定义校验器

import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IChainsEnumBFactory;
import com.zdc.business.business.handle.chains.AbstractChainHandle;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.chain
 * @Date:2023/5/11 21:02
 * @Wechat:DDOS12345H
 */
@BComponent
public class CheckAHandle extends AbstractChainHandle<RequestDto,ResponseDto> {
    @Override
    public ResponseDto execute(RequestDto context) {
        System.out.println("校验器A");
        if (context.equals("A")){
            //抛出异常,返回下个处理器名称;下次携带这个名称来找到当前节点
            throw new SoftTipException(getNextNode()==null?"succeed":getNextNode().getHandleName(),"资料A可能存在风险,是否继续提交?");
        }else{
            //调用下个节点校验器
            executeNextNode(context);
        }
        return null;
    }

    @Override
    public IChainsEnumBFactory getType() {
        return OrderCheckEnumBFactory.ORDER_CHECK_SOFT_A;
    }
}

import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IChainsEnumBFactory;
import com.zdc.business.business.handle.chains.AbstractChainHandle;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.chain
 * @Date:2023/5/11 21:02
 * @Wechat:DDOS12345H
 */
@BComponent
public class CheckBHandle extends AbstractChainHandle<RequestDto,ResponseDto> {
    @Override
    public ResponseDto execute(RequestDto context) {
        System.out.println("校验器B");
        if (context.equals("B")){
            //抛出异常,返回下个处理器名称;下次携带这个名称来找到当前节点
            throw new SoftTipException(getNextNode()==null?"succeed":getNextNode().getHandleName(),"资料B可能存在风险,是否继续提交?");
        }else{
            //调用下个节点校验器
            executeNextNode(context);
        }
        return null;
    }

    @Override
    public IChainsEnumBFactory getType() {
        return OrderCheckEnumBFactory.ORDER_CHECK_SOFT_B;
    }
}

import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IChainsEnumBFactory;
import com.zdc.business.business.handle.chains.AbstractChainHandle;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.chain
 * @Date:2023/5/11 21:02
 * @Wechat:DDOS12345H
 */
@BComponent
public class CheckCHandle extends AbstractChainHandle<RequestDto,ResponseDto> {
    @Override
    public ResponseDto execute(RequestDto context) {
        System.out.println("校验器C");
        if (context.equals("C")){
            //抛出异常,返回下个处理器名称;下次携带这个名称来找到当前节点
            throw new SoftTipException(getNextNode()==null?"succeed":getNextNode().getHandleName(),"资料C可能存在风险,是否继续提交?");
        }else{
            //调用下个节点校验器
            executeNextNode(context);
        }
        return null;
    }

    @Override
    public IChainsEnumBFactory getType() {
        return OrderCheckEnumBFactory.ORDER_CHECK_SOFT_C;
    }
}

运行用例

import com.zdc.business.business.context.ChainsBContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.strategy
 * @Date:2023/5/10 19:21
 * @Wechat:DDOS12345H
 */
public class StartApp {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.example.btest");
        ChainsBContext chainsBContext = (ChainsBContext) applicationContext.getBean("chainsBContext");
        //校验标识
        String checkFlag="checkB";
        if (!"succeed".equals(checkFlag)){
            if ("start".equals(checkFlag)){
                chainsBContext.start("order",new RequestDto(checkFlag),null);
            }
            chainsBContext.execute("order",checkFlag,new RequestDto(checkFlag),null);

        }

    }
}

在这里插入图片描述

通用代理模式处理器

业务场景

与其它周边系统进行交互时,需要将请求报文和响应报文记录到ES中,方便后续排查,并对请求报文加密加签名,响应报文解密验签;

考虑到复用性等方面,所以这里使用代理模式来增强方法最合适不过了。

代码演示

定义ES日志记录增强器

import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.proxy.AbstractBEnhanceIntecepter;
import com.zdc.business.business.wrapper.IntecepterProceedWrapper;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.aop
 * @Date:2023/5/11 22:58
 * @Wechat:DDOS12345H
 */
@BComponent
public class EnhanceEsHandle extends AbstractBEnhanceIntecepter {

    @Override
    public Object execute(IntecepterProceedWrapper ipw) {
        //方法参数
        Object[] args = ipw.getArgs();
        System.out.println("请求参数:"+args[0].toString());
        //调用真正的执行方法
        Object result = ipw.proceed();
        System.out.println("响应参数:"+args[0].toString());

        return result;
    }
}

加解密增强器

import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.proxy.AbstractBEnhanceIntecepter;
import com.zdc.business.business.wrapper.IntecepterProceedWrapper;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.aop
 * @Date:2023/5/11 22:58
 * @Wechat:DDOS12345H
 */
@BComponent
public class EnhanceEncryHandle extends AbstractBEnhanceIntecepter {

    @Override
    public Object execute(IntecepterProceedWrapper ipw) {
        //方法参数
        Object[] args = ipw.getArgs();
        System.out.println("对请求报文加密:");
        System.out.println("对请求报文加签:");
        //调用真正的执行方法
        Object result = ipw.proceed();
        System.out.println("对请求报文解密:");
        System.out.println("对请求报文验签:");

        return result;
    }
}

被增强类

import com.zdc.business.business.annotation.InterceptorEnhance;
import org.springframework.stereotype.Component;

/**
 * @Author:猪大肠
 * @Package:com.example.btest.aop
 * @Date:2023/5/11 23:06
 * @Wechat:DDOS12345H
 */
@Component
public class HttpToCompanyA {
    //按顺利指定增强器
    @InterceptorEnhance(intecepter = {EnhanceEsHandle.class,EnhanceEncryHandle.class})
    public String sendInfo(String request){
        return  "{code:\"0\",text:\"成功\"}";
    }

}

运行用例

在这里插入图片描述

依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        //打包到本地仓库后,引入使用
        <dependency>
            <groupId>com.zdc.business</groupId>
            <artifactId>business</artifactId>
            <version>0.0.1</version>
        </dependency>
    </dependencies>

总结

本人3年多开发经验,对于各方面认识有限。欢迎老师们指出改进之处,有好的建议或者有想法大家可以交流探讨,一起完善。

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

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

相关文章

每日学术速递5.11

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.Diffusion Explainer: Visual Explanation for Text-to-image Stable Diffusion 标题&#xff1a;扩散解释器&#xff1a;文本到图像稳定扩散的视觉解释 作者&#xff1a;Seongmin…

【数据结构】【算法】二叉树、二叉排序树、树的相关操作

树结构是以分支关系定义的一种层次结构&#xff0c;应用树结构组织起来的数据&#xff0c;逻辑上都具有明显的层次关系。 操作系统中的文件管理系统、网络系统中的域名管理、数据库系统中的索引管理等都使用了树结构来组织和管理数据。 树的基本概念 树Tree是由n个节点组成的有…

数据结构-查找-散列结构(散列表)

目录 *一、散列表 二、散列函数 *除留余数法 *直接定址法 数字分析法 平方取中法 三、冲突处理方法--开发定地法 *3.1线性探测法 *查找效率&#xff1a; *3.2平方探测法 3.3伪随机序列法 3.4再散列法 *一、散列表 又称哈希表&#xff0c;数据元素的关键字与其存储…

bgp团体属性配置案例一

RouterA的配置 sysname RouterA interface GigabitEthernet1/0/0 ip address 192.168.0.1 255.255.255.0 interface LoopBack0 ip address 1.1.1.1 255.255.255.255 bgp 10 router-id 1.1.1.1 //Router ID&#xff0c;建议配置为LoopBack0的IP地址 peer 192.168.0.2 as-number …

【Linux】信号的处理

信号篇终章 文章目录 前言一、信号的处理 1.可重入函数 2.volatile关键字 3.SIGCHLD信号总结 前言 在前两篇linux文章中我们详细的讲解了信号的产生和信号的保存&#xff0c;今天来到最后一个重点信号的处理&#xff0c;对于信号的处理我们会重新引入进程…

如何实现一个高效的H264信源编码器?了解核心算法和实现流程

H264 H264是一种常用的视频编码标准&#xff0c;它以网络传输和存储为设计目的&#xff0c;能够将视频信号进行高效压缩&#xff0c;并保持较高的视频质量。 H264视频编码标准采用的是基于帧的编码方式。每一帧视频都被分为不同的块&#xff0c;每个块中都包含了可压缩的信息…

11.PC端网页特效

PC端网页特效 1. 元素偏移量 offset 系列 1.1 offset 概述 offset 翻译过来就是偏移量&#xff0c; 使用 offset 系列相关属性可以动态的得到该元素的位置&#xff08;偏移&#xff09;、大小等 获得元素距离带有定位父元素的位置获得元素自身的大小&#xff08;宽度高度&a…

03:MYSQL----DQL,聚合函数

目录 1:介绍 2:语法 3:聚合函数 4:DOL 语句练习 5:SQL执行顺序 1:介绍 数据查询语言&#xff0c;用来查询数据库中表的记录 2:语法 select 字段列表 from 表名列表 where 条件列表 group by 分组字段列表 having 分组后字段列表 order by 排序字段列表 limit 分页参…

Vben Admin 自学记录 —— 使用 mock 模拟数据以及模拟api联调接口(持续更新中...)

Vben Admin —— 使用 mock 模拟数据以及模拟api联调接口 数据 mock&联调相关概念及使用 练习 —— 在之前table基础上&#xff0c;使用mock模拟数据&#xff0c;替换原来的死数据&#xff0c;添加新增、查看、修改和删除api并添加逻辑&#xff0c;实现一个简单的、完整的…

《编程思维与实践》1067.小型组合数

《编程思维与实践》1067.小型组合数 题目 思路 法一: 注意到题目数据最大为 C 40 20 137846528820 C_{40}^{20}137846528820 C4020​137846528820在long long的范围内,所以其实可以不用大整数的处理方法去计算: 由于 C m n m ! n ! ( m − n ) ! m ( m − 1 ) . . . ( m −…

mysql数据库的库操作 --2

目录 库操作 2.1&#xff1a;数据库的查看与创建与使用 2.2&#xff1a;字符集和效验规则 2.3&#xff1a;修改和删除数据库 2.4&#xff1a;数据库的备份和恢复 2.5&#xff1a;查看连接情况 库操作 2.1&#xff1a;数据库的查看与创建与使用 2.1.1&#xff1a;数据库…

AcWing算法提高课-1.3.9庆功会

宣传一下算法提高课整理 <— CSDN个人主页&#xff1a;更好的阅读体验 <— 本题链接&#xff08;AcWing&#xff09; 点这里 题目描述 为了庆贺班级在校运动会上取得全校第一名成绩&#xff0c;班主任决定开一场庆功会&#xff0c;为此拨款购买奖品犒劳运动员。 期望…

[golang gin框架] 32.Gin 商城项目- 支付宝支付操作相关功能讲解

一.支付宝支付之前的准备工作 创建应用、配置签名、提交审核 支付宝支付之前的准备工作 支付宝开放平台支持使用 普通公钥、公钥证书 两种签名方式 公钥证书模式下完成支付需要获取的内容&#xff1a; appId 应用私钥 应用公钥证书 支付宝根证书 支付宝公钥证书 普通公钥模式下…

热乎的面经——不屈不挠

⭐️前言⭐️ &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主将持续更新学习记录收获&#xff0c;友友们有任何问题可以在评论区留言 &#x1f349;博客中涉及源码及博主日常练习代码均已上传GitHub &#x1f4…

【Linux常见指令以及权限理解】基本指令(3)

写在前面 上一篇文章&#xff0c;我们学习了Linux的一些常用指令&#xff0c; 学习了如何理解Linux系统&#xff0c;介绍了对Linux系统的理解&#xff1a;Linux下一切皆文件 介绍了重定向还有管道相关的知识。这里是上一篇博客的链接&#xff1a;http://t.csdn.cn/2d6fc 接…

Kali HTTrack演示-渗透测试察打一体(1)

HTTrack是一个免费并易于使用的线下浏览器工具,全称是HTTrack Website Copier for Windows,它能够让你从互联网上下载指定的网站进行线下浏览(离线浏览),也可以用来收集信息(甚至有网站使用隐藏的密码文件),一些仿真度极高的伪网站(为了骗取用户密码),也是使用类似工具做…

[一篇读懂]C语言十二讲:栈与队列和真题实战

[一篇读懂]C语言十二讲&#xff1a;栈与队列和真题实战 1. 与408关联解析及本节内容介绍1 与408关联解析2 本节内容介绍 2. 栈(stack)的原理解析2.1 **栈&#xff1a;只允许在一端进行插入或删除操作的线性表**2.2 栈的基本操作2.3 栈的顺序存储2.4 栈的链表存储 3. 初始化栈 -…

PE文件+UPX壳 ida分析

die查壳发现是UPX壳&#xff0c;直接用ida分析&#xff0c;会发现能分析出来的信息特别少&#xff0c;需要脱壳 工具链接发布 UPX/UPX (github.com) 下载压缩包后解压&#xff0c;直接在该文件路径下cmd&#xff0c;输入upx.exe -h安装完成&#xff0c;使用命令“upx -d 文件路…

计算机网络-网络层与链路层协议分析实验

一.实验目的 通过本实验&#xff0c;进一步熟悉PacketTracer的使用&#xff0c;学习路由器与交换机的基本配置&#xff0c;加深对网络层与链路层协议的理解。 二.实验内容 1.完成路由器交换机的基本配置 2.了解 ICMP 数据包的格式 3.检查ARP交换 三.实验过程 1.完成路由…

链表——循环链表

其他形式的链表——循环链表 循环链表 定义&#xff1a;循环链表是表中最后一个结点的指针指向头结点&#xff0c;使链表构成环状 特点&#xff1a;从表中任一结点发出均可找到表中其他结点&#xff0c;提高查找效率 双向循环链表 data&#xff1a;数据元素 prior&#xff1…