前后端分離開發

目錄

前言

一、前后端分離開發

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.pswp.cn/news/714401.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714401.shtml
英文地址,請注明出處:http://en.pswp.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; 思路來源 官方…