前后端分离开发

目录

前言

一、前后端分离开发

1.  介绍

2. 开发流程

3. 前端技术栈

(1)开发工具:

(2)技术框架:

二、Yapi

1. 介绍

2. 使用

(1)准备

(2)定义接口

(3)导出接口文档

(4)导入接口文档

三、Swagger

1. 介绍

2. 使用方式

(1)导入knife4j的maven坐标

(2)导入knife4j相关配置类

(3)设置静态资源映射

(4)在LoginCheckFilter中设置不需要处理的请求路径

3. 查看接口文档

4. 常用注解

(1)问题说明

(2)注解介绍

(3)注解测试


前言

当前项目中,前端代码和后端代码混合在一起,是存在问题的,存在什么问题呢?

主要存在以下几点问题:

(1) 开发人员同时负责前端和后端代码开发,分工不明确

(2)开发效率低

(3)前后端代码混合在一个工程中,不便于管理

(4)对开发人员要求高(既会前端,又会后端),人员招聘困难

为了解决上述提到的问题,现在比较主流的开发方式,就是前后端分离开发,前端人员开发前端的代码,后端开发人员开发服务端的业务功能,分工明确,各司其职。我们本章节,就是需要将之前的项目进行优化改造,变成前后端分离开发的项目。

一、前后端分离开发

1.  介绍

前后端分离开发,就是在项目开发过程中,对于前端代码的开发由专门的前端开发人员负责,后端代码则由后端开发人员负责,这样可以做到分工明确、各司其职,提高开发效率,前后端代码并行开发,可以加快项目开发进度。

目前,前后端分离开发方式已经被越来越多的公司所采用,成为当前项目开发的主流开发方式。

前后端分离开发后,从工程结构上也会发生变化,即前后端代码不再混合在同一个maven工程中,而是分为 前端工程后端工程

前后端分离之后,不仅工程结构变化,后期项目上线部署时,与之前也不同:

 之前: 前后端代码都混合在一起,我们只需要将前端和后端的代码统一打成jar包,直接运行就可以了。

 现在: 拆分为前后端分离的项目后,最终部署时,后端工程会打成一个jar包,运行在Tomcat中(springboot内嵌的tomcat)。前端工程的静态资源,会直接部署在Nginx中进行访问。

2. 开发流程

前后端分离开发后,面临一个问题,就是前端开发人员和后端开发人员如何进行配合来共同开发一个项目?可以按照如下流程进行:

a. 定制接口: 这里所说的接口不是我们之前在service, mapper层定义的interface; 这里的接口(API接口)就是一个http的请求地址,主要就是去定义:请求路径、请求方式、请求参数、响应数据等内容。(具体接口文档描述的信息, 如上图)

b. 前后端并行开发: 依据定义好的接口信息,前端人员开发前端的代码,服务端人员开发服务端的接口; 在开发中前后端都需要进行测试,后端需要通过对应的工具来进行接口的测试,前端需要根据接口定义的参数进行Mock数据模拟测试。

c. 联调: 当前后端都开发完毕并且自测通过之后,就可以进行前后端的联调测试了,在这一阶段主要就是校验接口的参数格式。

d. 提测: 前后端联调测试通过之后,就可以将项目部署到测试服务器,进行自动化测试了。

3. 前端技术栈

(1)开发工具:

Visual Studio Code (简称VsCode)

Hbuilder

(2)技术框架:

A. Node.js: Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。(类似于java语言中的JDK)。

B. Vue : 目前最火的的一个前端javaScript框架。

C. ElementUI: 一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库,通过ElementUI组件可以快速构建项目页面。

D. Mock: 生成随机数据,拦截 Ajax 请求,前端可以借助于Mock生成测试数据进行功能测试。

E. Webpack: webpack 是一个现代 JavaScript 应用程序的模块打包器(module bundler),分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。

二、Yapi

1. 介绍

YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理。

YApi让接口开发更简单高效,让接口的管理更具可读性、可维护性,让团队协作更合理。

源码地址: GitHub - YMFE/yapi: YApi 是一个可本地部署的、打通前后端及QA的、可视化的接口管理平台

官方文档: YApi 接口管理平台

要使用YApi,项目组需要自己进行部署,在本项目中我们可以使用课程提供的平台进行测试,域名: https://mock-java.itheima.net/

2. 使用

(1)准备

注册账号,登录平台

(2)定义接口

登录到Yapi平台之后,我们可以创建项目,在项目下创建接口分类,在对应的分类中添加接口。

a. 创建项目

b. 添加分类

在当前项目中,有针对于员工、菜品、套餐、订单的操作,我们在进行接口维护时,可以针对接口进行分类,如果没有对应的分类,我们自己添加分类。

c. 添加接口

接口基本信息录入之后,添加提交,就可以看到该接口的基本信息:

但是目前,接口中我们并未指定请求参数,响应数据等信息,我们可以进一步点击编辑,对该接口 详情进行编辑处理。

d. 运行接口

Yapi也提供了接口测试功能,当我们接口编辑完毕后,后端服务的代码开发完毕,启动服务,就可以使用Yapi进行接口测试了。

注意: 由于菜品分页查询接口,是需要登录后才可以访问的,所以在测试该接口时,需要先请求员工管理接口中的登录接口,登录完成后,再访问该接口。

在Yapi平台中,将接口文档定义好了之后,前后端开发人员就需要根据接口文档中关于接口的描述进行前端和后端功能的开发。

(3)导出接口文档

在Yapi平台中我们不仅可以在线阅读文档,还可以将Yapi中维护的文档直接导出来,可以导出md,json,html格式,在导出时自行选择即可 。

而在导出的html文件或md文件中,主要描述的就是接口的基本信息, 包括: 请求路径、请求方式、接口描述、请求参数、返回数据等信息。展示形式如下:

(4)导入接口文档

上述我们讲解了接口文档的导出,我们也可以将外部的接口文档导入到Yapi的平台中,这样我们就不用一个接口一个接口的添加了。我们可以将课程资料中提供的json格式的接口文档直接导入Yapi平台中来。

导入过程中出现的确认弹窗,选择"确认"。

导入成功之后,我们就可以在Yapi平台查看到已导入的接口。

三、Swagger

1. 介绍

官网:API Documentation & Design Tools for Teams | Swagger

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。功能主要包含以下几点:

A. 使得前后端分离开发更加方便,有利于团队协作

B. 接口文档在线自动生成,降低后端开发人员编写接口文档的负担

C. 接口功能测试

使用Swagger只需要按照它的规范去定义接口及接口相关的信息,再通过Swagger衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,以及在线接口调试页面等等。

直接使用Swagger, 需要按照Swagger的规范定义接口, 实际上就是编写Json文件,编写起来比较繁琐、并不方便, 。而在项目中使用,我们一般会选择一些现成的框架来简化文档的编写,而这些框架是基于Swagger的,如knife4j。knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案。而我们要使用kinfe4j,需要在pom.xml中引入如下依赖即可:

<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.2</version>
</dependency>

2. 使用方式

接下来,我们就将我们的项目集成Knife4j,来自动生成接口文档。这里我们还是需要再创建一个新的分支v1.2,在该分支中进行knife4j的集成,集成测试完毕之后,没有问题,我们再将v1.2分支合并到master。

使用knife4j,主要需要操作以下几步:

(1)导入knife4j的maven坐标

<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.2</version>
</dependency>

(2)导入knife4j相关配置类

这里我们就不需要再创建一个新的配置类了,我们直接在WebMvcConfig配置类中声明即可。

A. 在该配置类中加上两个注解 @EnableSwagger2 @EnableKnife4j ,开启Swagger和Knife4j的功能。

B. 在配置类中声明一个Docket类型的bean, 通过该bean来指定生成文档的信息。

@Slf4j
@Configuration
@EnableSwagger2
@EnableKnife4j
public class WebMvcConfig extends WebMvcConfigurationSupport {/*** 设置静态资源映射* @param registry*/@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {log.info("开始进行静态资源映射...");registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");}/*** 扩展mvc框架的消息转换器* @param converters*/@Overrideprotected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {log.info("扩展消息转换器...");//创建消息转换器对象MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();//设置对象转换器,底层使用Jackson将Java对象转为jsonmessageConverter.setObjectMapper(new JacksonObjectMapper());//将上面的消息转换器对象追加到mvc框架的转换器集合中converters.add(0,messageConverter);}@Beanpublic Docket createRestApi() {// 文档类型return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("com.itheima.reggie.controller")).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("瑞吉外卖").version("1.0").description("瑞吉外卖接口文档").build();}
}

注意: Docket声明时,指定的有一个包扫描的路径,该路径指定的是Controller所在包的路径。因为Swagger在生成接口文档时,就是根据这里指定的包路径,自动的扫描该包下的@Controller, @RestController, @RequestMapping等SpringMVC的注解,依据这些注解来生成对应的接口文档。

(3)设置静态资源映射

由于Swagger生成的在线文档中,涉及到很多静态资源,这些静态资源需要添加静态资源映射,否则接口文档页面无法访问。因此需要在 WebMvcConfig类中的addResourceHandlers方法中增加如下配置。

registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");

(4)在LoginCheckFilter中设置不需要处理的请求路径

需要将Swagger及Knife4j相关的静态资源直接放行,无需登录即可访问,否则我们就需要登录之后,才可以访问接口文档的页面。

在原有的不需要处理的请求路径中,再增加如下链接:

"/doc.html",
"/webjars/**",
"/swagger-resources",
"/v2/api-docs"

3. 查看接口文档

经过上面的集成配置之后,我们的项目集成Swagger及Knife4j就已经完成了,接下来我们可以重新启动项目,访问接口文档,访问链接为: http://localhost:8080/doc.html

我们可以看到,在所有的Controller中提供的所有的业务增删改查的接口,全部都已经自动生成了,我们通过接口文档可以看到请求的url、请求方式、请求参数、请求实例、响应的参数,响应的示例。 并且呢,我们也可以通过这份在线的接口文档,对接口进行测试。

注意: 由于我们服务端的Controller中的业务增删改查的方法,都是必须登录之后才可以访问的,所以,我们在测试时候,也是需要先访问登录接口。登录完成之后,我们可以再访问其他接口进行测试。

我们不仅可以在浏览器浏览生成的接口文档,Knife4j还支持离线文档,对接口文档进行下载,支持下载的格式有:markdown、html、word、openApi。

4. 常用注解

(1)问题说明

在上面我们直接访问Knife4j的接口文档页面,可以查看到所有的接口文档信息,但是我们发现,这些接口文档分类及接口描述都是Controller的类名(驼峰命名转换而来)及方法名,而且在接口文档中,所有的请求参数,响应数据,都没有中文的描述,并不知道里面参数的含义,接口文档的可读性很差。

(2)注解介绍

为了解决上述的问题,Swagger提供了很多的注解,通过这些注解,我们可以更好更清晰的描述我们的接口,包含接口的请求参数、响应数据、数据模型等。核心的注解,主要包含以下几个:

注解位置说明
@Api加载Controller类上,表示对类的说明
@ApiModel类(通常是实体类)描述实体类的作用
@ApiModelProperty属性描述实体类的属性
@ApiOperation方法说明方法的用途、作用
@ApiImplicitParams方法表示一组参数说明
@ApiImplicitParam方法用在@ApiImplicitParams注解中,指定一个请求参数的各个方面的属性

(3)注解测试

a. 实体类:

可以通过 @ApiModel , @ApiModelProperty 来描述实体类及属性

@Data
@ApiModel("套餐")
public class Setmeal implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty("主键")private Long id;//分类id@ApiModelProperty("分类id")private Long categoryId;//套餐名称@ApiModelProperty("套餐名称")private String name;//套餐价格@ApiModelProperty("套餐价格")private BigDecimal price;//状态 0:停用 1:启用@ApiModelProperty("状态")private Integer status;//编码@ApiModelProperty("套餐编号")private String code;//描述信息@ApiModelProperty("描述信息")private String description;//图片@ApiModelProperty("图片")private String image;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;@TableField(fill = FieldFill.INSERT)private Long createUser;@TableField(fill = FieldFill.INSERT_UPDATE)private Long updateUser;
}

b. 响应实体R:

@Data
@ApiModel("返回结果")
public class R<T> implements Serializable{@ApiModelProperty("编码")private Integer code; //编码:1成功,0和其它数字为失败@ApiModelProperty("错误信息")private String msg; //错误信息@ApiModelProperty("数据")private T data; //数据@ApiModelProperty("动态数据")private Map map = new HashMap(); //动态数据//省略静态方法 ....
}    

 c. Controller类及其中的方法:

描述Controller、方法及其方法参数,可以通过注解: @Api, @APIOperation, @ApiImplicitParams, @ApiImplicitParam

@RestController
@RequestMapping("/setmeal")
@Slf4j
@Api(tags = "套餐相关接口")
public class SetmealController {@Autowiredprivate SetmealService setmealService;@Autowiredprivate CategoryService categoryService;@Autowiredprivate SetmealDishService setmealDishService;/*** 新增套餐* @param setmealDto* @return*/@PostMapping@CacheEvict(value = "setmealCache",allEntries = true)@ApiOperation(value = "新增套餐接口")public R<String> save(@RequestBody SetmealDto setmealDto){log.info("套餐信息:{}",setmealDto);setmealService.saveWithDish(setmealDto);return R.success("新增套餐成功");}/*** 套餐分页查询* @param page* @param pageSize* @param name* @return*/@GetMapping("/page")@ApiOperation(value = "套餐分页查询接口")@ApiImplicitParams({@ApiImplicitParam(name = "page",value = "页码",required = true),@ApiImplicitParam(name = "pageSize",value = "每页记录数",required = true),@ApiImplicitParam(name = "name",value = "套餐名称",required = false)})public R<Page> page(int page,int pageSize,String name){//分页构造器对象Page<Setmeal> pageInfo = new Page<>(page,pageSize);Page<SetmealDto> dtoPage = new Page<>();LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();//添加查询条件,根据name进行like模糊查询queryWrapper.like(name != null,Setmeal::getName,name);//添加排序条件,根据更新时间降序排列queryWrapper.orderByDesc(Setmeal::getUpdateTime);setmealService.page(pageInfo,queryWrapper);//对象拷贝BeanUtils.copyProperties(pageInfo,dtoPage,"records");List<Setmeal> records = pageInfo.getRecords();List<SetmealDto> list = records.stream().map((item) -> {SetmealDto setmealDto = new SetmealDto();//对象拷贝BeanUtils.copyProperties(item,setmealDto);//分类idLong categoryId = item.getCategoryId();//根据分类id查询分类对象Category category = categoryService.getById(categoryId);if(category != null){//分类名称String categoryName = category.getName();setmealDto.setCategoryName(categoryName);}return setmealDto;}).collect(Collectors.toList());dtoPage.setRecords(list);return R.success(dtoPage);}/*** 删除套餐* @param ids* @return*/@DeleteMapping@CacheEvict(value = "setmealCache",allEntries = true)@ApiOperation(value = "套餐删除接口")public R<String> delete(@RequestParam List<Long> ids){log.info("ids:{}",ids);setmealService.removeWithDish(ids);return R.success("套餐数据删除成功");}/*** 根据条件查询套餐数据* @param setmeal* @return*/@GetMapping("/list")@Cacheable(value = "setmealCache",key = "#setmeal.categoryId + '_' + #setmeal.status")@ApiOperation(value = "套餐条件查询接口")public R<List<Setmeal>> list(Setmeal setmeal){LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId());queryWrapper.eq(setmeal.getStatus() != null,Setmeal::getStatus,setmeal.getStatus());queryWrapper.orderByDesc(Setmeal::getUpdateTime);List<Setmeal> list = setmealService.list(queryWrapper);return R.success(list);}
}

d. 重启服务测试:

我们上述通过Swagger的注解,对实体类及实体类中的属性,以及Controller和Controller的方法进行描述,接下来,我们重新启动服务,然后看一下自动生成的接口文档有何变化。

在接口文档的页面中,我们可以看到接口的中文描述,清晰的看到每一个接口是做什么的,接口方法参数什么含义,参数是否是必填的,响应结果的参数是什么含义等,都可以清楚的描述出来。

总之,我们要想清晰的描述一个接口,就需要借助于Swagger给我们提供的注解。

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

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

相关文章

芯科科技为全球首批原生支持Matter-over-Thread的智能锁提供强大助力,推动Matter加速成为主流技术

智能锁领域的先锋企业U-tec和Nuki选择芯科科技解决方案&#xff0c;成为Matter-over-Thread应用的领先者 致力于以安全、智能无线连接技术&#xff0c;建立更互联世界的全球领导厂商Silicon Labs&#xff08;亦称“芯科科技”&#xff0c;NASDAQ&#xff1a;SLAB&#xff09;今…

2024广东水展即将开幕 | 聚焦净水行业热点抢占行业新机遇

2024广东水展即将开幕 | 聚焦净水行业热点抢占行业新机遇 随着消费升级和人们对环境健康的意识增强&#xff0c;人们除了关注净水产品的性能外&#xff0c;对产品的设计、服务、多应用场景化等需求也愈发多样化。节能环保、智能化成为产品迭代升级主要方向。据奥维云网数据显示…

Docker中使用Tomcat并部署war工程

系列文章目录 文章目录 系列文章目录前言一、构建镜像二、运行镜像三、列出正在运行的容器四、停止正在运行的容器 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文…

物联网技术助力智慧城市安全建设:构建全方位、智能化的安全防护体系

一、引言 随着城市化进程的加速和信息技术的迅猛发展&#xff0c;智慧城市已成为现代城市发展的重要方向。在智慧城市建设中&#xff0c;安全是不可或缺的一环。物联网技术的快速发展为智慧城市安全建设提供了有力支持&#xff0c;通过构建全方位、智能化的安全防护体系&#…

Kali Linux 安装 + 获取 root 权限 + 远程访问

一、什么是Kali kali是linux其中一个发行版&#xff0c;基于Debian&#xff0c;前身是BackTrack&#xff08;简称BT系统&#xff09;。kali系统内置大量渗透测试软件&#xff0c;可以说是巨大的渗透系统&#xff0c;涵盖了多个领域&#xff0c;如无线网络、数字取证、服务器、密…

Python读取hbase数据库

1. hbase连接 首先用hbase shell 命令来进入到hbase数据库&#xff0c;然后用list命令来查看hbase下所有表&#xff0c;以其中表“DB_level0”为例&#xff0c;可以看到库名“baotouyiqi”是拼接的&#xff0c;python代码访问时先连接&#xff1a; def hbase_connection(hbase…

red hat 6.9版本7.9版本 忘记root密码重置方法

文章目录 1、重置密码具体步骤Oracle Linux 6.9版本&#xff1a;1、开机到此界面按e2、在以下界面选择后按e3、选择相应内核后按e4、在此界面输入 single 回车5、回到内核界面后按b进入引导系统6、在#后输入passwd root修改密码7、修改密码&#xff1a;8、Reboot重启9、使用新密…

【工作实践-06】uniapp使用webView

一、建立APP页面和webview的通讯 1.引入webview.js App 端使用 uni.web-view.js 的最低版为 uni.webview.1.5.4.js APP端可以支持网络网页和本地网页&#xff0c;但如果使用本地网页和相关资源&#xff08;js、css等文件&#xff09;必须放在 static 目录下。 2.引入搭桥docum…

PostgreSQL中int类型达到上限的一些处理方案

使用int类型作为表的主键在pg中是很常见的情况&#xff0c;但是pg中int类型的范围在-2147483648到2147483647&#xff0c;最大只有21亿&#xff0c;这个在一些大表中很容易就会达到上限。一旦达到上限&#xff0c;那么表中便没办法在插入数据了&#xff0c;这个将会是很严重的问…

【react native】css踩坑记录

1、IOS上面opacity重叠失效 在 iOS 上&#xff0c;当两个具有相同背景色的元素重叠时&#xff0c;不透明度&#xff08;opacity&#xff09;较低的元素会显示在较高的元素上方。 所以考虑使用rgba的形式。 // 对于下面这种写法&#xff0c;如果存在container和activeIndicat…

word文档空格不能有下划线【笔记】

word文档空格不能有下划线 2024-3-1 21:20:24 推荐 word下划线打不出来了&#xff0c;是怎么回事&#xff1f; 问题 字后面打不出来下划线 操作 1.点击文件 左上角&#xff0c;点击“文件”。 2.点击选项 鼠标下滑&#xff0c;点击“选项”。 3.点击常规与保存 点击“…

java基础-mysql

文章目录 mysql基础面试题什么是mysql什么是事务并发事务带来的影响事物的隔离级别索引大表优化什么是池化思想&#xff0c;什么是数据库连接池&#xff0c;为什么要用数据库连接池⾏锁&#xff0c;表锁&#xff1b;乐观锁&#xff0c;悲观锁MySQL主备同步的基本原理SQL什么情况…

[⑥5G NR]: 无线接口协议,信道映射学习

5G系统整体包括核心网、接入网以及终端部分&#xff0c;接入网与终端间通过无线空口协议栈进行连接。无线接口可分为三个协议层&#xff1a;物理层&#xff08;L1&#xff09;、数据链路层&#xff08;L2&#xff09;和网络层&#xff08;L3&#xff09;。 L1&#xff1a;物理…

【python】json转成成yaml中文编码异常显示成:\u5317\u4EAC\u8DEF123\u53F7

姊妹篇&#xff1a;【python】json转成成yaml json数据 {"name": "张三","age": 30,"isMarried": false,"children": [{"name": "小王","age": 5},{"name": "小李",&qu…

mysql冷备

数据库备份类型 冷备份&#xff1a;在数据库停止服务的情况下进行备份 热备份&#xff1a;在数据库处于运行状态下进行备份 温备份&#xff1a;不可写但可读的情况下进行备份 冷备分时&#xff0c;只需要在停止数据库后&#xff0c;拷贝数据目录到另一个地方即可。 mysql 启…

为什么不能启动游戏错误代码126 加载bugreportnew.dll失败

错误代码126通常表示在尝试加载某个动态链接库&#xff08;DLL&#xff09;文件时出现了问题。在您提到的例子中&#xff0c;bugreportnew.dll 文件未能成功加载&#xff0c;这可能是由于以下几个原因&#xff1a; 腾讯云2024新春采购节优惠活动入口&#xff1a;https://curl.q…

Linux---进程信号

一、信号的概念 信号是一种向目标进程发送通知消息的机制 信号的特性(可以结合红绿灯、防空警报等生活样例来理解) 1、在信号没有出现之前&#xff0c;我们就已经知道如何去处理信号&#xff0c;即我们认识信号 2、信号是异步产生的&#xff0c;即我们不知道它具体何时产生 3、…

基于MQTT协议实现微服务架构事件总线

一、场景描述 昨天在博客《客户端订阅服务端事件的实现方法》中提出了利用websocket、服务端EventEmitter和客户端mitt实现客户端订阅服务端事件&#xff0c;大大简化了客户端对服务端数据实时响应的逻辑。上述方案适用于单服务节点的情形。 对于由服务集群支撑的微服务架构&…

Redis 之七:穿透、击穿、雪崩

&#xff08;本内容部分来自知乎网等网络&#xff09; Redis 缓存的使用&#xff0c;极大的提升了应用程序的性能和效率&#xff0c;特别是数据查询方面。但同时&#xff0c;它也带来了一些问题。其中&#xff0c;最要害的问题&#xff0c;就是数据的一致性问题&#xff0c;从严…

Educational Codeforces Round 132 (Rated for Div. 2) E. XOR Tree(启发式合并+贪心)

题目 n(n<2e5)个点的树&#xff0c;点i权值ai&#xff08;1<ai<2^30&#xff09; 修改最少的点的权值&#xff0c;使得树上不存在异或和为0的简单路径&#xff0c;输出最少的点数 权值可以被修改成任意正整数&#xff08;可以是无限大&#xff09; 思路来源 官方…