一句话概括:基于springboot+swagger实现接口文档显示后,本文将给出在企业实践的进阶需求,包括接口按需过滤,前端mock数据,文档离线导出。

1.引言

在上一篇文章《springboot+swagger接口文档企业实践(上)》已对使用springboot+swagger的接口文档构建及配置进行了介绍,可以实时显示接口的输入输出,还可以调用接口调试。解决了后端开发人员写接口文档的难处。但在企业实践中,还有一些问题需要解决,如以下几种:

  • 发布指定的接口:不希望把全部的接口都对外发布提供,只需要发布指定的接口。
  • 发布指定版本接口:每一次版本迭代,只需要对变更和新增的接口进行说明,而不是每次都输出全部的接口(每次都全量发布接口,前端人员还得与后端沟通哪些是变更和新增接口,无疑会增加工作量)
  • mock接口数据:有了接口文档,前后端可以并行开发,此时前端需要模拟接口的返回数据来显示效果,测试内容等。
  • 离线导出接口文档:当前的接口文档是通过页面访问的,但有些企业(特别注重文档交付的企业)还是有一些特殊需求,需要离线的接口文档。

针对以上的情况,本文提供相应的解决方法,主要包含以下内容:

  1. 接口过滤:通过包过滤、类注解过滤、方法注解过滤、分组过滤等方式,实现按需发布指定接口的功能。
  2. 使用easy-mock+swagger实现mock数据。
  3. 使用maven插件实现接口文档的离线导出。

本文配套的示例工程地址https://github.com/mianshenglee/my-example/tree/master/springboot-swagger-demo/advance-swagger-demo,读者可fork或pull下来,结合学习。

2. swagger接口过滤

对于swagger的接口文档,在实践开发中,一般只需要发布指定的接口,按需发布即可,针对版本迭代,只需要对变更和新增的接口进行说明,而不是每次都输出全部的接口。这些需求都属于swagger的接口过滤功能。在springboot的swagger配置类(Swagger2Config.java)中,Docket提供了apis()paths()两个方法用于接口过滤,下面详细说明一下。

2.1 按包过滤(package)

一般接口都是写在控制器(controller)中,而controller一般都统一放在一个package中,这样,可以通过包过滤显示指定包的接口。通过在配置文件Swagger2Config.java中使用apis()函数进行过滤,把需要显示的接口使用函数进行返回,注意,此处的参数enableClassFilterenableMethodFiltergroupsFilters分别对应后面的过滤方法,定义如下:

  1. private List<Predicate<RequestHandler>> apisFilter(boolean enableClassFilter,boolean enableMethodFilter, String[]groupsFilters) {
  2. List<Predicate<RequestHandler>> apis = new ArrayList<>();
  3. String basePackageStr = swaggerInfo.getBasePackage();
  4. // 1.包过滤
  5. if (StrUtil.isNotEmpty(basePackageStr)) {
  6. //支持多个包
  7. String[] basePackages = basePackageStr.split(";");
  8. if (null != basePackages && basePackages.length > 0) {
  9. Predicate<RequestHandler> predicate = input -> {
  10. // 按basePackage过滤
  11. Class<?> declaringClass = input.declaringClass();
  12. String packageName = declaringClass.getPackage().getName();
  13. return Arrays.asList(basePackages).contains(packageName);
  14. };
  15. apis.add(predicate);
  16. }
  17. }
  18. return apis;
  19. }

此处代码作用是按配置项swagger.basePackage的包(多个包用;分隔),从接口所在类中获取包名,若包名是在配置的包内,则返回,并把匹配的内容使用List返回。然后在apis()调用时对返回值进行and操作Predicates.and(apisFilter()),这样,返回的内容就只是指定的包的接口描述。

2.2 按类注解过滤

接口一般是在Controller类中,对于springmvc的controller,都会使用@Controller进行注解,甚至前后端分离一般都是使用@RestController,因此,如果我们想只显示使用@RestController注解的类的接口,则可以对此进行过滤。在前面的apisFilter()方法中。使用isAnnotationPresent可判断是否有某注解,如下所示

  1. // 2.过滤被RestController注解的类
  2. if(enableClassFilter){
  3. Predicate<RequestHandler> predicate = input -> {
  4. Class<?> declaringClass = input.declaringClass();
  5. return declaringClass.isAnnotationPresent(RestController.class);
  6. };
  7. apis.add(predicate);
  8. }

2.3 按方法注解过滤

按类注解是把整个类过滤掉,粒度较大,如果只想按方法过滤,可以使用swagger的@ApiIgnore注解对接口进行过滤,有此注解则不显示。也可以通过判断是否存在某个指定方法注解来过滤。swagger的接口描述一般都用@ApiOperation,因此,可以通过判断接口是否存在此注解,如果没有则不显示。如下:

  1. // 3.过滤被ApiOperation注解的方法
  2. if(enableMethodFilter){
  3. apis.add(input -> input.isAnnotatedWith(ApiOperation.class));
  4. }

2.4 按分组过滤

swagger的接口文档如果没有指定groupName,则会默认以default作为分组名,对应的接口文档是v2/api-docs?group=default,它会按apis过滤后的全部接口显示出来。在迭代版本时,有个显示的需求是只需要显示当前版本变更和新增的接口。其实也是使用注解过滤的方式,结合groupName进行设置即可。具体如下:

2.4.1 定义注解ApiVersion

此注解需自定义,用于指定版本号,注意可以是多个版本(多版本兼容的情况)。

  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target(ElementType.METHOD)
  3. public @interface ApiVersion {
  4. /**
  5. * 接口版本号(对应swagger中的group)
  6. * @return String[]
  7. */
  8. String[] group();
  9. }

当开发新的版本,在变更和新增的接口中添加此注解,并把版本号写到对应的group中即可,如

  1. @ApiVersion(group = {"v1.0.0"})

2.4.2 添加ApiVersion过滤

apisFilter()函数中,添加以下过滤代码:

  1. // 4.过滤组
  2. if(groupsFilters !=null && groupsFilters.length >0){
  3. Predicate<RequestHandler> predicate = input -> {
  4. ApiVersion apiVersion = input.getHandlerMethod().getMethodAnnotation(ApiVersion.class);
  5. return apiVersion!=null && ArrayUtil.containsAny(apiVersion.group(),groupsFilters);
  6. };
  7. apis.add(predicate);
  8. }

从接口方法中获取ApiVersion注解,并获取它的group参数,通过与指定的分组进行比较,存在即显示,否则不显示。

2.4.3 新建指定版本号分组的Docket

添加新的一个Docket Bean,指定groupName为当前需要显示的版本号,并输入需要过滤的分组数组。如下:

  1. @Bean
  2. public Docket v100Api() {
  3. Docket docket = new Docket(DocumentationType.SWAGGER_2)
  4. .groupName(ApiVersionConstant.VERVION_100)
  5. ...//略
  6. ApiSelectorBuilder builder = docket.select();
  7. //指定需要过滤的版本号
  8. builder = builder.apis(Predicates.and(apisFilter(false,true,new String[]{ApiVersionConstant.VERVION_100})));
  9. ...//略
  10. return builder.build();
  11. }

经过上面的处理,显示的接口界面有两个分组,一个是default,一个是指定的版本号(v1.0.0),指定版本显示的接口即是当前版本变更或新增的接口描述,如下:

3. 接口mock数据

有了接口文档,前后端可以并行开发,此时前端需要模拟接口的返回数据来显示效果,测试内容。虽然swagger提供example属性,可以在返回结果中提供示例,但对于前端而言,单一的示例不足以满足显示和测试的需求。需要对数据按接口情况进行mock。easy-mock是一个很好的选择,它可以连接swagger,自动生成mock数据,也可以自定义mock规则。下面对easy-mock+swagger的使用进行描述。

3.1 easy-mock安装

根据easy-mock的官网介绍(官网经常挂掉,建议直接使用它的github私有部署), Easy Mock 是一个可视化,并且能快速生成模拟数据的持久化服务。 可以使用它的在线服务,也可以私有部署。它是开源项目,github地址https://github.com/easy-mock/easy-mock,具有以下特征:

它的官方文档github文档中,已经对easymock的安装和使用进行详细描述,读者可参考官方文档,此处只列出安装的关键点和需要注意的地方(本文使用的easy-mock及相关工具是在centos7上安装的)。

  1. 安装easy-mock前,需先安装了 Node.jsv8.x)、 MongoDB>= v3.4)、 Redis>= v4.0) ,且已正常运行。关于这几个软件的安装与运行,请读者自行查看官网教程。
  2. 安装 easy-mock。
  1. $ git clone https://github.com/easy-mock/easy-mock.git
  2. $ cd easy-mock && npm install
  1. 更改 easy-mock\config 文件夹下的配置文件 default.json,注意修改host为"0.0.0.0",修改连接mongodb的地址以及redis的host,端口等信息。
  2. 启动 easy-mock,这种不是在后台运行的方式,直接ctrl+c可关闭。
  1. $ npm run dev
  2. # 启动后访问 http://127.0.0.1:7300
  1. 使用pm2进行后台启动, 启动成功后,在命令行中输入 netstat -ntlp 查看正在使用的端口(如mongodb的27017,redis的6379,easy-mock的7300等)
  1. $ [sudo] npm install pm2 -g
  2. $ pm2 start app.js

easy-mock启动后,通过浏览器可以访问, 输入用户名和密码(如果用户不存在会自动注册)。

3.2 easy-mock + swagger实现mock数据

easy-mock是使用项目来进行接口管理,可以创建个人项目,也可以加入到其它人创建的项目,项目即是需要mock的接口。

3.2.1 创建项目并添加swagger地址

在创建项目时,可以设置swagger的接口文档地址,以此导入swagger的接口进行管理与模拟。前面提到,使用分组过滤可以按版本号来显示接口,因此,创建项目时,可以使用版本号作为项目名称,一个版本对应一个项目。这样,前端在mock数据时就可以针对当前版本进行处理。如下为示例项目中的v1.0.0版本(填写的swagger接口文档地址为v2/api-docs?group=v1.0.0):

填写swagger地址后,会自动导入对应的接口,与前端看到swaggger-ui.html的接口一致,执行测试时,也会按swgger的返回数据类型或example进行返回。

3.2.2 自定义模拟数据

模拟数据使用的是 Mock.js ,在其官网中有相应的文档、示例和代码。读者可以上去详细阅读。简单来说,mockjs提供了对StringNumberBooleanObjectArray等数据的模拟规则,只需按规则编写,即可生成随机数据,达到模拟数据效果。生成规则有 7 种格式:

  1. 'name|min-max': value
  2. 'name|count': value
  3. 'name|min-max.dmin-dmax': value
  4. 'name|min-max.dcount': value
  5. 'name|count.dmin-dmax': value
  6. 'name|count.dcount': value
  7. 'name|+step': value

使用了自定义的模拟数据后,需要注意以下几点:

  • 使用了自定义的模拟数据规则后,前端在使用此接口进行模拟数据时,原来在swagger中定义的示例和返回值就会被自定义的数据覆盖。
  • 当后端接口有变化,需要前端在easy-mock中重新同步新的swagger接口,同步前需要备份原来的自定义数据规则,否则,重新同步后,原来自定义的数据会swagger的接口定义覆盖。因此,最好是先备份,然后针对有改动的地方进行规则修改即可。

4.接口文档离线导出

一般在开发过程中使用swagger文档,直接使用浏览器访问swagger-ui.html页面即可满足要求,若有需求是需要导出离线接口文档,总体可以按以下思路进行:

  1. 使用swaggerv2/api-docs的url地址导出json文档(不导出也可以直接使用此url作为输入文档的地址)
  2. 使用swagger2markup工具将json文档转为asciidoc格式文档。
  3. 使用asciidoctor工具将asciidoc文件转html或pdf文件。

4.1 导出swagger的json文档

在浏览器中访问接口文档页面的地址是/swagger-ui.html,而swagger的规范文档的地址是/v2/api-docsctrl+s把此文件保存为json文件,如api-docs.json。在项目的根目录添加一个docs目录,用于存放离线文档相关内容,如下所示,分别建立对应文档格式的目录,并把api-docs.json放在swagger目录下:

  1. ├─asciidoc
  2. ├─html
  3. ├─pdf
  4. └─swagger
  5. └─api-docs.json

4.2 导出asciidoc文档

有了api-docs.json文档,即可使用swagger2markup导出asciidoc文档,Swagger2Markup是Github上的一个开源项目。该项目主要用来将Swagger自动生成的文档转换成几种流行的格式以便于静态部署和使用,比如:AsciiDoc、Markdown、Confluence。使用swagger2markup导出asciidoc文档有两种方式:

  • 引入swagger2markup的jar包,通过编码方式生成对应格式的文档输出。
  • 使用swagger2markup的maven插件,以mvn命令生成对应格式文档输出。

第一种方式示例代码中有提供SwaggerExportTest.java,其中编写了相应的测试代码用于生成文档,请读者自行阅读。本文主要使用第二种方式,即maven插件进行asciidoc文档输出。

4.2.1 设置文档输出相关插件版本

以下插件版本在示例可正常运行,更高的版本有可能会出现不兼容的情况,因此请读者按本文设置的版本进行处理。文档输出的路径以前面指定的相关docs目录为准(${basedir}是项目的根目录)。

  1. <!-- 文档输出插件版本 -->
  2. <swagger.plugin.version>3.1.8</swagger.plugin.version>
  3. <swagger2markup.version>1.3.1</swagger2markup.version>
  4. <swagger2markup.plugin.version>1.3.3</swagger2markup.plugin.version>
  5. <asciidoctor.plugin.version>1.5.7</asciidoctor.plugin.version>
  6. <!-- 文档输出路径 -->
  7. <docs.path>${basedir}/docs</docs.path>
  8. <docs.asciidoc.path>${docs.path}/asciidoc</docs.asciidoc.path>
  9. <docs.html.path>${docs.path}/html</docs.html.path>
  10. <docs.pdf.path>${docs.path}/pdf</docs.pdf.path>
  11. <docs.swagger.json.path>${docs.path}/swagger/api-docs.json</docs.swagger.json.path>

4.2.2 添加swagger2markup-maven-plugin插件

build/plugins元素下,添加以下元素:

  1. <!-- 1.swagger.json文件转asciidoc文件-->
  2. <plugin>
  3. <groupId>io.github.swagger2markup</groupId>
  4. <artifactId>swagger2markup-maven-plugin</artifactId>
  5. <version>${swagger2markup.plugin.version}</version>
  6. <configuration>
  7. <!-- 访问url -->
  8. <!--<swaggerInput>http://localhost:8080/swaggerdemo/v2/api-docs?group=default</swaggerInput>-->
  9. <!-- 访问json文件-->
  10. <swaggerInput>${docs.swagger.json.path}</swaggerInput>
  11. <!-- 生成多个文档输出路径 -->
  12. <!--<outputDir>${docs.asciidoc.path}</outputDir>-->
  13. <!-- 生成单个文档输出路径 -->
  14. <outputFile>${docs.asciidoc.path}/all</outputFile>
  15. <config>
  16. <swagger2markup.pathsGroupedBy>TAGS</swagger2markup.pathsGroupedBy>
  17. <!-- 选择:ASCIIDOC/MARKDOWN/CONFLUENCE_MARKUP-->
  18. <swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
  19. </config>
  20. </configuration>
  21. </plugin>

说明:

  • swaggerInput元素可以是导出的json文件路径,也可以使用访问url地址(v2/api-docs),效果是一样的。但若使用url,则需要确保先把应用启动,能正常访问url。
  • outputFile元素是指把全部内容输出到一个文件中,若使用outputDir,则会把各种类型的内容,分开成多个文件输出。
  • swagger2markup.markupLanguage元素可以选择导出ASCIIDOC/MARKDOWN/CONFLUENCE_MARKUP三种格式的文档,此处使用ASCIIDOC即可。

4.2.3 使用命令输出文档

添加完此插件后,使用mvn swagger2markup:convertSwagger2markup命令即可以导出文件到指定的目录。如本示例中的输出是docs/asciidoc/all.adoc

4.3 导出html/pdf文档

导出asciidoc文档后,使用asciidoctor插件对其转换为html和pdf文档输出。

4.3.1 添加asciidoctor插件

如下所示,通过添加asciidoctor-maven-plugin,并对它进行配置:

  1. <!-- 2.asciidoc文件转html/pdf文件-->
  2. <plugin>
  3. <groupId>org.asciidoctor</groupId>
  4. <artifactId>asciidoctor-maven-plugin</artifactId>
  5. <version>${asciidoctor.plugin.version}</version>
  6. <!-- 转换pdf使用的依赖 -->
  7. <dependencies>
  8. <dependency>
  9. <groupId>org.asciidoctor</groupId>
  10. <artifactId>asciidoctorj-pdf</artifactId>
  11. <version>1.5.0-alpha.16</version>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.jruby</groupId>
  15. <artifactId>jruby-complete</artifactId>
  16. <version>9.2.8.0</version>
  17. </dependency>
  18. </dependencies>
  19. <configuration>
  20. <sourceDirectory>${docs.asciidoc.path}</sourceDirectory>
  21. <doctype>book</doctype>
  22. <sourceHighlighter>coderay</sourceHighlighter>
  23. <headerFooter>true</headerFooter>
  24. <attributes>
  25. <!-- 菜单栏在左边 -->
  26. <toc>left</toc>
  27. <!-- 三级目录 -->
  28. <toclevels>3</toclevels>
  29. <!-- 数字序号 -->
  30. <sectnums>true</sectnums>
  31. </attributes>
  32. </configuration>
  33. <!-- 生成html和pdf两种格式 -->
  34. <executions>
  35. <execution>
  36. <id>output-html</id>
  37. <phase>generate-resources</phase>
  38. <goals>
  39. <goal>process-asciidoc</goal>
  40. </goals>
  41. <configuration>
  42. <outputDirectory>${docs.html.path}</outputDirectory>
  43. <backend>html</backend>
  44. </configuration>
  45. </execution>
  46. <execution>
  47. <id>output-pdf</id>
  48. <phase>generate-resources</phase>
  49. <goals>
  50. <goal>process-asciidoc</goal>
  51. </goals>
  52. <configuration>
  53. <outputDirectory>${docs.pdf.path}</outputDirectory>
  54. <backend>pdf</backend>
  55. <!-- 处理中文字符问题 -->
  56. <attributes>
  57. <pdf-fontsdir>${docs.pdf.path}/fonts</pdf-fontsdir>
  58. <pdf-stylesdir>${docs.pdf.path}/themes</pdf-stylesdir>
  59. <pdf-style>cn</pdf-style>
  60. </attributes>
  61. </configuration>
  62. </execution>
  63. </executions>
  64. </plugin>

此配置相对较长,其实主要分为三部分:

  1. 转换pdf使用的依赖,即<dependencies>元素,直接使用即可。
  2. 通用文档配置<configuration>元素,其中需要注意的是<sourceDirectory>,此处需要配置上一个步骤生成的asiidoc文件目录路径。
  3. <executions>元素:由于需要生成html和pdf两种格式的文档,因此分别使用executions来实现。其中html相对简单,配置outputDirectorybackend元素指定输出目录路径和文件格式html即可,对应的pdf也一样配置。

对于pdf文档的转换,需要解决中文字体缺失的问题。

  • 若不配置对应的中文字符支持(即配置中的<attributes>元素),则会出现中文乱码或文字缺失的情况,如下图,缺失了这几个字:

  • pdf中文字符支持,在github中,已有对asciidoctor-pdf中文字体的支持,在下载页面下载KaiGenGothicCN开头和RobotoMono开头的ttf字体,同时下载cn-theme.yml文件,分别放到docs/pdf目录下:
  1. ├─pdf
  2. │ ├─fonts
  3. │ │ ├─KaiGenGothicCN-Bold-Italic.ttf
  4. │ │ ├─KaiGenGothicCN-Bold.ttf
  5. │ │ ├─KaiGenGothicCN-Regular-Italic.ttf
  6. │ │ ├─KaiGenGothicCN-Regular.ttf
  7. │ │ ├─RobotoMono-Bold.ttf
  8. │ │ ├─RobotoMono-BoldItalic.ttf
  9. │ │ ├─RobotoMono-Italic.ttf
  10. │ │ └─RobotoMono-Regular.ttf
  11. │ └─themes
  12. │  └─cn-theme.yml
  • 使用<attributes>元素设置对应的pdf-fontsdir,pdf-stylesdirpdf-style,指定下载好的fonts目录和themes目录。

4.3.2 使用命令输出文档

使用命令mvn generate-resources,即可生成对应的html和pdf文档到对应的目录,分别是docs/html/all.htmldocs/html/all.pdf。效果如下图所示:

  • html文档

  • pdf文档(缺失文字问题已解决)

5. 总结

本篇文章针对接口过滤显示,前端mock数据和离线导出文档等问题,提供相应的解决方法,包括接口过滤(包过滤、类注解过滤、方法注解过滤、分组过滤等方式),实现按需发布指定接口的功能;使用easy-mock+swagger实现mock数据;使用maven插件实现接口文档的离线导出。希望对有需要的同学有所帮助。本文配套的示例工程地址https://github.com/mianshenglee/my-example/tree/master/springboot-swagger-demo/advance-swagger-demo,读者可fork或pull下来,结合学习。

相关阅读

springboot+swagger接口文档企业实践(上)

参考资料

关注我的公众号,获取更多技术记录

springboot+swagger接口文档企业实践(下)的更多相关文章

  1. springboot+swagger接口文档企业实践(上)

    目录 1.引言 2.swagger简介 2.1 swagger 介绍 2.2 springfox.swagger与springboot 3. 使用springboot+swagger构建接口文档 3. ...

  2. SpringBoot开发mockserver及生成swagger接口文档

    通过springboot开发mock server,包含get及post接口,用于练习接口自动化及jmeter很方便 当然,也为后面jenkins持续集成做基础(开发push代码后  → jenkin ...

  3. .net core的Swagger接口文档使用教程(二):NSwag

    上一篇介绍了Swashbuckle ,地址:.net core的Swagger接口文档使用教程(一):Swashbuckle 讲的东西还挺多,怎奈微软还推荐了一个NSwag,那就继续写吧! 但是和Sw ...

  4. SpringBoot: 后台接口文档 - 基于Swagger3

    目录 前言:什么是Swagger 起步:(只需简单的3步) 加载依赖 添加注解@EnableOpenApi 启动SpringBoot,访问Swagger后台界面 配置:基于Java的配置 注解:Swa ...

  5. .Net Core---- WebApi生成Swagger接口文档

    1. Swagger是什么? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件 ...

  6. .netcore 3.1高性能微服务架构:加入swagger接口文档

    本文为原创文章:首发:http://www.zyiz.net/tech/detail-108663.html swagger是什么? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视 ...

  7. .net core的Swagger接口文档使用教程(一):Swashbuckle

    现在的开发大部分都是前后端分离的模式了,后端提供接口,前端调用接口.后端提供了接口,需要对接口进行测试,之前都是使用浏览器开发者工具,或者写单元测试,再或者直接使用Postman,但是现在这些都已经o ...

  8. Swagger 接口文档

    目录 Swagger 介绍 Swagger 依赖 SpringBoot 集成 Swagger 配置类 常用注解 效果示例 Swagger 介绍 Swagger UI 允许任何人(无论是开发团队还是最终 ...

  9. Postman----基础使用篇(没有接口文档的情况下如何着手做接口测试)

    [备注说明]内文中的图片由于页面的限制,图片显示不清晰,为了能更加的看清图片,请点击"图片",点击"右键"选择"在新标签页中打开图片",可查 ...

随机推荐

  1. C语言文件输入/输出 ACM改进版(用freopen函数方便检验)

    这次用到的文件打开函数不再是fopen,而是stdio.h中包含的另一个函数freopen FILE * freopen ( const char * filename,const char * mo ...

  2. 计算机网络(1)- TCP

    TCP的全称是传输控制协议(Transmission Control Protocol)[RFC 793] TCP提供面向连接的服务.在传送数据之前必须先建立连接,数据传送结束后要释放连接.TCP不提 ...

  3. SpirngCloud之Ribbon负载均衡(二)

    一 概念 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具. 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负 ...

  4. 前端开发之VSCode扩展

    1.Chinese (Simplified) Language Pack for Visual Studio Code——中文语言包 2.Beautify——代码格式化工具 3.HTML Snippe ...

  5. Splash API 调用

    render.html render.html 接口用于获取 JavaScript 渲染的页面的 HTML 代码,接口地址就是 Splash 的运行地址加此接口名称,例如http://localhos ...

  6. 工厂模式(C++)

    转载来源:https://www.runoob.com/design-pattern/ 工厂模式 创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑, ...

  7. Unity2-投影方式

  8. 学习笔记31_ORM框架ModelFirst设计数据库

    ModelFirst就是先设计实体数据类型,然后根据设计的数据类型,生成数据库表 1.新建项--ADO.NET实体数据模型--空数据模型--进入模型设计器(点击xxx.edmx文件也能进入设计器). ...

  9. javascript创建一个基于数组的栈结构

    栈是一种遵从后进先出(LIFO)原则的有序集合.新添加或待删除的元素都保存在栈的同 一端,称作栈顶,另一端就叫栈底.在栈里,新元素都靠近栈顶,旧元素都接近栈底. 栈拥有以下方法: push(eleme ...

  10. [Hadoop]HDFS机架感知策略

    HDFS NameNode对文件块复制相关所有事物负责,它周期性接受来自于DataNode的HeartBeat和BlockReport信息,HDFS文件块副本的放置对于系统整体的可靠性和性能有关键性影 ...