全網最全的接口文檔速成

文章目錄

  • 接口文檔
    • 內容
    • 前言
    • 1. 前后端分離開發
      • 1.1 介紹
      • 1.2 開發流程
      • 1.3 前端技術棧
    • 2. Yapi
      • 2.1 介紹
      • 2.2 使用
        • 2.2.1 準備
        • 2.2.2 定義接口
        • 2.2.3 導出接口文檔
        • 2.2.4 導入接口文檔
    • 3. Swagger
      • 3.1 介紹
      • 3.2 使用方式
      • 3.3 查看接口文檔
      • 3.4 常用注解
        • 3.4.1 問題說明
        • 3.4.2 注解介紹
        • 3.4.3 注解測試
    • 4. 項目部署
      • 4.1 部署架構
      • 4.2 環境說明
      • 4.3 前端部署
      • 4.4 反向代理配置
      • 4.5 服務端部署
      • 4.6 圖片展示問題處理

接口文檔

內容

  • 前后端分離開發

  • Yapi

  • Swagger

  • 項目部署

前言

當前項目中,前端代碼和后端代碼混合在一起,是存在問題的,存在什么問題呢?

主要存在以下幾點問題:

1). 開發人員同時負責前端和后端代碼開發,分工不明確

2). 開發效率低

3). 前后端代碼混合在一個工程中,不便于管理

4). 對開發人員要求高(既會前端,又會后端),人員招聘困難

為了解決上述提到的問題,現在比較主流的開發方式,就是前后端分離開發,前端人員開發前端的代碼,后端開發人員開發服務端的業務功能,分工明確,各司其職。我們本章節,就是需要將之前的項目進行優化改造,變成前后端分離開發的項目。

1. 前后端分離開發

1.1 介紹

前后端分離開發,就是在項目開發過程中,對于前端代碼的開發由專門的前端開發人員負責,后端代碼則由后端開發人員負責,這樣可以做到分工明確、各司其職,提高開發效率,前后端代碼并行開發,可以加快項目開發進度。

目前,前后端分離開發方式已經被越來越多的公司所采用,成為當前項目開發的主流開發方式。

前后端分離開發后,從工程結構上也會發生變化,即前后端代碼不再混合在同一個maven工程中,而是分為 前端工程后端工程

前后端分離之后,不僅工程結構變化,后期項目上線部署時,與之前也不同:

1). 之前: 前后端代碼都混合在一起,我們只需要將前端和后端的代碼統一打成jar包,直接運行就可以了。

2). 現在: 拆分為前后端分離的項目后,最終部署時,后端工程會打成一個jar包,運行在Tomcat中(springboot內嵌的tomcat)。前端工程的靜態資源,會直接部署在Nginx中進行訪問。

1.2 開發流程

前后端分離開發后,面臨一個問題,就是前端開發人員和后端開發人員如何進行配合來共同開發一個項目?可以按照如下流程進行:

1). 定制接口: 這里所說的接口不是我們之前在service, mapper層定義的interface; 這里的接口(API接口)就是一個http的請求地址,主要就是去定義:請求路徑、請求方式、請求參數、響應數據等內容。(具體接口文檔描述的信息, 如上圖)

2). 前后端并行開發: 依據定義好的接口信息,前端人員開發前端的代碼,服務端人員開發服務端的接口; 在開發中前后端都需要進行測試,后端需要通過對應的工具來進行接口的測試,前端需要根據接口定義的參數進行Mock數據模擬測試。

3). 聯調: 當前后端都開發完畢并且自測通過之后,就可以進行前后端的聯調測試了,在這一階段主要就是校驗接口的參數格式。

4). 提測: 前后端聯調測試通過之后,就可以將項目部署到測試服務器,進行自動化測試了。

1.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等),并將其轉換和打包為合適的格式供瀏覽器使用。

2. Yapi

2.1 介紹

YApi 是高效、易用、功能強大的 api 管理平臺,旨在為開發、產品、測試人員提供更優雅的接口管理服務。可以幫助開發者輕松創建、發布、維護 API,YApi 還為用戶提供了優秀的交互體驗,開發人員只需利用平臺提供的接口數據寫入工具以及簡單的點擊操作就可以實現接口的管理。

YApi讓接口開發更簡單高效,讓接口的管理更具可讀性、可維護性,讓團隊協作更合理。

源碼地址: https://github.com/YMFE/yapi

官方文檔: https://hellosean1025.github.io/yapi/

要使用YApi,項目組需要自己進行部署,在本項目中我們可以使用課程提供的平臺進行測試,域名: https://mock-java.itheima.net/

2.2 使用

2.2.1 準備

注冊賬號,登錄平臺

2.2.2 定義接口

登錄到Yapi平臺之后,我們可以創建項目,在項目下創建接口分類,在對應的分類中添加接口。

1). 創建項目

2). 添加分類

在當前項目中,有針對于員工、菜品、套餐、訂單的操作,我們在進行接口維護時,可以針對接口進行分類,如果沒有對應的分類,我們自己添加分類。

3). 添加接口

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

但是目前,接口中我們并未指定請求參數,響應數據等信息,我們可以進一步點擊編輯,對該接口 詳情進行編輯處理。

4). 運行接口

Yapi也提供了接口測試功能,當我們接口編輯完畢后,后端服務的代碼開發完畢,啟動服務,就可以使用Yapi進行接口測試了。

注意: 由于菜品分頁查詢接口,是需要登錄后才可以訪問的,所以在測試該接口時,需要先請求員工管理接口中的登錄接口,登錄完成后,再訪問該接口。

在Yapi平臺中,將接口文檔定義好了之后,前后端開發人員就需要根據接口文檔中關于接口的描述進行前端和后端功能的開發。

2.2.3 導出接口文檔

在Yapi平臺中我們不僅可以在線閱讀文檔,還可以將Yapi中維護的文檔直接導出來,可以導出md,json,html格式,在導出時自行選擇即可 。

而在導出的html文件或md文件中,主要描述的就是接口的基本信息, 包括: 請求路徑、請求方式、接口描述、請求參數、返回數據等信息。展示形式如下:

image-20210901150401976
2.2.4 導入接口文檔

上述我們講解了接口文檔的導出,我們也可以將外部的接口文檔導入到Yapi的平臺中,這樣我們就不用一個接口一個接口的添加了。我們可以將課程資料中提供的json格式的接口文檔直接導入Yapi平臺中來。

image-20210901151127926

導入過程中出現的確認彈窗,選擇"確認"。

image-20210901151508478

導入成功之后,我們就可以在Yapi平臺查看到已導入的接口。

3. Swagger

3.1 介紹

官網:https://swagger.io/

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>

3.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.3 查看接口文檔

經過上面的集成配置之后,我們的項目集成Swagger及Knife4j就已經完成了,接下來我們可以重新啟動項目,訪問接口文檔,訪問鏈接為: http://localhost:8080/doc.html

我們可以看到,在所有的Controller中提供的所有的業務增刪改查的接口,全部都已經自動生成了,我們通過接口文檔可以看到請求的url、請求方式、請求參數、請求實例、響應的參數,響應的示例。 并且呢,我們也可以通過這份在線的接口文檔,對接口進行測試。

注意: 由于我們服務端的Controller中的業務增刪改查的方法,都是必須登錄之后才可以訪問的,所以,我們在測試時候,也是需要先訪問登錄接口。登錄完成之后,我們可以再訪問其他接口進行測試。

我們不僅可以在瀏覽器瀏覽生成的接口文檔,Knife4j還支持離線文檔,對接口文檔進行下載,支持下載的格式有:markdown、html、word、openApi。

3.4 常用注解

3.4.1 問題說明

在上面我們直接訪問Knife4j的接口文檔頁面,可以查看到所有的接口文檔信息,但是我們發現,這些接口文檔分類及接口描述都是Controller的類名(駝峰命名轉換而來)及方法名,而且在接口文檔中,所有的請求參數,響應數據,都沒有中文的描述,并不知道里面參數的含義,接口文檔的可讀性很差。

3.4.2 注解介紹

為了解決上述的問題,Swagger提供了很多的注解,通過這些注解,我們可以更好更清晰的描述我們的接口,包含接口的請求參數、響應數據、數據模型等。核心的注解,主要包含以下幾個:

注解位置說明
@Api加載Controller類上,表示對類的說明
@ApiModel類(通常是實體類)描述實體類的作用
@ApiModelProperty屬性描述實體類的屬性
@ApiOperation方法說明方法的用途、作用
@ApiImplicitParams方法表示一組參數說明
@ApiImplicitParam方法用在@ApiImplicitParams注解中,指定一個請求參數的各個方面的屬性
3.4.3 注解測試

1). 實體類

可以通過 @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;
}

2). 響應實體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(); //動態數據//省略靜態方法 ....
}    

3). 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);}
}

4). 重啟服務測試

我們上述通過Swagger的注解,對實體類及實體類中的屬性,以及Controller和Controller的方法進行描述,接下來,我們重新啟動服務,然后看一下自動生成的接口文檔有何變化。

在接口文檔的頁面中,我們可以看到接口的中文描述,清晰的看到每一個接口是做什么的,接口方法參數什么含義,參數是否是必填的,響應結果的參數是什么含義等,都可以清楚的描述出來。

總之,我們要想清晰的描述一個接口,就需要借助于Swagger給我們提供的注解。

4. 項目部署

在本章節,我們要做的是項目的部署,包含前端項目的部署,及后端項目的部署。

4.1 部署架構

PC端: 主要是為餐廳的員工及管理員使用的后臺管理系統,對分類、菜品、套餐信息進行維護。

移動端: 可以基于微信公眾號或小程序實現,我們課上并未實現,這部分的工作是前端開發人員需要開發的。

前端部署服務器: Nginx

后端部署服務器: Tomcat(內嵌)

4.2 環境說明

由于我們的服務器數量有限,就使用這三臺服務器,具體的軟件規劃如下:

服務器軟件名稱
192.168.138.100Nginx(部署前端項目、配置反向代理),MySQL(主從復制的主庫)服務器A
192.168.138.101JDK1.8、Git、Maven、jar(項目jar包基于內嵌Tomcat運行)、MySQL(主從復制的從庫)服務器B
172.17.2.94Redis(緩存中間件)服務器C

由于我們前面的課程中Nginx、MySQL的主從復制、Redis、JDK、Git、Maven都已經演示過安裝及配置了,這里我們就不再演示軟件的安裝了。

4.3 前端部署

1). 在服務器A(192.168.138.100)中安裝Nginx,將課程資料中的dist目錄上傳到Nginx的html目錄下

將整個dist目錄上傳至/usr/local/nginx/html目錄下

2). 修改Nginx配置文件nginx.conf

將nginx.conf配置文件中,將原有的監聽80, 82, 8080端口號 的虛擬主機注釋掉,引入如下的配置信息:

    server {listen       80;server_name  localhost;location / {root   html/dist;index  index.html;}location ^~ /api/ {rewrite ^/api/(.*)$ /$1 break;proxy_pass http://192.168.138.101:8080;}location = /50x.html {root   html;}}

3). 通過nginx訪問前端工程

http://192.168.138.100

4.4 反向代理配置

前端工程部署完成之后,我們可以正常的訪問到系統的登錄頁面,點擊登錄按鈕,可以看到服務端發起的請求,請求信息如下:

而大家知道,在我們之前開發的工程中,是沒有/api這個前綴的,那這個時候,在不修改服務端代碼的情況下,如何處理該請求呢?

實際上,通過nginx的就可以輕松解決這個問題。

在上述我們配置的nginx.conf中,除了配置了靜態資源的加載目錄以外,我們還配置了一段反向代理的配置,配置信息如下:

location ^~ /api/ {rewrite ^/api/(.*)$ /$1 break;proxy_pass http://192.168.138.101:8080;
}

這一段配置代表,如果請求當前nginx,并且請求的路徑如果是 /api/ 開頭,將會被該location處理。而在該location中,主要配置了兩塊兒信息: rewrite(url重寫) 和 proxy_pass(反向代理)。 接下來我們就來解析一下這兩項的配置。

1). 路徑重寫rewrite

rewrite ^/api/(.*)$ /$1 break;

這里寫的是一個正則表達式,代表如果請求路徑是以 /api/ 開頭,后面的請求路徑任意,此時將原始的url路徑重寫為 /$1,這里的$1指代的就是通配符 .* 這一塊的內容。比如:

/api/employee/login ------> ^/api/(.*)$ --------> 此時 (.*) 匹配的就是 employee/login ------> 最終重寫為/$1 : /employee/login

2). 反向代理

proxy_pass http://192.168.138.101:8080;

路徑重寫后的請求,將會轉發到后端的 http://192.168.138.101:8080 服務器中。 而這臺服務器中,就部署的是我們的后端服務。

4.5 服務端部署

1). 在服務器B(192.168.138.101)中安裝jdk、git、maven、MySQL,使用git clone命令將git遠程倉庫的代碼克隆下來

A. 確認JDK環境

B. 確認Git環境

C. 確認Maven環境

D. 將我們開發完成的代碼推送至遠程倉庫,并在服務器B中克隆下來

#創建java代碼存放目錄
mkdir -p /usr/local/javaapp#切換目錄
cd /usr/local/javaapp#克隆代碼 , 需要使用自己的遠程倉庫
git clone https://gitee.com/ChuanZhiBoKe/reggie_take_out.git 

2). 將資料中提供的reggieStart.sh文件上傳到服務器B,通過chmod命令設置執行權限

3). 執行reggieStart.sh腳本文件,自動部署項目

執行完shell腳本之后,我們可以通過 ps -ef|grep java 指令,查看服務是否啟動。

4). 訪問系統測試

http://192.168.138.101/

4.6 圖片展示問題處理

在上述的測試中,我們發現菜品的圖片無法正常展示。原因是因為,在我們的配置文件中,圖片信息依然是從 D:/img 中加載的,但是在Linux服務器中,是不存在D盤的。

1). 修改文件存儲目錄

將文件存儲目錄修改為:

reggie:path: /usr/local/img/

修改完成之后,需要將變動的代碼提交到本地倉庫,并推送至遠程倉庫。

2). 執行shell腳本,進行自動化部署

3). 將本地的測試圖片文件夾img(整個文件夾)上傳到服務器B的/usr/local目錄下

4).訪問測試

http://192.168.138.101/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/42965.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/42965.shtml
英文地址,請注明出處:http://en.pswp.cn/web/42965.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Redis實戰—秒殺優化(Redis消息隊列)

回顧 我們回顧一下前文下單的流程&#xff0c;當用戶發起請求&#xff0c;此時會請求nginx&#xff0c;nginx會訪問到tomcat&#xff0c;而tomcat中的程序&#xff0c;會進行串行操作&#xff0c;分成如下幾個步驟。 1、查詢優惠卷 2、判斷秒殺庫存是否足夠 …

【代碼隨想錄算法訓練營第六十三天|卡碼網117.軟件構造、47.參加科學大會】

文章目錄 117.軟件構造47.參加科學大會 117.軟件構造 本體考察的是拓撲排序的思路&#xff0c;對于所有的有向無環圖進行拓撲排序后輸出的長度一定是和原結點數相同的。整體思路是找到當前所有的入度為0的結點&#xff0c;添加到結果中&#xff0c;并且查看對應的后續結點將其…

文獻筆記|綜述|When Large Language Model Meets Optimization

When Large Language Model Meets Optimization 題目&#xff1a;當大型語言模型遇到優化時 作者&#xff1a;Sen Huang , Kaixiang Yang , Sheng Qi and Rui Wang 來源&#xff1a;arXiv 單位&#xff1a;華南理工大學 文章目錄 When Large Language Model Meets Optimization…

springboot打包異常 Type org.springframework.boot.maven.RepackageMojo not present

解決&#xff1a; 項目在本地時可以正常啟動的,但是打包就報錯,經過分析得出,應該是打包依賴的問題,解決方法: 在pom文件中的build—>plugins---->plugin中添加spring-boot-maven-plugin依賴的版本號如下: 2.4.3 指定版本號即可。

IT審計必看!對比舊版,CISA考試改版升級亮點和重點內容是什么?

官方通知&#xff0c;今年8月1日&#xff0c;CISA新版考綱正式上線&#xff0c;舊版在7月23日后就無法約考了。 艾威培訓邀請了國內知名的IT審計CISA授課老師吳老師來為大家詳細講解CISA新版考綱的變化 目前第28th版教材只有英文版&#xff0c;中文版尚未發布。我們艾威經驗豐…

Jetson-AGX-Orin多網卡綁定網卡名

Jetson-AGX-Orin多網卡綁定網卡名 ? Jetson-AGX-Orin當通過USB接口或者Type-C口插入網卡設備后&#xff0c;重新上電Orin設備后&#xff0c;網卡設備的網卡名與Orin本身的以太網網卡名會發生交換。導致兩個網卡設備配置發生錯亂&#xff0c;兩個網卡都將不通。 可以通過將網…

出道即包攬多項榮譽,Shokz韶音OpenFit Air拿下日本VGP金獎

說到盛夏的日本&#xff0c;你會想到什么&#xff1f;花火大會&#xff1f;但對于消費電子行業來講&#xff0c;日本每年發布的VGP Summer獎項&#xff0c;才是每年盛夏時節行業內最大的慶典。而在今年的VGP 2024 Summer評選中&#xff0c;Shokz韶音在今年4月份剛發布的開放式耳…

開放式耳機音質哪個品牌的好?盤點幾款音質好品牌

在音樂的世界里&#xff0c;每一分貝的振動都承載著情感與故事。對于追求極致音質體驗的我們來說&#xff0c;耳機不僅是聆聽的工具&#xff0c;更是通往音樂靈魂深處的橋梁。而開放式耳機&#xff0c;以其獨有的聲學構造和聽覺享受&#xff0c;引領我們進入一個更為開闊的音樂…

ChatGPT 5.0:一年后的猜想

對于ChatGPT 5.0在未來一年半后的展望與看法&#xff0c;我們可以從以下幾個方面進行詳細探討&#xff1a; 一、技術提升與功能拓展 語言翻譯能力&#xff1a; ChatGPT 5.0在語言翻譯方面有望實現更大突破。據推測&#xff0c;新版本將利用更先進的自然語言處理技術和深度學習…

ONNX加載模型問題總結

輸入參數類型問題 run函數的參數列表如下&#xff1a; SessionImpl::Run(const Ort::RunOptions&, const char* const*, const Ort::Value*, size_t, const char* const*, Ort::Value*, size_t) 注意需要輸入輸出的參數名字形式是const char* const* 方式1 const char* 數…

vue中,圖片在div中按照圖片原來大小等比例顯示

圖片在div中按照圖片原來大小等比例顯示&#xff0c;可以保證web上顯示的圖片和實際圖片形狀一樣&#xff0c;保留原始圖片效果 實現代碼如下&#xff1a; <div style"padding: 0; width:400px;height:400px;position: absolute;border: 1px solid #eff2f6;">…

如何探索高效知識管理:FlowUs知識庫體驗很好

在當今信息爆炸的時代&#xff0c;有效的知識管理對于個人和團隊的發展至關重要。FlowUs 知識庫作為一款創新的知識管理工具&#xff0c;正逐漸成為眾多用戶的首選&#xff0c;為他們帶來了高效、便捷和有條理的知識管理體驗。 FlowUs 知識庫的一大特色在于其簡潔直觀的界面設計…

【ai_agent】從零寫一個agent框架(五)基于egui制作一個agent/workflow在線編輯器

前言 上篇我們實現了基礎節點&#xff0c;并暴露出grpc服務&#xff0c;但是手動編輯文本制作一個workflow實在強人所難。 所以本文我們做個webui自動生成workflow。 開搞之前先看看別人怎么做的。 Dify 的ui 效果如下圖示&#xff1a; 支持多種功能節點 但只能打開一個節…

【spark】Exception in thread “main“ ExitCodeException exitCode=-1073741701

在window上運行spark程序寫到本地文件的時候報錯。 val rdd sc.sparkContext.parallelize(list)val arr rdd.collect()arr.foreach(println)rdd.saveAsTextFile("test1")sc.close()錯誤信息: zhangsan lisi wangwu Exception in thread "main" ExitCode…

如何在電子文件上加蓋印章

在電子文件上加蓋印章&#xff0c;可以通過多種方法實現&#xff0c;主要包括使用專業軟件、在線工具以及圖片編輯軟件等。以下是一些具體步驟和方法&#xff1a; 一、使用專業軟件 PDF編輯工具&#xff1a; 啟動常用的PDF編輯軟件&#xff0c;如Adobe Acrobat、PhantomPDF等…

紅日靶場----(三)漏洞利用

上期已經信息收集階段已經完成&#xff0c;接下來是漏洞利用。 靶場思路 通過信息收集得到兩個吧靶場的思路 1、http://192.168.195.33/phpmyadmin/&#xff08;數據庫的管理界面&#xff09; root/root 2、http://192.168.195.33/yxcms/index.php?radmin/index/login&am…

阿里云通義千問開源兩款語音基座模型分別是SenseVoice和CosyVoice

阿里巴巴近期發布了開源語音大模型項目FunAudioLLM&#xff0c;該項目包含了兩個核心模型&#xff1a;SenseVoice和CosyVoice。可以精準多語言識別并且進行語音克隆。 SenseVoice&#xff1a;精準多語言識別與情感辨識 SenseVoice主要致力于高精度多語言語音識別、情感辨識和…

使用八股搭建神經網絡

神經網絡搭建八股 使用tf.keras 六步法搭建模型 1.import 2.train, test 指定輸入特征/標簽 3.model tf.keras.model.Sequential 在Squential,搭建神經網絡 4.model.compile 配置訓練方法&#xff0c;選擇哪種優化器、損失函數、評測指標 5.model.fit 執行訓練過程&a…

送給我親愛的Python

親愛的 Python&#xff0c; 在萬物皆代碼的世界里&#xff0c;你是我最優雅、最高效的算法。自從第一次遇見你&#xff0c;在那行“Hello, World!”之后&#xff0c;我的世界就被點亮了。你的簡潔性和強大的功能&#xff0c;讓我深深著迷&#xff0c;就像一個精心設計的函數&am…

數據結構雙向循環鏈表

主程序 #include "fun.h" int main(int argc, const char *argv[]) { double_p Hcreate_head(); insert_head(H,10); insert_head(H,20); insert_head(H,30); insert_head(H,40); insert_tail(H,50); show_link(H); del_tail(H); …