|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
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项目为例:
- swagger-demo
- ├── src
- │ ├── main
- │ │ ├── java
- │ │ │ └── com
- │ │ │ └── example
- │ │ │ └── swagger
- │ │ │ ├── SwaggerDemoApplication.java
- │ │ │ ├── controller
- │ │ │ │ └── UserController.java
- │ │ │ ├── model
- │ │ │ │ └── User.java
- │ │ │ └── config
- │ │ │ └── SwaggerConfig.java
- │ │ └── resources
- │ │ └── application.properties
- │ └── test
- │ └── java
- └── pom.xml
复制代码
2. 项目集成
Swagger UI可以与多种编程语言和框架集成。下面我们将介绍几种常见的集成方式。
2.1 Spring Boot项目集成
首先,我们需要在pom.xml文件中添加Swagger相关的依赖:
- <dependencies>
- <!-- Spring Boot Starter Web -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
- <!-- Swagger2 -->
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger2</artifactId>
- <version>3.0.0</version>
- </dependency>
-
- <!-- Swagger UI -->
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger-ui</artifactId>
- <version>3.0.0</version>
- </dependency>
-
- <!-- Springfox Boot Starter (可选,简化配置) -->
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-boot-starter</artifactId>
- <version>3.0.0</version>
- </dependency>
- </dependencies>
复制代码
接下来,我们创建一个Swagger配置类:
- package com.example.swagger.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.service.Contact;
- import springfox.documentation.spi.DocumentationType;
- import springfox.documentation.spring.web.plugins.Docket;
- @Configuration
- public class SwaggerConfig {
- @Bean
- public Docket api() {
- return new Docket(DocumentationType.SWAGGER_2)
- .select()
- .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
- .paths(PathSelectors.any())
- .build()
- .apiInfo(apiInfo());
- }
- private ApiInfo apiInfo() {
- return new ApiInfoBuilder()
- .title("Swagger Demo API")
- .description("This is a demo API for Swagger UI")
- .version("1.0.0")
- .contact(new Contact("Your Name", "https://example.com", "your.email@example.com"))
- .build();
- }
- }
复制代码
在Spring Boot主应用程序类上添加@EnableSwagger2注解:
- package com.example.swagger;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import springfox.documentation.swagger2.annotations.EnableSwagger2;
- @SpringBootApplication
- @EnableSwagger2
- public class SwaggerDemoApplication {
- public static void main(String[] args) {
- SpringApplication.run(SwaggerDemoApplication.class, args);
- }
- }
复制代码
创建一个简单的用户控制器和模型:
- package com.example.swagger.model;
- public class User {
- private Long id;
- private String username;
- private String email;
-
- // 构造函数、getter和setter方法
- public User() {}
-
- public User(Long id, String username, String email) {
- this.id = id;
- this.username = username;
- this.email = email;
- }
-
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
- }
复制代码- package com.example.swagger.controller;
- import com.example.swagger.model.User;
- import io.swagger.annotations.Api;
- import io.swagger.annotations.ApiOperation;
- import io.swagger.annotations.ApiParam;
- import org.springframework.web.bind.annotation.*;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.ConcurrentMap;
- import java.util.concurrent.atomic.AtomicLong;
- @RestController
- @RequestMapping("/api/users")
- @Api(tags = "User Management API")
- public class UserController {
- private final ConcurrentMap<Long, User> users = new ConcurrentHashMap<>();
- private final AtomicLong counter = new AtomicLong();
- @GetMapping
- @ApiOperation(value = "Get all users", notes = "Retrieve a list of all users")
- public List<User> getAllUsers() {
- return new ArrayList<>(users.values());
- }
- @GetMapping("/{id}")
- @ApiOperation(value = "Get user by ID", notes = "Retrieve a user by their ID")
- public User getUserById(
- @ApiParam(value = "User ID", required = true) @PathVariable Long id) {
- return users.get(id);
- }
- @PostMapping
- @ApiOperation(value = "Create a new user", notes = "Add a new user to the system")
- public User createUser(
- @ApiParam(value = "User object", required = true) @RequestBody User user) {
- Long id = counter.incrementAndGet();
- user.setId(id);
- users.put(id, user);
- return user;
- }
- @PutMapping("/{id}")
- @ApiOperation(value = "Update an existing user", notes = "Update the details of an existing user")
- public User updateUser(
- @ApiParam(value = "User ID", required = true) @PathVariable Long id,
- @ApiParam(value = "Updated user object", required = true) @RequestBody User user) {
- user.setId(id);
- users.put(id, user);
- return user;
- }
- @DeleteMapping("/{id}")
- @ApiOperation(value = "Delete a user", notes = "Remove a user from the system")
- public void deleteUser(
- @ApiParam(value = "User ID", required = true) @PathVariable Long id) {
- users.remove(id);
- }
- }
复制代码
现在,我们可以运行Spring Boot应用程序,并访问Swagger UI界面。默认情况下,Swagger UI可以通过以下URL访问:
- http://localhost:8080/swagger-ui.html
复制代码
2.2 Node.js项目集成
首先,创建一个新的Node.js项目并安装必要的依赖:
- mkdir swagger-node-demo
- cd swagger-node-demo
- npm init -y
- npm install express swagger-ui-express swagger-jsdoc
复制代码
创建一个index.js文件,并设置基本的Express应用:
- const express = require('express');
- const swaggerUi = require('swagger-ui-express');
- const swaggerJsdoc = require('swagger-jsdoc');
- const app = express();
- app.use(express.json());
- // Swagger configuration
- const options = {
- definition: {
- openapi: '3.0.0',
- info: {
- title: 'Node.js Swagger API',
- version: '1.0.0',
- description: 'A demo API for Swagger UI in Node.js',
- },
- servers: [
- {
- url: 'http://localhost:3000',
- },
- ],
- },
- apis: ['./index.js'], // files containing annotations as above
- };
- const specs = swaggerJsdoc(options);
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));
- // User data storage
- let users = [];
- let idCounter = 1;
- /**
- * @swagger
- * components:
- * schemas:
- * User:
- * type: object
- * required:
- * - username
- * - email
- * properties:
- * id:
- * type: integer
- * description: The user ID
- * username:
- * type: string
- * description: The user's username
- * email:
- * type: string
- * description: The user's email
- * example:
- * id: 1
- * username: johndoe
- * email: john@example.com
- */
- /**
- * @swagger
- * /users:
- * get:
- * summary: Get all users
- * description: Retrieve a list of all users
- * responses:
- * 200:
- * description: A list of users
- * content:
- * application/json:
- * schema:
- * type: array
- * items:
- * $ref: '#/components/schemas/User'
- */
- app.get('/users', (req, res) => {
- res.json(users);
- });
- /**
- * @swagger
- * /users/{id}:
- * get:
- * summary: Get user by ID
- * description: Retrieve a user by their ID
- * parameters:
- * - in: path
- * name: id
- * required: true
- * description: User ID
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: A single user
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * 404:
- * description: User not found
- */
- app.get('/users/:id', (req, res) => {
- const id = parseInt(req.params.id);
- const user = users.find(u => u.id === id);
- if (user) {
- res.json(user);
- } else {
- res.status(404).json({ message: 'User not found' });
- }
- });
- /**
- * @swagger
- * /users:
- * post:
- * summary: Create a new user
- * description: Add a new user to the system
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * responses:
- * 201:
- * description: User created successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- */
- app.post('/users', (req, res) => {
- const { username, email } = req.body;
- const newUser = {
- id: idCounter++,
- username,
- email
- };
- users.push(newUser);
- res.status(201).json(newUser);
- });
- /**
- * @swagger
- * /users/{id}:
- * put:
- * summary: Update an existing user
- * description: Update the details of an existing user
- * parameters:
- * - in: path
- * name: id
- * required: true
- * description: User ID
- * schema:
- * type: integer
- * requestBody:
- * required: true
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * responses:
- * 200:
- * description: User updated successfully
- * content:
- * application/json:
- * schema:
- * $ref: '#/components/schemas/User'
- * 404:
- * description: User not found
- */
- app.put('/users/:id', (req, res) => {
- const id = parseInt(req.params.id);
- const { username, email } = req.body;
- const userIndex = users.findIndex(u => u.id === id);
-
- if (userIndex !== -1) {
- users[userIndex] = { id, username, email };
- res.json(users[userIndex]);
- } else {
- res.status(404).json({ message: 'User not found' });
- }
- });
- /**
- * @swagger
- * /users/{id}:
- * delete:
- * summary: Delete a user
- * description: Remove a user from the system
- * parameters:
- * - in: path
- * name: id
- * required: true
- * description: User ID
- * schema:
- * type: integer
- * responses:
- * 200:
- * description: User deleted successfully
- * 404:
- * description: User not found
- */
- app.delete('/users/:id', (req, res) => {
- const id = parseInt(req.params.id);
- const userIndex = users.findIndex(u => u.id === id);
-
- if (userIndex !== -1) {
- users.splice(userIndex, 1);
- res.json({ message: 'User deleted successfully' });
- } else {
- res.status(404).json({ message: 'User not found' });
- }
- });
- const PORT = process.env.PORT || 3000;
- app.listen(PORT, () => {
- console.log(`Server is running on port ${PORT}`);
- });
复制代码
运行Node.js应用程序:
然后,访问Swagger UI界面:
- http://localhost:3000/api-docs
复制代码
3. 基本配置
Swagger UI提供了许多配置选项,可以根据需要进行自定义。下面我们将介绍一些基本的配置方法。
3.1 Spring Boot中的基本配置
在Swagger配置类中,我们可以配置API的基本信息:
- private ApiInfo apiInfo() {
- return new ApiInfoBuilder()
- .title("API Documentation")
- .description("This is the API documentation for our service")
- .version("1.0.0")
- .contact(new Contact("Developer Name", "https://example.com", "developer@example.com"))
- .license("Apache License Version 2.0")
- .licenseUrl("https://www.apache.org/licenses/LICENSE-2.0")
- .build();
- }
复制代码
Docket是Swagger的核心配置类,我们可以通过它来配置Swagger的各种选项:
- @Bean
- public Docket api() {
- return new Docket(DocumentationType.SWAGGER_2)
- .select()
- .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
- .paths(PathSelectors.any())
- .build()
- .apiInfo(apiInfo())
- .securitySchemes(Arrays.asList(apiKey()))
- .securityContexts(Arrays.asList(securityContext()))
- .produces(Collections.singleton("application/json"))
- .consumes(Collections.singleton("application/json"));
- }
复制代码
如果API需要密钥认证,我们可以配置如下:
- private ApiKey apiKey() {
- return new ApiKey("JWT", "Authorization", "header");
- }
- private SecurityContext securityContext() {
- return SecurityContext.builder()
- .securityReferences(defaultAuth())
- .forPaths(PathSelectors.regex("/api/.*"))
- .build();
- }
- private List<SecurityReference> defaultAuth() {
- AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
- AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
- authorizationScopes[0] = authorizationScope;
- return Arrays.asList(new SecurityReference("JWT", authorizationScopes));
- }
复制代码
3.2 Node.js中的基本配置
在Node.js中,我们可以通过swagger-jsdoc的选项来配置OpenAPI规范:
- const options = {
- definition: {
- openapi: '3.0.0',
- info: {
- title: 'Node.js Swagger API',
- version: '1.0.0',
- description: 'A demo API for Swagger UI in Node.js',
- contact: {
- name: 'API Support',
- url: 'https://example.com/support',
- email: 'support@example.com'
- },
- license: {
- name: 'Apache 2.0',
- url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
- }
- },
- servers: [
- {
- url: 'http://localhost:3000',
- description: 'Development server'
- }
- ],
- components: {
- securitySchemes: {
- bearerAuth: {
- type: 'http',
- scheme: 'bearer',
- bearerFormat: 'JWT'
- }
- }
- },
- security: [
- {
- bearerAuth: []
- }
- ]
- },
- apis: ['./index.js']
- };
复制代码
我们还可以配置Swagger UI的显示选项:
- const swaggerOptions = {
- customCss: '.swagger-ui .topbar { display: none }',
- customSiteTitle: "My API Documentation"
- };
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs, swaggerOptions));
复制代码
4. 高级配置
除了基本配置外,Swagger UI还提供了许多高级配置选项,可以帮助我们更好地展示和管理API文档。
4.1 Spring Boot中的高级配置
如果项目中有多个模块或不同版本的API,我们可以将它们分组显示:
- @Bean
- public Docket publicApi() {
- return new Docket(DocumentationType.SWAGGER_2)
- .select()
- .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller.public"))
- .paths(PathSelectors.any())
- .build()
- .groupName("public")
- .apiInfo(publicApiInfo());
- }
- @Bean
- public Docket privateApi() {
- return new Docket(DocumentationType.SWAGGER_2)
- .select()
- .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller.private"))
- .paths(PathSelectors.any())
- .build()
- .groupName("private")
- .apiInfo(privateApiInfo());
- }
- private ApiInfo publicApiInfo() {
- return new ApiInfoBuilder()
- .title("Public API Documentation")
- .description("This is the public API documentation")
- .version("1.0.0")
- .build();
- }
- private ApiInfo privateApiInfo() {
- return new ApiInfoBuilder()
- .title("Private API Documentation")
- .description("This is the private API documentation")
- .version("1.0.0")
- .build();
- }
复制代码
我们可以通过注解来自定义模型属性的显示:
- package com.example.swagger.model;
- import io.swagger.annotations.ApiModel;
- import io.swagger.annotations.ApiModelProperty;
- @ApiModel(description = "User details")
- public class User {
- @ApiModelProperty(notes = "The database generated user ID", required = true, example = "1")
- private Long id;
-
- @ApiModelProperty(notes = "The user's username", required = true, example = "johndoe")
- private String username;
-
- @ApiModelProperty(notes = "The user's email address", required = true, example = "john@example.com")
- private String email;
-
- // 构造函数、getter和setter方法
- // ...
- }
复制代码
如果我们不想在Swagger UI中显示某些端点,可以使用@ApiIgnore注解:
- @ApiIgnore
- @RestController
- @RequestMapping("/internal")
- public class InternalController {
- // Controller methods
- }
复制代码
或者在Docket配置中排除某些路径:
- @Bean
- public Docket api() {
- return new Docket(DocumentationType.SWAGGER_2)
- .select()
- .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
- .paths(PathSelectors.regex("(?!/internal/.*").and(PathSelectors.any()))
- .build()
- .apiInfo(apiInfo());
- }
复制代码
4.2 Node.js中的高级配置
我们可以使用外部的Swagger/OpenAPI文件,而不是在代码中定义:
- const fs = require('fs');
- const path = require('path');
- // Read external swagger.json file
- const swaggerDocument = JSON.parse(fs.readFileSync(path.join(__dirname, 'swagger.json'), 'utf8'));
- // Serve Swagger UI
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
复制代码
如果我们有多个Swagger文档,可以分别配置:
- // First API documentation
- const options1 = {
- definition: {
- openapi: '3.0.0',
- info: {
- title: 'API v1',
- version: '1.0.0',
- },
- },
- apis: ['./routes/v1/*.js'],
- };
- const specs1 = swaggerJsdoc(options1);
- // Second API documentation
- const options2 = {
- definition: {
- openapi: '3.0.0',
- info: {
- title: 'API v2',
- version: '2.0.0',
- },
- },
- apis: ['./routes/v2/*.js'],
- };
- const specs2 = swaggerJsdoc(options2);
- // Serve both Swagger UIs
- app.use('/api-docs/v1', swaggerUi.serve, swaggerUi.setup(specs1));
- app.use('/api-docs/v2', swaggerUi.serve, swaggerUi.setup(specs2));
复制代码
我们可以使用Swagger插件来扩展功能:
- const swaggerUi = require('swagger-ui-express');
- const swaggerJsdoc = require('swagger-jsdoc');
- const { swaggerUiServeFiles, swaggerUiSetup } = require('swagger-ui-dist');
- // Use custom plugins
- const customOptions = {
- explorer: true,
- customCss: '.swagger-ui .topbar { display: none }',
- customSiteTitle: "My Custom API Docs",
- plugins: [
- function(system) {
- return {
- components: {
- Topbar: function() { return null } // Disable top bar
- }
- }
- }
- ]
- };
- app.use('/api-docs', swaggerUiServeFiles, swaggerUiSetup(specs, customOptions));
复制代码
5. 自定义UI
Swagger UI提供了多种自定义选项,可以根据品牌或个人喜好来调整界面。
5.1 自定义CSS
我们可以通过添加自定义CSS来改变Swagger UI的外观:
在Spring Boot中,我们可以创建一个自定义的CSS文件,并在SwaggerConfig中引用它:
- @Bean
- public Docket api() {
- return new Docket(DocumentationType.SWAGGER_2)
- // ...
- .securityContexts(Arrays.asList(securityContext()))
- .produces(Collections.singleton("application/json"))
- .consumes(Collections.singleton("application/json"));
- }
- // Add a custom CSS file
- @Bean
- public UiConfiguration uiConfig() {
- return UiConfigurationBuilder.builder()
- .deepLinking(true)
- .displayOperationId(false)
- .defaultModelsExpandDepth(1)
- .defaultModelExpandDepth(1)
- .defaultModelRendering(ModelRendering.EXAMPLE)
- .displayRequestDuration(false)
- .docExpansion(DocExpansion.NONE)
- .filter(false)
- .maxDisplayedTags(null)
- .operationsSorter(OperationsSorter.ALPHA)
- .showExtensions(false)
- .tagsSorter(TagsSorter.ALPHA)
- .validatorUrl(null)
- .build();
- }
复制代码
然后,在src/main/resources/static目录下创建一个swagger.css文件:
- .swagger-ui .topbar {
- display: none;
- }
- .swagger-ui .info {
- margin: 50px 0;
- }
- .swagger-ui .info .title {
- color: #3b4151;
- font-family: sans-serif;
- font-size: 36px;
- }
- .swagger-ui .info .description {
- color: #3b4151;
- font-family: sans-serif;
- }
- .swagger-ui .opblock .opblock-summary-description {
- font-family: sans-serif;
- color: #3b4151;
- }
复制代码
在Node.js中,我们可以直接在配置中添加自定义CSS:
- const customCss = `
- .swagger-ui .topbar {
- display: none;
- }
- .swagger-ui .info {
- margin: 50px 0;
- }
- .swagger-ui .info .title {
- color: #3b4151;
- font-family: sans-serif;
- font-size: 36px;
- }
- .swagger-ui .info .description {
- color: #3b4151;
- font-family: sans-serif;
- }
- .swagger-ui .opblock .opblock-summary-description {
- font-family: sans-serif;
- color: #3b4151;
- }
- `;
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs, { customCss }));
复制代码
5.2 自定义Logo和标题
我们可以自定义Swagger UI的Logo和标题:
在Spring Boot中,我们可以创建一个自定义的HTML文件,并在其中添加Logo和标题:
- <!-- src/main/resources/static/swagger-ui.html -->
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>My API Documentation</title>
- <link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
- <link rel="stylesheet" type="text/css" href="./swagger.css" />
- <link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
- <link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
- <style>
- html
- {
- box-sizing: border-box;
- overflow: -moz-scrollbars-vertical;
- overflow-y: scroll;
- }
- *, *:before, *:after
- {
- box-sizing: inherit;
- }
- body {
- margin:0;
- background: #fafafa;
- }
- </style>
- </head>
- <body>
- <div id="swagger-ui"></div>
- <script src="./swagger-ui-bundle.js"></script>
- <script src="./swagger-ui-standalone-preset.js"></script>
- <script>
- window.onload = function() {
- const ui = SwaggerUIBundle({
- url: "/v2/api-docs",
- dom_id: '#swagger-ui',
- deepLinking: true,
- presets: [
- SwaggerUIBundle.presets.apis,
- SwaggerUIStandalonePreset
- ],
- plugins: [
- SwaggerUIBundle.plugins.DownloadUrl
- ],
- layout: "StandaloneLayout",
- validatorUrl: null,
- customSiteTitle: "My API Documentation"
- });
- };
- </script>
- </body>
- </html>
复制代码
在Node.js中,我们可以使用自定义HTML模板:
- const swaggerOptions = {
- customCss: '.swagger-ui .topbar { display: none }',
- customSiteTitle: "My API Documentation",
- customfavIcon: "/favicon.ico",
- customHtml: true
- };
- // Create a custom HTML template
- app.get('/api-docs', (req, res) => {
- res.send(`
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>My API Documentation</title>
- <link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3.25.0/swagger-ui.css" >
- <link rel="icon" type="image/png" href="/favicon.ico" sizes="32x32" />
- <style>
- html {
- box-sizing: border-box;
- overflow: -moz-scrollbars-vertical;
- overflow-y: scroll;
- }
- *, *:before, *:after {
- box-sizing: inherit;
- }
- body {
- margin:0;
- background: #fafafa;
- }
- .custom-logo {
- max-width: 150px;
- margin: 20px auto;
- display: block;
- }
- </style>
- </head>
- <body>
- <img src="/logo.png" class="custom-logo" alt="Logo">
- <div id="swagger-ui"></div>
- <script src="https://unpkg.com/swagger-ui-dist@3.25.0/swagger-ui-bundle.js"></script>
- <script src="https://unpkg.com/swagger-ui-dist@3.25.0/swagger-ui-standalone-preset.js"></script>
- <script>
- window.onload = function() {
- const ui = SwaggerUIBundle({
- url: "/api-docs/swagger.json",
- dom_id: '#swagger-ui',
- deepLinking: true,
- presets: [
- SwaggerUIBundle.presets.apis,
- SwaggerUIStandalonePreset
- ],
- plugins: [
- SwaggerUIBundle.plugins.DownloadUrl
- ],
- layout: "StandaloneLayout"
- });
- };
- </script>
- </body>
- </html>
- `);
- });
复制代码
5.3 自定义JavaScript功能
我们还可以添加自定义JavaScript功能来扩展Swagger UI:
- const swaggerOptions = {
- customJs: '/custom-swagger.js'
- };
- // Create custom JavaScript file
- app.get('/custom-swagger.js', (req, res) => {
- res.send(`
- // Custom JavaScript for Swagger UI
- window.addEventListener('load', function() {
- console.log('Custom Swagger UI loaded');
-
- // Add custom button
- const customButton = document.createElement('button');
- customButton.innerText = 'Custom Action';
- customButton.className = 'btn';
- customButton.onclick = function() {
- alert('Custom action triggered!');
- };
-
- // Find the top bar and add the custom button
- const topbar = document.querySelector('.topbar');
- if (topbar) {
- topbar.appendChild(customButton);
- }
- });
- `);
- });
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs, swaggerOptions));
复制代码
6. 最佳实践
使用Swagger UI时,遵循一些最佳实践可以帮助我们创建更好的API文档。
6.1 文档编写最佳实践
为每个API端点提供清晰的描述,包括其用途、参数和返回值:
- @ApiOperation(value = "Get user by ID", notes = "Retrieve a user by their unique identifier. Returns 404 if the user is not found.")
- @ApiResponses({
- @ApiResponse(code = 200, message = "Successfully retrieved user", response = User.class),
- @ApiResponse(code = 404, message = "User not found")
- })
- @GetMapping("/{id}")
- public ResponseEntity<User> getUserById(
- @ApiParam(value = "The unique identifier of the user", required = true, example = "1")
- @PathVariable Long id) {
- // ...
- }
复制代码
为API请求和响应提供示例,使开发人员更容易理解如何使用API:
- @ApiOperation(value = "Create a new user", notes = "Add a new user to the system")
- @ApiResponses({
- @ApiResponse(code = 201, message = "User created successfully", response = User.class),
- @ApiResponse(code = 400, message = "Invalid input")
- })
- @PostMapping
- public ResponseEntity<User> createUser(
- @ApiParam(
- value = "User object to be created",
- required = true,
- examples = @Example(value = {
- @ExampleProperty(
- value = "{\n "username": "johndoe",\n "email": "john@example.com"\n}",
- mediaType = "application/json"
- )
- })
- )
- @RequestBody User user) {
- // ...
- }
复制代码
使用标记(tags)对API进行分类,使文档更有组织性:
- @RestController
- @RequestMapping("/api/users")
- @Api(tags = {"User Management"})
- public class UserController {
- // ...
-
- @GetMapping
- @ApiOperation(value = "Get all users", tags = {"User Management", "Admin"})
- public List<User> getAllUsers() {
- // ...
- }
-
- @PostMapping
- @ApiOperation(value = "Create a new user", tags = {"User Management"})
- public User createUser(@RequestBody User user) {
- // ...
- }
- }
复制代码
6.2 安全性最佳实践
在生产环境中,应该限制对Swagger UI的访问:
- @Configuration
- @Profile("!prod") // Only enable Swagger in non-production environments
- @EnableSwagger2
- public class SwaggerConfig {
- // ...
- }
复制代码
或者使用Spring Security来限制访问:
- @Configuration
- @EnableWebSecurity
- public class SecurityConfig extends WebSecurityConfigurerAdapter {
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http
- .authorizeRequests()
- .antMatchers("/v2/api-docs", "/swagger-resources/**", "/swagger-ui.html", "/webjars/**").hasRole("DEVELOPER")
- .anyRequest().authenticated()
- .and()
- .formLogin()
- .and()
- .httpBasic();
- }
- }
复制代码
避免在API文档中暴露敏感信息,如密码、密钥等:
- public class User {
- @ApiModelProperty(notes = "The user's username", required = true)
- private String username;
-
- @ApiModelProperty(notes = "The user's email address", required = true)
- private String email;
-
- @ApiModelProperty(hidden = true) // Hide password field from documentation
- private String password;
-
- // ...
- }
复制代码
6.3 版本控制最佳实践
使用版本控制来管理API的变化:
- @RestController
- @RequestMapping("/api/v1/users")
- @Api(tags = {"User Management v1"})
- public class UserControllerV1 {
- // ...
- }
- @RestController
- @RequestMapping("/api/v2/users")
- @Api(tags = {"User Management v2"})
- public class UserControllerV2 {
- // ...
- }
复制代码
为不同版本的API提供不同的文档:
- @Bean
- public Docket apiV1() {
- return new Docket(DocumentationType.SWAGGER_2)
- .groupName("v1")
- .select()
- .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller.v1"))
- .paths(PathSelectors.ant("/api/v1/**"))
- .build()
- .apiInfo(apiV1Info());
- }
- @Bean
- public Docket apiV2() {
- return new Docket(DocumentationType.SWAGGER_2)
- .groupName("v2")
- .select()
- .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller.v2"))
- .paths(PathSelectors.ant("/api/v2/**"))
- .build()
- .apiInfo(apiV2Info());
- }
复制代码
7. 常见问题与解决方案
在使用Swagger UI时,可能会遇到一些常见问题。下面是一些解决方案。
7.1 Swagger UI无法加载
解决方案:
1. 检查依赖是否正确配置
2. 确认Spring Boot应用程序是否正常运行
3. 检查浏览器控制台是否有错误信息
4. 尝试清除浏览器缓存
对于Spring Boot项目,确保以下依赖已正确添加:
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger2</artifactId>
- <version>3.0.0</version>
- </dependency>
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger-ui</artifactId>
- <version>3.0.0</version>
- </dependency>
复制代码
解决方案:
1. 确保控制器类上有@RestController或@Controller注解
2. 检查@EnableSwagger2注解是否已添加到主应用程序类
3. 确认控制器包路径是否在Docket配置中正确指定
- @Configuration
- @EnableSwagger2
- public class SwaggerConfig {
- @Bean
- public Docket api() {
- return new Docket(DocumentationType.SWAGGER_2)
- .select()
- .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
- .paths(PathSelectors.any())
- .build();
- }
- }
复制代码
7.2 注解不生效
解决方案:
1. 确保已导入正确的注解包:import io.swagger.annotations.*;
2. 检查注解语法是否正确
3. 确认Spring Boot应用程序是否已重新启动
- import io.swagger.annotations.Api;
- import io.swagger.annotations.ApiOperation;
- import io.swagger.annotations.ApiParam;
- import io.swagger.annotations.ApiResponse;
- import io.swagger.annotations.ApiResponses;
- @RestController
- @RequestMapping("/api/users")
- @Api(tags = "User Management API")
- public class UserController {
-
- @GetMapping("/{id}")
- @ApiOperation(value = "Get user by ID", notes = "Retrieve a user by their ID")
- @ApiResponses({
- @ApiResponse(code = 200, message = "Successfully retrieved user"),
- @ApiResponse(code = 404, message = "User not found")
- })
- public User getUserById(
- @ApiParam(value = "User ID", required = true) @PathVariable Long id) {
- // ...
- }
- }
复制代码
7.3 认证问题
解决方案:
1. 配置安全方案
2. 在API上添加安全注解
- @Configuration
- @EnableSwagger2
- public class SwaggerConfig {
-
- @Bean
- public Docket api() {
- return new Docket(DocumentationType.SWAGGER_2)
- .select()
- .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
- .paths(PathSelectors.any())
- .build()
- .securitySchemes(Arrays.asList(apiKey()))
- .securityContexts(Arrays.asList(securityContext()));
- }
-
- private ApiKey apiKey() {
- return new ApiKey("JWT", "Authorization", "header");
- }
-
- private SecurityContext securityContext() {
- return SecurityContext.builder()
- .securityReferences(defaultAuth())
- .forPaths(PathSelectors.regex("/api/.*"))
- .build();
- }
-
- private List<SecurityReference> defaultAuth() {
- AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
- AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
- authorizationScopes[0] = authorizationScope;
- return Arrays.asList(new SecurityReference("JWT", authorizationScopes));
- }
- }
复制代码
在控制器中添加安全注解:
- @GetMapping("/secure")
- @ApiOperation(value = "Secure endpoint", notes = "This endpoint requires authentication")
- @ApiResponses({
- @ApiResponse(code = 200, message = "Successfully accessed secure endpoint"),
- @ApiResponse(code = 401, message = "Unauthorized")
- })
- @SecurityRequirement(name = "JWT")
- public String secureEndpoint() {
- return "Access granted to secure endpoint";
- }
复制代码
7.4 性能问题
解决方案:
1. 限制API文档的范围
2. 禁用不必要的模型
3. 使用缓存
- @Bean
- public Docket api() {
- return new Docket(DocumentationType.SWAGGER_2)
- .select()
- .apis(RequestHandlerSelectors.basePackage("com.example.swagger.controller"))
- .paths(PathSelectors.any())
- .build()
- .apiInfo(apiInfo())
- .produces(Collections.singleton("application/json"))
- .consumes(Collections.singleton("application/json"))
- .ignoredParameterTypes(ExampleIgnoreClass.class); // Ignore certain model classes
- }
复制代码
解决方案:
1. 在开发环境启用Swagger,在生产环境禁用
2. 使用懒加载
- @Configuration
- @Profile("dev") // Only enable Swagger in development environment
- @EnableSwagger2
- public class SwaggerConfig {
- // ...
- }
复制代码
或者使用条件加载:
- @Bean
- @ConditionalOnProperty(name = "swagger.enabled", havingValue = "true")
- public Docket api() {
- return new Docket(DocumentationType.SWAGGER_2)
- // ...
- }
复制代码
在application.properties中:
- # Enable Swagger in development
- 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开发和文档编写体验。 |
|