Swagger的安装以及SpringBoot整合Swagger2实现SwaggerAPI文档测试

news/2024/12/4 4:03:21/

前言

本篇博客是本人在网上学习Swagger所产出的个人笔记。主要内容有:
1.Swagger的安装
2.Swagger的介绍
3.Swagger2中常用的注解
4.快速上手案例

准备工作:Swagger Editor安装与启动

  • 1.下载Swagger-Editor。直接下载zip文件地址并解压
    • 下载zip文件网址: https://swagger.io/download-page/**
  • 2.下载并且安装node.js
  • 3.npm install -g http-server
  • 4.进入swagger-editor文件夹。运行http-server命令。
  • 5.在浏览器中输入http://127.0.0.1:8080即可看到Swagger-Editor的界面(看到如下图就说名OK了)
    在这里插入图片描述

1.什么是 Swagger

Swagger 是一系列 RESTful API 的工具,通过 Swagger 可以获得项目的一种交互式文档,客户端 SDK 的自动生成等功能。

Swagger 的目标是为 REST APIs 定义一个标准的、与语言无关的接口,使人和计算机在看不到源码或者看不到文档或者不能通过网络流量检测的情况下,能发现和理解各种服务的功能。当服务通过 Swagger 定义,消费者就能与远程的服务互动通过少量的实现逻辑。类似于低级编程接口,Swagger 去掉了调用服务时的很多猜测。

Swagger(丝袜哥)是世界上最流行的 API 表达工具。

Swagger 是一个简单但功能强大的 API 表达工具。它具有地球上最大的 API 工具生态系统,数以千计的开发人员,使用几乎所有的现代编程语言,都在支持和使用 Swagger。使用 Swagger 生成 API,我们可以得到交互式文档,自动生成代码的 SDK 以及 API 的发现特性等。

使用 Spring Boot 集成 Swagger 的理念是,使用注解来标记出需要在 API 文档中展示的信息,Swagger 会根据项目中标记的注解来生成对应的 API 文档。Swagger 被号称世界上最流行的 API 工具,它提供了 API 管理的全套解决方案,API 文档管理需要考虑的因素基本都包含,这里将讲解最常用的定制内容。

2.Swagger常用注解

Swagger 通过注解表明该接口会生成文档,包括接口名、请求方法、参数、返回信息等,常用注解内容如下:

作用范围API使用位置
协议集描述@Api用于 Controller 类上
协议描述@ApiOperation用在 Controller 的方法上
非对象参数集@ApiImplicitParams用在 Controller 的方法上
非对象参数描述@ApiImplicitParam用在 @ApiImplicitParams 的方法里边
响应集@ApiResponses用在 Controller 的方法上
响应信息参数@ApiResponse用在 @ApiResponses 里边
描述返回对象的意义@ApiModel用在返回对象类上
对象属性@ApiModelProperty用在出入参数对象的字段上

@Api 的使用

Api 作用在 Controller 类上,做为 Swagger 文档资源,该注解将一个 Controller(Class)标注为一个 Swagger 资源(API)。在默认情况下,Swagger-Core 只会扫描解析具有 @Api 注解的类,而会自动忽略其他类别资源(JAX-RS endpoints、Servlets 等)的注解。

使用示例:

@Api(value = "测试",description = "swaggerAPI测试",position = 100,protocols = "http")
@RestController
@RequestMapping("/")
public class TestController {
}

与 Controller 注解并列使用,属性配置如表所示:

属性名称备注
valueurl 的路径值
tags如果设置这个值,value 的值会被覆盖
description对 API 资源的描述
producesFor example, “application/json, application/xml”
consumesFor example, “application/json, application/xml”
protocolsPossible values: http, https, ws, wss
authorizations高级特性认证时配置
hidden配置为 true 将在文档中隐藏

ApiOperation 的使用

ApiOperation 定义在方法上,描述方法名、方法解释、返回信息、标记等信息。

使用示例:

@ApiOperation(value = "消息列表",notes = "完整的消息内容列表",produces="application/json, application/xml",consumes="application/json, application/xml",response = List.class)
@GetMapping(value = "messages")
public List<Message> list() {
}
属性名称备注
valueurl 的路径值
tags如果设置这个值、value的 值会被覆盖
producesFor example, “application/json, application/xml”
consumesFor example, “application/json, application/xml”
protocolsPossible values: http, https, ws, wss
authorizations高级特性认证时配置
hidden配置为 true 将在文档中隐藏
response返回的对象
responseContainer这些对象是有效的 “List”, “Set” or “Map”,其他无效
httpMethod“GET”、“HEAD”、“POST”、“PUT”、“DELETE”、“OPTIONS” and “PATCH”
codehttp 的状态码 默认 200
extensions扩展属性

@ApiImplicitParams 和 @ApiImplicitParam 的使用

@ApiImplicitParams 用于描述方法的返回信息,和 @ApiImplicitParam 注解配合使用;@ApiImplicitParam 用来描述具体某一个参数的信息,包括参数的名称、类型、限制等信息。

使用示例:

@ApiOperation(value = "添加消息", notes = "根据参数创建消息")@ApiImplicitParams({@ApiImplicitParam(name = "id", value = "消息 ID", required = true, dataType = "Long", paramType = "query"),@ApiImplicitParam(name = "text", value = "正文", required = true, dataType = "String", paramType = "query"),@ApiImplicitParam(name = "summary", value = "摘要", required = false, dataType = "String", paramType = "query"),
})
@PostMapping(value = "message")
public Message create(Message message) {
}
属性名称备注
name接收参数名
value接收参数的意义描述
required参数是否必填值为 true 或者 false
dataType参数的数据类型只作为标志说明,并没有实际验证
paramType查询参数类型,其值: path 以地址的形式提交数据 query 直接跟参数完成自动映射赋 body 以流的形式提交,仅支持 POST header 参数在 request headers 里边提交 form 以 form 表单的形式提交 仅支持 POST
defaultValue默认值

@ApiImplicitParam注解的dataType、paramType两个属性的区别?

比如:

@ApiImplicitParam(name = "id",value = "用户id",required = true,dataType = "int",paramType = "body")

dataType=“int” 代表请求参数类型为int类型,当然也可以是Map、User、String等;

paramType=“body” 代表参数应该放在请求的什么地方:
header–>放在请求头。请求参数的获取:@RequestHeader(代码中接收注解)
query–>用于get请求的参数拼接。请求参数的获取:@RequestParam(代码中接收注解)
path(用于restful接口)–>请求参数的获取:@PathVariable(代码中接收注解)
body–>放在请求体。请求参数的获取:@RequestBody(代码中接收注解)
form(不常用)

@ApiResponses 和 @ApiResponse 的使用

@ApiResponses 主要封装方法的返回信息和 @ApiResponse 配置起来使用,@ApiResponse 定义返回的具体信息包括返回码、返回信息等。

使用示例:

@ApiOperation(value = "修改消息", notes = "根据参数修改消息")
@PutMapping(value = "message")
@ApiResponses({@ApiResponse(code = 100, message = "请求参数有误"),@ApiResponse(code = 101, message = "未授权"),@ApiResponse(code = 103, message = "禁止访问"),@ApiResponse(code = 104, message = "请求路径不存在"),@ApiResponse(code = 200, message = "服务器内部错误")
})
public Message modify(Message message) {
}
属性名称备注
codehttp 的状态码
message描述
response默认响应类 Void
reference参考
responseHeaders封装返回信息
responseContainer字符串

@ApiModel 和 @ApiModelProperty 的使用

在实际的项目中我们常常会封装一个对象作为返回值,@ApiModel 就是负责描述对象的信息,@ApiModelProperty 负责描述对象中属性的相关内容。

使用示例:

@ApiModel(description = "响应对象")
public class BaseResult<T> {private static final int SUCCESS_CODE = 0;private static final String SUCCESS_MESSAGE = "成功";@ApiModelProperty(value = "响应码", name = "code", required = true, example = "" + SUCCESS_CODE)private int code;@ApiModelProperty(value = "响应消息", name = "msg", required = true, example = SUCCESS_MESSAGE)private String msg;@ApiModelProperty(value = "响应数据", name = "data")private T data;
}

属性配置如下表所示:

属性名称备注
value属性描述
name如果配置覆盖属性名称
allowableValues允许的值
access可以不配置
notes没有使用
dataType数据类型
required是否为必传参数
position显示的顺序位置
hidden是否因此
example举例
readOnly只读
reference引用

3.快速上手

我们用一个例子来演示一下,使用SpringBoot整合Swagger2,实现SwaggerAPI文档测试。

这里我准备了一张商品表,对商品表中的数据进行CRUD,并使用swagger测试文档对接口进行测试

CREATE TABLE `tb_sku` (`id` varchar(20) NOT NULL COMMENT '商品id',`sn` varchar(100) NOT NULL COMMENT '商品条码',`name` varchar(200) NOT NULL COMMENT 'SKU名称',`price` int(20) NOT NULL COMMENT '价格(分)',`num` int(10) NOT NULL COMMENT '库存数量',`alert_num` int(11) DEFAULT NULL COMMENT '库存预警数量',`image` varchar(200) DEFAULT NULL COMMENT '商品图片',`images` varchar(2000) DEFAULT NULL COMMENT '商品图片列表',`weight` int(11) DEFAULT NULL COMMENT '重量(克)',`create_time` datetime DEFAULT NULL COMMENT '创建时间',`update_time` datetime DEFAULT NULL COMMENT '更新时间',`spu_id` varchar(20) DEFAULT NULL COMMENT 'SPUID',`category_id` int(10) DEFAULT NULL COMMENT '类目ID',`category_name` varchar(200) DEFAULT NULL COMMENT '类目名称',`brand_name` varchar(100) DEFAULT NULL COMMENT '品牌名称',`spec` varchar(200) DEFAULT NULL COMMENT '规格',`sale_num` int(11) DEFAULT '0' COMMENT '销量',`comment_num` int(11) DEFAULT '0' COMMENT '评论数',`status` char(1) DEFAULT '1' COMMENT '商品状态 1-正常,2-下架,3-删除',PRIMARY KEY (`id`),KEY `cid` (`category_id`),KEY `status` (`status`),KEY `updated` (`update_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';INSERT INTO tb_sku (id, sn, name, price, num, alert_num, image, images, weight, create_time, update_time, spu_id, category_id, category_name, brand_name, spec, sale_num, comment_num, status) VALUES('100000003145', '', 'vivo X23 8GB+128GB 幻夜蓝 水滴屏全面屏 游戏手机 移动联通电信全网通4G手机', 95900, 10000, 100, 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t1/4612/28/6223/298257/5ba22d66Ef665222f/d97ed0b25cbe8c6e.jpg!q70.jpg.webp', 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t1/4612/28/6223/298257/5ba22d66Ef665222f/d97ed0b25cbe8c6e.jpg!q70.jpg.webp', 10, '2019-05-01 00:00:00.0', '2019-05-01 00:00:00.0', '889527500', 0, '手机', 'vivo', '{''颜色'': ''红色'', ''版本'': ''8GB+128GB''}', 0, 0, '1');
INSERT INTO tb_sku (id, sn, name, price, num, alert_num, image, images, weight, create_time, update_time, spu_id, category_id, category_name, brand_name, spec, sale_num, comment_num, status) VALUES('100000004580', '', '薇妮(viney)女士单肩包 时尚牛皮女包百搭斜挎包女士手提大包(经典黑)', 87900, 10000, 100, 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t5590/64/5811657380/234462/5398e856/5965e173N34179777.jpg!q70.jpg.webp', 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t5590/64/5811657380/234462/5398e856/5965e173N34179777.jpg!q70.jpg.webp', 10, '2019-05-01 00:00:00.0', '2019-05-01 00:00:00.0', '451277100', 0, '真皮包', 'viney', '{''颜色'': ''黑色''}', 0, 0, '1');
INSERT INTO tb_sku (id, sn, name, price, num, alert_num, image, images, weight, create_time, update_time, spu_id, category_id, category_name, brand_name, spec, sale_num, comment_num, status) VALUES('100000006163', '', '巴布豆(BOBDOG)柔薄悦动婴儿拉拉裤XXL码80片(15kg以上)', 67100, 9999, 100, 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t23998/350/2363990466/222391/a6e9581d/5b7cba5bN0c18fb4f.jpg!q70.jpg.webp', 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t23998/350/2363990466/222391/a6e9581d/5b7cba5bN0c18fb4f.jpg!q70.jpg.webp', 10, '2019-05-01 00:00:00.0', '2019-05-01 00:00:00.0', '10000000616300', 1124, '拉拉裤', '巴布豆', '{}', 1, 0, '1');
INSERT INTO tb_sku (id, sn, name, price, num, alert_num, image, images, weight, create_time, update_time, spu_id, category_id, category_name, brand_name, spec, sale_num, comment_num, status) VALUES('100000011113', '', '莎米特SUMMIT拉杆箱22英寸PC材质万向轮旅行箱行李箱PC154T4A可扩容 法拉利红', 78900, 10000, 100, 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t1/25363/12/2929/274060/5c21df3aE1789bda7/030af31afd116ae0.jpg!q70.jpg.webp', 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t1/25363/12/2929/274060/5c21df3aE1789bda7/030af31afd116ae0.jpg!q70.jpg.webp', 10, '2019-05-01 00:00:00.0', '2019-05-01 00:00:00.0', '595502400', 0, '拉杆箱', '莎米特', '{''颜色'': ''红色''}', 0, 0, '1');
INSERT INTO tb_sku (id, sn, name, price, num, alert_num, image, images, weight, create_time, update_time, spu_id, category_id, category_name, brand_name, spec, sale_num, comment_num, status) VALUES('100000011127', '', '莎米特SUMMIT拉杆箱22英寸PC材质万向轮旅行箱行李箱PC154T4A可扩容 米白', 26600, 10000, 100, 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t1/25363/12/2929/274060/5c21df3aE1789bda7/030af31afd116ae0.jpg!q70.jpg.webp', 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t1/25363/12/2929/274060/5c21df3aE1789bda7/030af31afd116ae0.jpg!q70.jpg.webp', 10, '2019-05-01 00:00:00.0', '2019-05-01 00:00:00.0', '595502400', 0, '拉杆箱', '莎米特', '{''颜色'': ''米色''}', 0, 0, '1');
INSERT INTO tb_sku (id, sn, name, price, num, alert_num, image, images, weight, create_time, update_time, spu_id, category_id, category_name, brand_name, spec, sale_num, comment_num, status) VALUES('100000015158', '', '华为 HUAWEI 麦芒7 6G+64G 魅海蓝 全网通  前置智慧双摄  移动联通电信4G手机 双卡双待', 40800, 9998, 100, 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t22642/312/2563982615/103706/1398b13d/5b865bb3N0409f0d0.jpg!q70.jpg.webp', 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t22642/312/2563982615/103706/1398b13d/5b865bb3N0409f0d0.jpg!q70.jpg.webp', 10, '2019-05-01 00:00:00.0', '2019-05-01 00:00:00.0', '10000001516600', 106, '手机', '华为', '{''颜色'': ''蓝色''}', 2, 0, '1');
INSERT INTO tb_sku (id, sn, name, price, num, alert_num, image, images, weight, create_time, update_time, spu_id, category_id, category_name, brand_name, spec, sale_num, comment_num, status) VALUES('100000015166', '', '华为 HUAWEI 麦芒7 6G+64G 亮黑色 全网通  前置智慧双摄  移动联通电信4G手机 双卡双待', 89200, 10000, 100, 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t22642/312/2563982615/103706/1398b13d/5b865bb3N0409f0d0.jpg!q70.jpg.webp', 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t22642/312/2563982615/103706/1398b13d/5b865bb3N0409f0d0.jpg!q70.jpg.webp', 10, '2019-05-01 00:00:00.0', '2019-05-01 00:00:00.0', '10000001516600', 106, '手机', '华为', '{''颜色'': ''黑色''}', 0, 0, '1');
INSERT INTO tb_sku (id, sn, name, price, num, alert_num, image, images, weight, create_time, update_time, spu_id, category_id, category_name, brand_name, spec, sale_num, comment_num, status) VALUES('100000022652', '', 'vivo Y81s 刘海全面屏 3GB+32GB 香槟金 移动联通电信4G手机', 11700, 10000, 100, 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t20707/78/2349564629/130172/50a245d8/5b8e00e2Nf0bcd624.jpg!q70.jpg.webp', 'https://m.360buyimg.com/mobilecms/s720x720_jfs/t20707/78/2349564629/130172/50a245d8/5b8e00e2Nf0bcd624.jpg!q70.jpg.webp', 10, '2019-05-01 00:00:00.0', '2019-05-01 00:00:00.0', '10000015453200', 0, '手机', 'vivo', '{''颜色'': ''槟色''}', 0, 0, '1');

项目结构

1.添加依赖包

<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.8.0</version>
</dependency>
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.8.0</version>
</dependency>

2.编写Swagger配置类

com.jn.config.SwaggerConfig.java

package com.jn.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;/*** @Author ScholarTang* @Date 2020/2/5 5:39 PM* @Desc swagger配置类*/@Configuration
@EnableSwagger2
public class SwaggerConfig {@Beanpublic Docket api() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()// 自行修改为自己的包路径.apis(RequestHandlerSelectors.basePackage("com.jn.controller")).paths(PathSelectors.any()).build();}public ApiInfo apiInfo() {return new ApiInfoBuilder()//swagger文档标题.title("swaggerAIP测试")//描述.description("测试 API 1.0 操作文档")//版本号.version("1.0").build();}
}

3.使用idea提供的工具生成domain & mapper & service

4.业务层代码

**com.jn.controller.SkuController.java**

package com.jn.controller;import com.jn.domain.Sku;
import com.jn.service.SkuService;
import com.jn.vo.Result;
import com.jn.vo.ResultUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** @Author ScholarTang* @Date 2020/2/5 9:46 PM* @Desc 处理商品相关的业务*/@Slf4j
@RestController
@RequestMapping("/sku")
@Api(value = "商品管理",description = "商品管理",position = 100,protocols = "http")
public class SkuController {@Autowiredprivate SkuService service;@ApiOperation(value = "查询所有商品记录",notes = "查询所有商品记录",produces="application/json, application/xml",consumes="application/json, application/xml",response = List.class)@GetMapping("/findAllSku")public Result<List<Sku>> findAllSku() {Result<List<Sku>> result;try {List<Sku> skuList = service.list();result = ResultUtils.success(skuList);} catch (Exception e) {e.printStackTrace();result = ResultUtils.fail();}return result;}@ApiOperation(value = "添加商品",notes = "添加商品",produces="application/json, application/xml",consumes="application/json, application/xml")@ApiImplicitParam(value = "商品数据",name = "sku",dataType = "Sku",paramType = "body")@PostMapping("/addSku")public Result addSku (@RequestBody Sku sku) {Result result;boolean insert = sku.insert();if (insert) {result = ResultUtils.success(insert);} else {result = ResultUtils.fail();}return result;}@ApiOperation(value = "修改商品",notes = "修改商品",produces="application/json, application/xml",consumes="application/json, application/xml")@ApiImplicitParam(value = "商品数据",name = "sku",dataType = "Sku",paramType = "body")@PutMapping("/updateSku")public Result updateSku (@RequestBody Sku sku) {Result result = new Result();boolean updateById = sku.updateById();if (updateById) {result = ResultUtils.success(updateById);} else {result = ResultUtils.fail();}return result;}@ApiOperation(value = "删除商品",notes = "删除商品",produces="application/json, application/xml",consumes="application/json, application/xml")@ApiImplicitParam(value = "商品ID",name = "id",dataType = "int",paramType = "query")@DeleteMapping("/deleteSkuById")public Result deleteSkuById(@RequestParam(value = "id") Integer id) {Result result;boolean removeById = service.removeById(id);if (removeById) {result = ResultUtils.success(removeById);} else {result = ResultUtils.fail();}return result;}
}

5.运行项目访问localhost:8080/swagger-ui.html (这个端口号是你项目的端口)

6.使用Try it out进行测试

使用 Swagger 创建的在线 API 还有一个非常强大的功能,可以在页面直接测试接口的可用性,这样在前端和后端接口调试出现问题时,可以非常方便地利用此功能进行接口验证。在上面参数讲解过程中,我们发现每个接口描述右侧都有一个按钮 try it out,单击 try it out 按钮即可进入表单页面,如下:

码云地址

https://gitee.com/Tang1314521/swagger-blog.git


http://www.ppmy.cn/news/341837.html

相关文章

细菌大盘点(二) | 葡萄球菌、沙门氏菌、弯曲杆菌

谷禾健康 介绍三种菌&#xff1a; 葡萄球菌、沙门氏菌、 弯曲杆菌 01 葡萄球菌 Staph 葡萄球菌是一群革兰氏阳性球菌&#xff0c;因常堆聚成葡萄串状&#xff0c;故名。多数为非致病菌&#xff0c;少数可导致疾病。可以生活在人的皮肤、口腔或鼻子里。 葡萄球菌有30多种&#…

国外保健品品牌介绍

在这个菜比肉贵&#xff0c;蛋比鸡贵的年代&#xff0c;每天吃饱自然没有问题&#xff0c;但要保证全面充分的营养摄入是比较困难、也是比较昂贵的事情&#xff1b;加上各种农药、杀虫剂的滥用&#xff0c;蔬菜瓜果能否吃的放心也是个问题。不少朋友除了崇尚健康的饮食之外&…

《科技之巅2》书摘

笔记摘自 科技之巅2 麻省理工科技评论 2017年10大全球突破性技术深度剖析 麻省理工科技评论 2017年10月7日 推荐序五 机器智能扩大了人类智商与智慧容量&#xff0c;每一代新技术工具都是人类“利己”的选择&#xff0c;而机器智能引起的部分企业员工阶段性转岗、失业&…

上海车展直击:哪吒汽车推出多款精品车型

4月19日&#xff0c;第十九届上海国际车展开幕。哪吒汽车以“因您而变、智见未来”为主题&#xff0c;携哪吒U Pro、哪吒S、哪吒V女生版三款车型&#xff0c;强势亮相4.1展馆4A05展位。此外&#xff0c;还展示了哪吒V樱花小魔女、傲世魔童两款特装车。 【哪吒汽车-家族车型矩阵…

灵界的科学丨五、心灵与意识的科学奥祕

摘自李嗣涔教授《灵界的科学》 每个人都有「自我意识」&#xff0c; 每天睡觉时「我」就不见了&#xff0c; 每天早上醒来时&#xff0c;「我」又回来了&#xff0c; 好像没有太大的改变&#xff0c; 这个「我」的物理现象是什么&#xff1f; 探索科学的最后疆界──意识 …

【GPU精粹与Shader编程】(二) 《GPU Gems 1》全书核心内容提炼总结 · 上篇

本文由浅墨_毛星云 出品&#xff0c;首发于知乎专栏&#xff0c;转载请注明出处 文章链接&#xff1a; https://zhuanlan.zhihu.com/p/35974789 题图背景来自《战神4》。 系列文章前言 我们知道&#xff0c;《GPU Gems》1~3 、《GPU Pro》1~7 以及《GPU Zen》组成的饕餮盛宴&a…

支持指纹模块的服务器,指纹模块

指纹模块是指纹锁的核心部件,安装在如指纹门禁或者硬盘等器件上,用来完成指纹的采集和指纹的识别的模块。指纹模块主要由指纹采集模块、指纹识别模块和扩展功能模块(如锁具驱动模块)组成。 中文名 指纹模块 外文名 fingerprint module 比对时间 <1秒认假率 0.0001[%] 拒真…

JavaScript 学习笔记(二)-- ECMAScript

ECMAScript 客户端脚本语言的标准 基本语法 与html结合方式 内部JS&#xff1a; 标签体内容就是js代码 <script text"text/javascript">// 内容 </script>外部JS&#xff1a; 通过src属性引入外部的js文件 <script text"text/javascript"…