活动公告

系统通知
05-18 21:22
系统通知
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,资源失效请在帖子内回复要求补档,会尽快处理!
10-23 09:31

手把手教你Swagger UI界面搭建步骤从环境准备到项目集成再到优化配置全面指南构建专业API文档平台

SunJu_FaceMall

3万

主题

2860

科技点

3万

积分

白金月票

碾压王

积分
32872

塔罗立华奏

<font color=白金月票" /> 发表于 2025-9-9 19:50:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Swagger UI是一个强大的工具,它允许我们可视化地展示和交互API文档。通过Swagger UI,开发人员可以轻松地理解和测试API,而无需查看实际的代码实现。本文将详细介绍如何从零开始搭建Swagger UI界面,包括环境准备、项目集成、基本配置以及优化配置,帮助您构建一个专业的API文档平台。

1. 环境准备

在开始搭建Swagger UI之前,我们需要准备一些必要的工具和环境。

1.1 必要工具

• Java开发工具包(JDK)8或更高版本(如果使用Java)
• Node.js和npm(如果使用JavaScript)
• 一个IDE(如IntelliJ IDEA、VS Code等)
• Maven或Gradle(如果使用Java)

1.2 项目结构

我们将创建一个基本的项目结构,以便集成Swagger UI。这里以Spring Boot项目为例:
  1. swagger-demo
  2. ├── src
  3. │   ├── main
  4. │   │   ├── java
  5. │   │   │   └── com
  6. │   │   │       └── example
  7. │   │   │           └── swagger
  8. │   │   │               ├── SwaggerDemoApplication.java
  9. │   │   │               ├── controller
  10. │   │   │               │   └── UserController.java
  11. │   │   │               ├── model
  12. │   │   │               │   └── User.java
  13. │   │   │               └── config
  14. │   │   │                   └── SwaggerConfig.java
  15. │   │   └── resources
  16. │   │       └── application.properties
  17. │   └── test
  18. │       └── java
  19. └── pom.xml
复制代码

2. 项目集成

Swagger UI可以与多种编程语言和框架集成。下面我们将介绍几种常见的集成方式。

2.1 Spring Boot项目集成

首先,我们需要在pom.xml文件中添加Swagger相关的依赖:
  1. <dependencies>
  2.     <!-- Spring Boot Starter Web -->
  3.     <dependency>
  4.         <groupId>org.springframework.boot</groupId>
  5.         <artifactId>spring-boot-starter-web</artifactId>
  6.     </dependency>
  7.    
  8.     <!-- Swagger2 -->
  9.     <dependency>
  10.         <groupId>io.springfox</groupId>
  11.         <artifactId>springfox-swagger2</artifactId>
  12.         <version>3.0.0</version>
  13.     </dependency>
  14.    
  15.     <!-- Swagger UI -->
  16.     <dependency>
  17.         <groupId>io.springfox</groupId>
  18.         <artifactId>springfox-swagger-ui</artifactId>
  19.         <version>3.0.0</version>
  20.     </dependency>
  21.    
  22.     <!-- Springfox Boot Starter (可选,简化配置) -->
  23.     <dependency>
  24.         <groupId>io.springfox</groupId>
  25.         <artifactId>springfox-boot-starter</artifactId>
  26.         <version>3.0.0</version>
  27.     </dependency>
  28. </dependencies>
复制代码

接下来,我们创建一个Swagger配置类:
  1. package com.example.swagger.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import springfox.documentation.builders.ApiInfoBuilder;
  5. import springfox.documentation.builders.PathSelectors;
  6. import springfox.documentation.builders.RequestHandlerSelectors;
  7. import springfox.documentation.service.ApiInfo;
  8. import springfox.documentation.service.Contact;
  9. import springfox.documentation.spi.DocumentationType;
  10. import springfox.documentation.spring.web.plugins.Docket;
  11. @Configuration
  12. public class SwaggerConfig {
  13.     @Bean
  14.     public Docket api() {
  15.         return new Docket(DocumentationType.SWAGGER_2)
  16.                 .select()
  17.                 .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
  18.                 .paths(PathSelectors.any())
  19.                 .build()
  20.                 .apiInfo(apiInfo());
  21.     }
  22.     private ApiInfo apiInfo() {
  23.         return new ApiInfoBuilder()
  24.                 .title("Swagger Demo API")
  25.                 .description("This is a demo API for Swagger UI")
  26.                 .version("1.0.0")
  27.                 .contact(new Contact("Your Name", "https://example.com", "your.email@example.com"))
  28.                 .build();
  29.     }
  30. }
复制代码

在Spring Boot主应用程序类上添加@EnableSwagger2注解:
  1. package com.example.swagger;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import springfox.documentation.swagger2.annotations.EnableSwagger2;
  5. @SpringBootApplication
  6. @EnableSwagger2
  7. public class SwaggerDemoApplication {
  8.     public static void main(String[] args) {
  9.         SpringApplication.run(SwaggerDemoApplication.class, args);
  10.     }
  11. }
复制代码

创建一个简单的用户控制器和模型:
  1. package com.example.swagger.model;
  2. public class User {
  3.     private Long id;
  4.     private String username;
  5.     private String email;
  6.    
  7.     // 构造函数、getter和setter方法
  8.     public User() {}
  9.    
  10.     public User(Long id, String username, String email) {
  11.         this.id = id;
  12.         this.username = username;
  13.         this.email = email;
  14.     }
  15.    
  16.     public Long getId() {
  17.         return id;
  18.     }
  19.    
  20.     public void setId(Long id) {
  21.         this.id = id;
  22.     }
  23.    
  24.     public String getUsername() {
  25.         return username;
  26.     }
  27.    
  28.     public void setUsername(String username) {
  29.         this.username = username;
  30.     }
  31.    
  32.     public String getEmail() {
  33.         return email;
  34.     }
  35.    
  36.     public void setEmail(String email) {
  37.         this.email = email;
  38.     }
  39. }
复制代码
  1. package com.example.swagger.controller;
  2. import com.example.swagger.model.User;
  3. import io.swagger.annotations.Api;
  4. import io.swagger.annotations.ApiOperation;
  5. import io.swagger.annotations.ApiParam;
  6. import org.springframework.web.bind.annotation.*;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. import java.util.concurrent.ConcurrentHashMap;
  10. import java.util.concurrent.ConcurrentMap;
  11. import java.util.concurrent.atomic.AtomicLong;
  12. @RestController
  13. @RequestMapping("/api/users")
  14. @Api(tags = "User Management API")
  15. public class UserController {
  16.     private final ConcurrentMap<Long, User> users = new ConcurrentHashMap<>();
  17.     private final AtomicLong counter = new AtomicLong();
  18.     @GetMapping
  19.     @ApiOperation(value = "Get all users", notes = "Retrieve a list of all users")
  20.     public List<User> getAllUsers() {
  21.         return new ArrayList<>(users.values());
  22.     }
  23.     @GetMapping("/{id}")
  24.     @ApiOperation(value = "Get user by ID", notes = "Retrieve a user by their ID")
  25.     public User getUserById(
  26.             @ApiParam(value = "User ID", required = true) @PathVariable Long id) {
  27.         return users.get(id);
  28.     }
  29.     @PostMapping
  30.     @ApiOperation(value = "Create a new user", notes = "Add a new user to the system")
  31.     public User createUser(
  32.             @ApiParam(value = "User object", required = true) @RequestBody User user) {
  33.         Long id = counter.incrementAndGet();
  34.         user.setId(id);
  35.         users.put(id, user);
  36.         return user;
  37.     }
  38.     @PutMapping("/{id}")
  39.     @ApiOperation(value = "Update an existing user", notes = "Update the details of an existing user")
  40.     public User updateUser(
  41.             @ApiParam(value = "User ID", required = true) @PathVariable Long id,
  42.             @ApiParam(value = "Updated user object", required = true) @RequestBody User user) {
  43.         user.setId(id);
  44.         users.put(id, user);
  45.         return user;
  46.     }
  47.     @DeleteMapping("/{id}")
  48.     @ApiOperation(value = "Delete a user", notes = "Remove a user from the system")
  49.     public void deleteUser(
  50.             @ApiParam(value = "User ID", required = true) @PathVariable Long id) {
  51.         users.remove(id);
  52.     }
  53. }
复制代码

现在,我们可以运行Spring Boot应用程序,并访问Swagger UI界面。默认情况下,Swagger UI可以通过以下URL访问:
  1. http://localhost:8080/swagger-ui.html
复制代码

2.2 Node.js项目集成

首先,创建一个新的Node.js项目并安装必要的依赖:
  1. mkdir swagger-node-demo
  2. cd swagger-node-demo
  3. npm init -y
  4. npm install express swagger-ui-express swagger-jsdoc
复制代码

创建一个index.js文件,并设置基本的Express应用:
  1. const express = require('express');
  2. const swaggerUi = require('swagger-ui-express');
  3. const swaggerJsdoc = require('swagger-jsdoc');
  4. const app = express();
  5. app.use(express.json());
  6. // Swagger configuration
  7. const options = {
  8.   definition: {
  9.     openapi: '3.0.0',
  10.     info: {
  11.       title: 'Node.js Swagger API',
  12.       version: '1.0.0',
  13.       description: 'A demo API for Swagger UI in Node.js',
  14.     },
  15.     servers: [
  16.       {
  17.         url: 'http://localhost:3000',
  18.       },
  19.     ],
  20.   },
  21.   apis: ['./index.js'], // files containing annotations as above
  22. };
  23. const specs = swaggerJsdoc(options);
  24. app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));
  25. // User data storage
  26. let users = [];
  27. let idCounter = 1;
  28. /**
  29. * @swagger
  30. * components:
  31. *   schemas:
  32. *     User:
  33. *       type: object
  34. *       required:
  35. *         - username
  36. *         - email
  37. *       properties:
  38. *         id:
  39. *           type: integer
  40. *           description: The user ID
  41. *         username:
  42. *           type: string
  43. *           description: The user's username
  44. *         email:
  45. *           type: string
  46. *           description: The user's email
  47. *       example:
  48. *         id: 1
  49. *         username: johndoe
  50. *         email: john@example.com
  51. */
  52. /**
  53. * @swagger
  54. * /users:
  55. *   get:
  56. *     summary: Get all users
  57. *     description: Retrieve a list of all users
  58. *     responses:
  59. *       200:
  60. *         description: A list of users
  61. *         content:
  62. *           application/json:
  63. *             schema:
  64. *               type: array
  65. *               items:
  66. *                 $ref: '#/components/schemas/User'
  67. */
  68. app.get('/users', (req, res) => {
  69.   res.json(users);
  70. });
  71. /**
  72. * @swagger
  73. * /users/{id}:
  74. *   get:
  75. *     summary: Get user by ID
  76. *     description: Retrieve a user by their ID
  77. *     parameters:
  78. *       - in: path
  79. *         name: id
  80. *         required: true
  81. *         description: User ID
  82. *         schema:
  83. *           type: integer
  84. *     responses:
  85. *       200:
  86. *         description: A single user
  87. *         content:
  88. *           application/json:
  89. *             schema:
  90. *               $ref: '#/components/schemas/User'
  91. *       404:
  92. *         description: User not found
  93. */
  94. app.get('/users/:id', (req, res) => {
  95.   const id = parseInt(req.params.id);
  96.   const user = users.find(u => u.id === id);
  97.   if (user) {
  98.     res.json(user);
  99.   } else {
  100.     res.status(404).json({ message: 'User not found' });
  101.   }
  102. });
  103. /**
  104. * @swagger
  105. * /users:
  106. *   post:
  107. *     summary: Create a new user
  108. *     description: Add a new user to the system
  109. *     requestBody:
  110. *       required: true
  111. *       content:
  112. *         application/json:
  113. *           schema:
  114. *             $ref: '#/components/schemas/User'
  115. *     responses:
  116. *       201:
  117. *         description: User created successfully
  118. *         content:
  119. *           application/json:
  120. *             schema:
  121. *               $ref: '#/components/schemas/User'
  122. */
  123. app.post('/users', (req, res) => {
  124.   const { username, email } = req.body;
  125.   const newUser = {
  126.     id: idCounter++,
  127.     username,
  128.     email
  129.   };
  130.   users.push(newUser);
  131.   res.status(201).json(newUser);
  132. });
  133. /**
  134. * @swagger
  135. * /users/{id}:
  136. *   put:
  137. *     summary: Update an existing user
  138. *     description: Update the details of an existing user
  139. *     parameters:
  140. *       - in: path
  141. *         name: id
  142. *         required: true
  143. *         description: User ID
  144. *         schema:
  145. *           type: integer
  146. *     requestBody:
  147. *       required: true
  148. *       content:
  149. *         application/json:
  150. *           schema:
  151. *             $ref: '#/components/schemas/User'
  152. *     responses:
  153. *       200:
  154. *         description: User updated successfully
  155. *         content:
  156. *           application/json:
  157. *             schema:
  158. *               $ref: '#/components/schemas/User'
  159. *       404:
  160. *         description: User not found
  161. */
  162. app.put('/users/:id', (req, res) => {
  163.   const id = parseInt(req.params.id);
  164.   const { username, email } = req.body;
  165.   const userIndex = users.findIndex(u => u.id === id);
  166.   
  167.   if (userIndex !== -1) {
  168.     users[userIndex] = { id, username, email };
  169.     res.json(users[userIndex]);
  170.   } else {
  171.     res.status(404).json({ message: 'User not found' });
  172.   }
  173. });
  174. /**
  175. * @swagger
  176. * /users/{id}:
  177. *   delete:
  178. *     summary: Delete a user
  179. *     description: Remove a user from the system
  180. *     parameters:
  181. *       - in: path
  182. *         name: id
  183. *         required: true
  184. *         description: User ID
  185. *         schema:
  186. *           type: integer
  187. *     responses:
  188. *       200:
  189. *         description: User deleted successfully
  190. *       404:
  191. *         description: User not found
  192. */
  193. app.delete('/users/:id', (req, res) => {
  194.   const id = parseInt(req.params.id);
  195.   const userIndex = users.findIndex(u => u.id === id);
  196.   
  197.   if (userIndex !== -1) {
  198.     users.splice(userIndex, 1);
  199.     res.json({ message: 'User deleted successfully' });
  200.   } else {
  201.     res.status(404).json({ message: 'User not found' });
  202.   }
  203. });
  204. const PORT = process.env.PORT || 3000;
  205. app.listen(PORT, () => {
  206.   console.log(`Server is running on port ${PORT}`);
  207. });
复制代码

运行Node.js应用程序:
  1. node index.js
复制代码

然后,访问Swagger UI界面:
  1. http://localhost:3000/api-docs
复制代码

3. 基本配置

Swagger UI提供了许多配置选项,可以根据需要进行自定义。下面我们将介绍一些基本的配置方法。

3.1 Spring Boot中的基本配置

在Swagger配置类中,我们可以配置API的基本信息:
  1. private ApiInfo apiInfo() {
  2.     return new ApiInfoBuilder()
  3.             .title("API Documentation")
  4.             .description("This is the API documentation for our service")
  5.             .version("1.0.0")
  6.             .contact(new Contact("Developer Name", "https://example.com", "developer@example.com"))
  7.             .license("Apache License Version 2.0")
  8.             .licenseUrl("https://www.apache.org/licenses/LICENSE-2.0")
  9.             .build();
  10. }
复制代码

Docket是Swagger的核心配置类,我们可以通过它来配置Swagger的各种选项:
  1. @Bean
  2. public Docket api() {
  3.     return new Docket(DocumentationType.SWAGGER_2)
  4.             .select()
  5.             .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
  6.             .paths(PathSelectors.any())
  7.             .build()
  8.             .apiInfo(apiInfo())
  9.             .securitySchemes(Arrays.asList(apiKey()))
  10.             .securityContexts(Arrays.asList(securityContext()))
  11.             .produces(Collections.singleton("application/json"))
  12.             .consumes(Collections.singleton("application/json"));
  13. }
复制代码

如果API需要密钥认证,我们可以配置如下:
  1. private ApiKey apiKey() {
  2.     return new ApiKey("JWT", "Authorization", "header");
  3. }
  4. private SecurityContext securityContext() {
  5.     return SecurityContext.builder()
  6.             .securityReferences(defaultAuth())
  7.             .forPaths(PathSelectors.regex("/api/.*"))
  8.             .build();
  9. }
  10. private List<SecurityReference> defaultAuth() {
  11.     AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
  12.     AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
  13.     authorizationScopes[0] = authorizationScope;
  14.     return Arrays.asList(new SecurityReference("JWT", authorizationScopes));
  15. }
复制代码

3.2 Node.js中的基本配置

在Node.js中,我们可以通过swagger-jsdoc的选项来配置OpenAPI规范:
  1. const options = {
  2.   definition: {
  3.     openapi: '3.0.0',
  4.     info: {
  5.       title: 'Node.js Swagger API',
  6.       version: '1.0.0',
  7.       description: 'A demo API for Swagger UI in Node.js',
  8.       contact: {
  9.         name: 'API Support',
  10.         url: 'https://example.com/support',
  11.         email: 'support@example.com'
  12.       },
  13.       license: {
  14.         name: 'Apache 2.0',
  15.         url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
  16.       }
  17.     },
  18.     servers: [
  19.       {
  20.         url: 'http://localhost:3000',
  21.         description: 'Development server'
  22.       }
  23.     ],
  24.     components: {
  25.       securitySchemes: {
  26.         bearerAuth: {
  27.           type: 'http',
  28.           scheme: 'bearer',
  29.           bearerFormat: 'JWT'
  30.         }
  31.       }
  32.     },
  33.     security: [
  34.       {
  35.         bearerAuth: []
  36.       }
  37.     ]
  38.   },
  39.   apis: ['./index.js']
  40. };
复制代码

我们还可以配置Swagger UI的显示选项:
  1. const swaggerOptions = {
  2.   customCss: '.swagger-ui .topbar { display: none }',
  3.   customSiteTitle: "My API Documentation"
  4. };
  5. app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs, swaggerOptions));
复制代码

4. 高级配置

除了基本配置外,Swagger UI还提供了许多高级配置选项,可以帮助我们更好地展示和管理API文档。

4.1 Spring Boot中的高级配置

如果项目中有多个模块或不同版本的API,我们可以将它们分组显示:
  1. @Bean
  2. public Docket publicApi() {
  3.     return new Docket(DocumentationType.SWAGGER_2)
  4.             .select()
  5.             .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller.public"))
  6.             .paths(PathSelectors.any())
  7.             .build()
  8.             .groupName("public")
  9.             .apiInfo(publicApiInfo());
  10. }
  11. @Bean
  12. public Docket privateApi() {
  13.     return new Docket(DocumentationType.SWAGGER_2)
  14.             .select()
  15.             .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller.private"))
  16.             .paths(PathSelectors.any())
  17.             .build()
  18.             .groupName("private")
  19.             .apiInfo(privateApiInfo());
  20. }
  21. private ApiInfo publicApiInfo() {
  22.     return new ApiInfoBuilder()
  23.             .title("Public API Documentation")
  24.             .description("This is the public API documentation")
  25.             .version("1.0.0")
  26.             .build();
  27. }
  28. private ApiInfo privateApiInfo() {
  29.     return new ApiInfoBuilder()
  30.             .title("Private API Documentation")
  31.             .description("This is the private API documentation")
  32.             .version("1.0.0")
  33.             .build();
  34. }
复制代码

我们可以通过注解来自定义模型属性的显示:
  1. package com.example.swagger.model;
  2. import io.swagger.annotations.ApiModel;
  3. import io.swagger.annotations.ApiModelProperty;
  4. @ApiModel(description = "User details")
  5. public class User {
  6.     @ApiModelProperty(notes = "The database generated user ID", required = true, example = "1")
  7.     private Long id;
  8.    
  9.     @ApiModelProperty(notes = "The user's username", required = true, example = "johndoe")
  10.     private String username;
  11.    
  12.     @ApiModelProperty(notes = "The user's email address", required = true, example = "john@example.com")
  13.     private String email;
  14.    
  15.     // 构造函数、getter和setter方法
  16.     // ...
  17. }
复制代码

如果我们不想在Swagger UI中显示某些端点,可以使用@ApiIgnore注解:
  1. @ApiIgnore
  2. @RestController
  3. @RequestMapping("/internal")
  4. public class InternalController {
  5.     // Controller methods
  6. }
复制代码

或者在Docket配置中排除某些路径:
  1. @Bean
  2. public Docket api() {
  3.     return new Docket(DocumentationType.SWAGGER_2)
  4.             .select()
  5.             .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
  6.             .paths(PathSelectors.regex("(?!/internal/.*").and(PathSelectors.any()))
  7.             .build()
  8.             .apiInfo(apiInfo());
  9. }
复制代码

4.2 Node.js中的高级配置

我们可以使用外部的Swagger/OpenAPI文件,而不是在代码中定义:
  1. const fs = require('fs');
  2. const path = require('path');
  3. // Read external swagger.json file
  4. const swaggerDocument = JSON.parse(fs.readFileSync(path.join(__dirname, 'swagger.json'), 'utf8'));
  5. // Serve Swagger UI
  6. app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
复制代码

如果我们有多个Swagger文档,可以分别配置:
  1. // First API documentation
  2. const options1 = {
  3.   definition: {
  4.     openapi: '3.0.0',
  5.     info: {
  6.       title: 'API v1',
  7.       version: '1.0.0',
  8.     },
  9.   },
  10.   apis: ['./routes/v1/*.js'],
  11. };
  12. const specs1 = swaggerJsdoc(options1);
  13. // Second API documentation
  14. const options2 = {
  15.   definition: {
  16.     openapi: '3.0.0',
  17.     info: {
  18.       title: 'API v2',
  19.       version: '2.0.0',
  20.     },
  21.   },
  22.   apis: ['./routes/v2/*.js'],
  23. };
  24. const specs2 = swaggerJsdoc(options2);
  25. // Serve both Swagger UIs
  26. app.use('/api-docs/v1', swaggerUi.serve, swaggerUi.setup(specs1));
  27. app.use('/api-docs/v2', swaggerUi.serve, swaggerUi.setup(specs2));
复制代码

我们可以使用Swagger插件来扩展功能:
  1. const swaggerUi = require('swagger-ui-express');
  2. const swaggerJsdoc = require('swagger-jsdoc');
  3. const { swaggerUiServeFiles, swaggerUiSetup } = require('swagger-ui-dist');
  4. // Use custom plugins
  5. const customOptions = {
  6.   explorer: true,
  7.   customCss: '.swagger-ui .topbar { display: none }',
  8.   customSiteTitle: "My Custom API Docs",
  9.   plugins: [
  10.     function(system) {
  11.       return {
  12.         components: {
  13.           Topbar: function() { return null } // Disable top bar
  14.         }
  15.       }
  16.     }
  17.   ]
  18. };
  19. app.use('/api-docs', swaggerUiServeFiles, swaggerUiSetup(specs, customOptions));
复制代码

5. 自定义UI

Swagger UI提供了多种自定义选项,可以根据品牌或个人喜好来调整界面。

5.1 自定义CSS

我们可以通过添加自定义CSS来改变Swagger UI的外观:

在Spring Boot中,我们可以创建一个自定义的CSS文件,并在SwaggerConfig中引用它:
  1. @Bean
  2. public Docket api() {
  3.     return new Docket(DocumentationType.SWAGGER_2)
  4.             // ...
  5.             .securityContexts(Arrays.asList(securityContext()))
  6.             .produces(Collections.singleton("application/json"))
  7.             .consumes(Collections.singleton("application/json"));
  8. }
  9. // Add a custom CSS file
  10. @Bean
  11. public UiConfiguration uiConfig() {
  12.     return UiConfigurationBuilder.builder()
  13.             .deepLinking(true)
  14.             .displayOperationId(false)
  15.             .defaultModelsExpandDepth(1)
  16.             .defaultModelExpandDepth(1)
  17.             .defaultModelRendering(ModelRendering.EXAMPLE)
  18.             .displayRequestDuration(false)
  19.             .docExpansion(DocExpansion.NONE)
  20.             .filter(false)
  21.             .maxDisplayedTags(null)
  22.             .operationsSorter(OperationsSorter.ALPHA)
  23.             .showExtensions(false)
  24.             .tagsSorter(TagsSorter.ALPHA)
  25.             .validatorUrl(null)
  26.             .build();
  27. }
复制代码

然后,在src/main/resources/static目录下创建一个swagger.css文件:
  1. .swagger-ui .topbar {
  2.     display: none;
  3. }
  4. .swagger-ui .info {
  5.     margin: 50px 0;
  6. }
  7. .swagger-ui .info .title {
  8.     color: #3b4151;
  9.     font-family: sans-serif;
  10.     font-size: 36px;
  11. }
  12. .swagger-ui .info .description {
  13.     color: #3b4151;
  14.     font-family: sans-serif;
  15. }
  16. .swagger-ui .opblock .opblock-summary-description {
  17.     font-family: sans-serif;
  18.     color: #3b4151;
  19. }
复制代码

在Node.js中,我们可以直接在配置中添加自定义CSS:
  1. const customCss = `
  2. .swagger-ui .topbar {
  3.     display: none;
  4. }
  5. .swagger-ui .info {
  6.     margin: 50px 0;
  7. }
  8. .swagger-ui .info .title {
  9.     color: #3b4151;
  10.     font-family: sans-serif;
  11.     font-size: 36px;
  12. }
  13. .swagger-ui .info .description {
  14.     color: #3b4151;
  15.     font-family: sans-serif;
  16. }
  17. .swagger-ui .opblock .opblock-summary-description {
  18.     font-family: sans-serif;
  19.     color: #3b4151;
  20. }
  21. `;
  22. app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs, { customCss }));
复制代码

5.2 自定义Logo和标题

我们可以自定义Swagger UI的Logo和标题:

在Spring Boot中,我们可以创建一个自定义的HTML文件,并在其中添加Logo和标题:
  1. <!-- src/main/resources/static/swagger-ui.html -->
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5.     <meta charset="UTF-8">
  6.     <title>My API Documentation</title>
  7.     <link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
  8.     <link rel="stylesheet" type="text/css" href="./swagger.css" />
  9.     <link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
  10.     <link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
  11.     <style>
  12.         html
  13.         {
  14.             box-sizing: border-box;
  15.             overflow: -moz-scrollbars-vertical;
  16.             overflow-y: scroll;
  17.         }
  18.         *, *:before, *:after
  19.         {
  20.             box-sizing: inherit;
  21.         }
  22.         body {
  23.             margin:0;
  24.             background: #fafafa;
  25.         }
  26.     </style>
  27. </head>
  28. <body>
  29.     <div id="swagger-ui"></div>
  30.     <script src="./swagger-ui-bundle.js"></script>
  31.     <script src="./swagger-ui-standalone-preset.js"></script>
  32.     <script>
  33.         window.onload = function() {
  34.             const ui = SwaggerUIBundle({
  35.                 url: "/v2/api-docs",
  36.                 dom_id: '#swagger-ui',
  37.                 deepLinking: true,
  38.                 presets: [
  39.                     SwaggerUIBundle.presets.apis,
  40.                     SwaggerUIStandalonePreset
  41.                 ],
  42.                 plugins: [
  43.                     SwaggerUIBundle.plugins.DownloadUrl
  44.                 ],
  45.                 layout: "StandaloneLayout",
  46.                 validatorUrl: null,
  47.                 customSiteTitle: "My API Documentation"
  48.             });
  49.         };
  50.     </script>
  51. </body>
  52. </html>
复制代码

在Node.js中,我们可以使用自定义HTML模板:
  1. const swaggerOptions = {
  2.   customCss: '.swagger-ui .topbar { display: none }',
  3.   customSiteTitle: "My API Documentation",
  4.   customfavIcon: "/favicon.ico",
  5.   customHtml: true
  6. };
  7. // Create a custom HTML template
  8. app.get('/api-docs', (req, res) => {
  9.   res.send(`
  10.     <!DOCTYPE html>
  11.     <html>
  12.     <head>
  13.         <meta charset="UTF-8">
  14.         <title>My API Documentation</title>
  15.         <link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3.25.0/swagger-ui.css" >
  16.         <link rel="icon" type="image/png" href="/favicon.ico" sizes="32x32" />
  17.         <style>
  18.             html {
  19.                 box-sizing: border-box;
  20.                 overflow: -moz-scrollbars-vertical;
  21.                 overflow-y: scroll;
  22.             }
  23.             *, *:before, *:after {
  24.                 box-sizing: inherit;
  25.             }
  26.             body {
  27.                 margin:0;
  28.                 background: #fafafa;
  29.             }
  30.             .custom-logo {
  31.                 max-width: 150px;
  32.                 margin: 20px auto;
  33.                 display: block;
  34.             }
  35.         </style>
  36.     </head>
  37.     <body>
  38.         <img src="/logo.png" class="custom-logo" alt="Logo">
  39.         <div id="swagger-ui"></div>
  40.         <script src="https://unpkg.com/swagger-ui-dist@3.25.0/swagger-ui-bundle.js"></script>
  41.         <script src="https://unpkg.com/swagger-ui-dist@3.25.0/swagger-ui-standalone-preset.js"></script>
  42.         <script>
  43.             window.onload = function() {
  44.                 const ui = SwaggerUIBundle({
  45.                     url: "/api-docs/swagger.json",
  46.                     dom_id: '#swagger-ui',
  47.                     deepLinking: true,
  48.                     presets: [
  49.                         SwaggerUIBundle.presets.apis,
  50.                         SwaggerUIStandalonePreset
  51.                     ],
  52.                     plugins: [
  53.                         SwaggerUIBundle.plugins.DownloadUrl
  54.                     ],
  55.                     layout: "StandaloneLayout"
  56.                 });
  57.             };
  58.         </script>
  59.     </body>
  60.     </html>
  61.   `);
  62. });
复制代码

5.3 自定义JavaScript功能

我们还可以添加自定义JavaScript功能来扩展Swagger UI:
  1. const swaggerOptions = {
  2.   customJs: '/custom-swagger.js'
  3. };
  4. // Create custom JavaScript file
  5. app.get('/custom-swagger.js', (req, res) => {
  6.   res.send(`
  7.     // Custom JavaScript for Swagger UI
  8.     window.addEventListener('load', function() {
  9.         console.log('Custom Swagger UI loaded');
  10.         
  11.         // Add custom button
  12.         const customButton = document.createElement('button');
  13.         customButton.innerText = 'Custom Action';
  14.         customButton.className = 'btn';
  15.         customButton.onclick = function() {
  16.             alert('Custom action triggered!');
  17.         };
  18.         
  19.         // Find the top bar and add the custom button
  20.         const topbar = document.querySelector('.topbar');
  21.         if (topbar) {
  22.             topbar.appendChild(customButton);
  23.         }
  24.     });
  25.   `);
  26. });
  27. app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs, swaggerOptions));
复制代码

6. 最佳实践

使用Swagger UI时,遵循一些最佳实践可以帮助我们创建更好的API文档。

6.1 文档编写最佳实践

为每个API端点提供清晰的描述,包括其用途、参数和返回值:
  1. @ApiOperation(value = "Get user by ID", notes = "Retrieve a user by their unique identifier. Returns 404 if the user is not found.")
  2. @ApiResponses({
  3.     @ApiResponse(code = 200, message = "Successfully retrieved user", response = User.class),
  4.     @ApiResponse(code = 404, message = "User not found")
  5. })
  6. @GetMapping("/{id}")
  7. public ResponseEntity<User> getUserById(
  8.     @ApiParam(value = "The unique identifier of the user", required = true, example = "1")
  9.     @PathVariable Long id) {
  10.     // ...
  11. }
复制代码

为API请求和响应提供示例,使开发人员更容易理解如何使用API:
  1. @ApiOperation(value = "Create a new user", notes = "Add a new user to the system")
  2. @ApiResponses({
  3.     @ApiResponse(code = 201, message = "User created successfully", response = User.class),
  4.     @ApiResponse(code = 400, message = "Invalid input")
  5. })
  6. @PostMapping
  7. public ResponseEntity<User> createUser(
  8.     @ApiParam(
  9.         value = "User object to be created",
  10.         required = true,
  11.         examples = @Example(value = {
  12.             @ExampleProperty(
  13.                 value = "{\n  "username": "johndoe",\n  "email": "john@example.com"\n}",
  14.                 mediaType = "application/json"
  15.             )
  16.         })
  17.     )
  18.     @RequestBody User user) {
  19.     // ...
  20. }
复制代码

使用标记(tags)对API进行分类,使文档更有组织性:
  1. @RestController
  2. @RequestMapping("/api/users")
  3. @Api(tags = {"User Management"})
  4. public class UserController {
  5.     // ...
  6.    
  7.     @GetMapping
  8.     @ApiOperation(value = "Get all users", tags = {"User Management", "Admin"})
  9.     public List<User> getAllUsers() {
  10.         // ...
  11.     }
  12.    
  13.     @PostMapping
  14.     @ApiOperation(value = "Create a new user", tags = {"User Management"})
  15.     public User createUser(@RequestBody User user) {
  16.         // ...
  17.     }
  18. }
复制代码

6.2 安全性最佳实践

在生产环境中,应该限制对Swagger UI的访问:
  1. @Configuration
  2. @Profile("!prod") // Only enable Swagger in non-production environments
  3. @EnableSwagger2
  4. public class SwaggerConfig {
  5.     // ...
  6. }
复制代码

或者使用Spring Security来限制访问:
  1. @Configuration
  2. @EnableWebSecurity
  3. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  4.     @Override
  5.     protected void configure(HttpSecurity http) throws Exception {
  6.         http
  7.             .authorizeRequests()
  8.                 .antMatchers("/v2/api-docs", "/swagger-resources/**", "/swagger-ui.html", "/webjars/**").hasRole("DEVELOPER")
  9.                 .anyRequest().authenticated()
  10.             .and()
  11.             .formLogin()
  12.             .and()
  13.             .httpBasic();
  14.     }
  15. }
复制代码

避免在API文档中暴露敏感信息,如密码、密钥等:
  1. public class User {
  2.     @ApiModelProperty(notes = "The user's username", required = true)
  3.     private String username;
  4.    
  5.     @ApiModelProperty(notes = "The user's email address", required = true)
  6.     private String email;
  7.    
  8.     @ApiModelProperty(hidden = true) // Hide password field from documentation
  9.     private String password;
  10.    
  11.     // ...
  12. }
复制代码

6.3 版本控制最佳实践

使用版本控制来管理API的变化:
  1. @RestController
  2. @RequestMapping("/api/v1/users")
  3. @Api(tags = {"User Management v1"})
  4. public class UserControllerV1 {
  5.     // ...
  6. }
  7. @RestController
  8. @RequestMapping("/api/v2/users")
  9. @Api(tags = {"User Management v2"})
  10. public class UserControllerV2 {
  11.     // ...
  12. }
复制代码

为不同版本的API提供不同的文档:
  1. @Bean
  2. public Docket apiV1() {
  3.     return new Docket(DocumentationType.SWAGGER_2)
  4.             .groupName("v1")
  5.             .select()
  6.             .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller.v1"))
  7.             .paths(PathSelectors.ant("/api/v1/**"))
  8.             .build()
  9.             .apiInfo(apiV1Info());
  10. }
  11. @Bean
  12. public Docket apiV2() {
  13.     return new Docket(DocumentationType.SWAGGER_2)
  14.             .groupName("v2")
  15.             .select()
  16.             .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller.v2"))
  17.             .paths(PathSelectors.ant("/api/v2/**"))
  18.             .build()
  19.             .apiInfo(apiV2Info());
  20. }
复制代码

7. 常见问题与解决方案

在使用Swagger UI时,可能会遇到一些常见问题。下面是一些解决方案。

7.1 Swagger UI无法加载

解决方案:

1. 检查依赖是否正确配置
2. 确认Spring Boot应用程序是否正常运行
3. 检查浏览器控制台是否有错误信息
4. 尝试清除浏览器缓存

对于Spring Boot项目,确保以下依赖已正确添加:
  1. <dependency>
  2.     <groupId>io.springfox</groupId>
  3.     <artifactId>springfox-swagger2</artifactId>
  4.     <version>3.0.0</version>
  5. </dependency>
  6. <dependency>
  7.     <groupId>io.springfox</groupId>
  8.     <artifactId>springfox-swagger-ui</artifactId>
  9.     <version>3.0.0</version>
  10. </dependency>
复制代码

解决方案:

1. 确保控制器类上有@RestController或@Controller注解
2. 检查@EnableSwagger2注解是否已添加到主应用程序类
3. 确认控制器包路径是否在Docket配置中正确指定
  1. @Configuration
  2. @EnableSwagger2
  3. public class SwaggerConfig {
  4.     @Bean
  5.     public Docket api() {
  6.         return new Docket(DocumentationType.SWAGGER_2)
  7.                 .select()
  8.                 .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
  9.                 .paths(PathSelectors.any())
  10.                 .build();
  11.     }
  12. }
复制代码

7.2 注解不生效

解决方案:

1. 确保已导入正确的注解包:import io.swagger.annotations.*;
2. 检查注解语法是否正确
3. 确认Spring Boot应用程序是否已重新启动
  1. import io.swagger.annotations.Api;
  2. import io.swagger.annotations.ApiOperation;
  3. import io.swagger.annotations.ApiParam;
  4. import io.swagger.annotations.ApiResponse;
  5. import io.swagger.annotations.ApiResponses;
  6. @RestController
  7. @RequestMapping("/api/users")
  8. @Api(tags = "User Management API")
  9. public class UserController {
  10.    
  11.     @GetMapping("/{id}")
  12.     @ApiOperation(value = "Get user by ID", notes = "Retrieve a user by their ID")
  13.     @ApiResponses({
  14.         @ApiResponse(code = 200, message = "Successfully retrieved user"),
  15.         @ApiResponse(code = 404, message = "User not found")
  16.     })
  17.     public User getUserById(
  18.             @ApiParam(value = "User ID", required = true) @PathVariable Long id) {
  19.         // ...
  20.     }
  21. }
复制代码

7.3 认证问题

解决方案:

1. 配置安全方案
2. 在API上添加安全注解
  1. @Configuration
  2. @EnableSwagger2
  3. public class SwaggerConfig {
  4.    
  5.     @Bean
  6.     public Docket api() {
  7.         return new Docket(DocumentationType.SWAGGER_2)
  8.                 .select()
  9.                 .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
  10.                 .paths(PathSelectors.any())
  11.                 .build()
  12.                 .securitySchemes(Arrays.asList(apiKey()))
  13.                 .securityContexts(Arrays.asList(securityContext()));
  14.     }
  15.    
  16.     private ApiKey apiKey() {
  17.         return new ApiKey("JWT", "Authorization", "header");
  18.     }
  19.    
  20.     private SecurityContext securityContext() {
  21.         return SecurityContext.builder()
  22.                 .securityReferences(defaultAuth())
  23.                 .forPaths(PathSelectors.regex("/api/.*"))
  24.                 .build();
  25.     }
  26.    
  27.     private List<SecurityReference> defaultAuth() {
  28.         AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
  29.         AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
  30.         authorizationScopes[0] = authorizationScope;
  31.         return Arrays.asList(new SecurityReference("JWT", authorizationScopes));
  32.     }
  33. }
复制代码

在控制器中添加安全注解:
  1. @GetMapping("/secure")
  2. @ApiOperation(value = "Secure endpoint", notes = "This endpoint requires authentication")
  3. @ApiResponses({
  4.     @ApiResponse(code = 200, message = "Successfully accessed secure endpoint"),
  5.     @ApiResponse(code = 401, message = "Unauthorized")
  6. })
  7. @SecurityRequirement(name = "JWT")
  8. public String secureEndpoint() {
  9.     return "Access granted to secure endpoint";
  10. }
复制代码

7.4 性能问题

解决方案:

1. 限制API文档的范围
2. 禁用不必要的模型
3. 使用缓存
  1. @Bean
  2. public Docket api() {
  3.     return new Docket(DocumentationType.SWAGGER_2)
  4.             .select()
  5.             .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
  6.             .paths(PathSelectors.any())
  7.             .build()
  8.             .apiInfo(apiInfo())
  9.             .produces(Collections.singleton("application/json"))
  10.             .consumes(Collections.singleton("application/json"))
  11.             .ignoredParameterTypes(ExampleIgnoreClass.class); // Ignore certain model classes
  12. }
复制代码

解决方案:

1. 在开发环境启用Swagger,在生产环境禁用
2. 使用懒加载
  1. @Configuration
  2. @Profile("dev") // Only enable Swagger in development environment
  3. @EnableSwagger2
  4. public class SwaggerConfig {
  5.     // ...
  6. }
复制代码

或者使用条件加载:
  1. @Bean
  2. @ConditionalOnProperty(name = "swagger.enabled", havingValue = "true")
  3. public Docket api() {
  4.     return new Docket(DocumentationType.SWAGGER_2)
  5.             // ...
  6. }
复制代码

在application.properties中:
  1. # Enable Swagger in development
  2. swagger.enabled=true
复制代码

8. 总结

Swagger UI是一个强大的工具,可以帮助我们创建专业、交互式的API文档。通过本文的介绍,我们了解了如何从环境准备到项目集成,再到优化配置,全面搭建Swagger UI界面。

我们首先介绍了Swagger UI的基本概念和重要性,然后详细讲解了如何在Spring Boot和Node.js项目中集成Swagger UI,包括添加依赖、创建配置类、编写控制器和模型等步骤。接着,我们探讨了Swagger UI的基本配置和高级配置,包括API信息配置、分组配置、自定义模型属性等。我们还介绍了如何自定义Swagger UI的界面,包括自定义CSS、Logo和标题,以及添加自定义JavaScript功能。最后,我们分享了一些使用Swagger UI的最佳实践和常见问题的解决方案。

通过正确地使用Swagger UI,我们可以大大提高API文档的质量和可用性,使开发人员能够更容易地理解和使用我们的API。希望本文能够帮助您构建一个专业的API文档平台,提升您的API开发和文档编写体验。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则