【推荐】SpringBoot整合 Swagger2

SpringBoot项目Swagger2接口文档不显示?试试这个注解修复方案 本文深入分析了SpringBoot项目中Swagger2接口文档不显示的常见问题,提供了包括@EnableWebMvc注解、手动配置资源处理器和检查依赖版本兼容性在内的多种解决方案。特别适合遇到Swagger UI页面能访问但接口列表空白的开发者参考,帮助快速恢复接口文档显示功能。 阅读详情

目录(?)[+]

 

相信各位在公司写API文档数量应该不少,当然如果你还处在自己一个人开发前后台的年代,当我没说,如今为了前后台更好的对接,还是为了以后交接方便,都有要求写API文档。

手写Api文档的几个痛点:

  1. 文档需要更新的时候,需要再次发送一份给前端,也就是文档更新交流不及时。
  2. 接口返回结果不明确
  3. 不能直接在线测试接口,通常需要使用工具,比如postman
  4. 接口文档太多,不好管理

Swagger也就是为了解决这个问题,当然也不能说Swagger就一定是完美的,当然也有缺点,最明显的就是代码移入性比较强。

其他的不多说,想要了解Swagger的,可以去Swagger官网,可以直接使用Swagger editor编写接口文档,当然我们这里讲解的是SpringBoot整合Swagger2,直接生成接口文档的方式。

一、依赖

<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<version>2.6.1</version>
</dependency>

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

二、Swagger配置类

其实这个配置类,只要了解具体能配置哪些东西就好了,毕竟这个东西配置一次之后就不用再动了。 特别要注意的是里面配置了api文件也就是controller包的路径,不然生成的文档扫描不到接口。

package cn.saytime;

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;

/**
 * @author zh
 * @ClassName cn.saytime.Swgger2
 * @Description
 * @date 2017-07-10 22:12:31
 */
@Configuration
public class Swagger2 {

	@Bean
	public Docket createRestApi() {
		return new Docket(DocumentationType.SWAGGER_2)
				.apiInfo(apiInfo())
				.select()
				.apis(RequestHandlerSelectors.basePackage("cn.saytime.web"))
				.paths(PathSelectors.any())
				.build();
	}
	
	private ApiInfo apiInfo() {
		return new ApiInfoBuilder()
				.title("springboot利用swagger构建api文档")
				.description("简单优雅的restfun风格,http://blog.youkuaiyun.com/saytime")
				.termsOfServiceUrl("http://blog.youkuaiyun.com/saytime")
				.version("1.0")
				.build();
	}
}

用@Configuration注解该类,等价于XML中配置beans;用@Bean标注方法等价于XML中配置bean。

Application.class 加上注解@EnableSwagger2 表示开启Swagger

package cn.saytime;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication
@EnableSwagger2
public class SpringbootSwagger2Application {

	public static void main(String[] args) {
		SpringApplication.run(SpringbootSwagger2Application.class, args);
	}
}

三、Restful 接口

package cn.saytime.web;

import cn.saytime.bean.JsonResult;
import cn.saytime.bean.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zh
 * @ClassName cn.saytime.web.UserController
 * @Description
 */
@RestController
public class UserController {

	// 创建线程安全的Map
	static Map<Integer, User> users = Collections.synchronizedMap(new HashMap<Integer, User>());

	/**
	 * 根据ID查询用户
	 * @param id
	 * @return
	 */
	@ApiOperation(value="获取用户详细信息", notes="根据url的id来获取用户详细信息")
	@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Integer", paramType = "path")
	@RequestMapping(value = "user/{id}", method = RequestMethod.GET)
	public ResponseEntity<JsonResult> getUserById (@PathVariable(value = "id") Integer id){
		JsonResult r = new JsonResult();
		try {
			User user = users.get(id);
			r.setResult(user);
			r.setStatus("ok");
		} catch (Exception e) {
			r.setResult(e.getClass().getName() + ":" + e.getMessage());
			r.setStatus("error");
			e.printStackTrace();
		}
		return ResponseEntity.ok(r);
	}

	/**
	 * 查询用户列表
	 * @return
	 */
	@ApiOperation(value="获取用户列表", notes="获取用户列表")
	@RequestMapping(value = "users", method = RequestMethod.GET)
	public ResponseEntity<JsonResult> getUserList (){
		JsonResult r = new JsonResult();
		try {
			List<User> userList = new ArrayList<User>(users.values());
			r.setResult(userList);
			r.setStatus("ok");
		} catch (Exception e) {
			r.setResult(e.getClass().getName() + ":" + e.getMessage());
			r.setStatus("error");
			e.printStackTrace();
		}
		return ResponseEntity.ok(r);
	}

	/**
	 * 添加用户
	 * @param user
	 * @return
	 */
	@ApiOperation(value="创建用户", notes="根据User对象创建用户")
	@ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
	@RequestMapping(value = "user", method = RequestMethod.POST)
	public ResponseEntity<JsonResult> add (@RequestBody User user){
		JsonResult r = new JsonResult();
		try {
			users.put(user.getId(), user);
			r.setResult(user.getId());
			r.setStatus("ok");
		} catch (Exception e) {
			r.setResult(e.getClass().getName() + ":" + e.getMessage());
			r.setStatus("error");

			e.printStackTrace();
		}
		return ResponseEntity.ok(r);
	}

	/**
	 * 根据id删除用户
	 * @param id
	 * @return
	 */
	@ApiOperation(value="删除用户", notes="根据url的id来指定删除用户")
	@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long", paramType = "path")
	@RequestMapping(value = "user/{id}", method = RequestMethod.DELETE)
	public ResponseEntity<JsonResult> delete (@PathVariable(value = "id") Integer id){
		JsonResult r = new JsonResult();
		try {
			users.remove(id);
			r.setResult(id);
			r.setStatus("ok");
		} catch (Exception e) {
			r.setResult(e.getClass().getName() + ":" + e.getMessage());
			r.setStatus("error");

			e.printStackTrace();
		}
		return ResponseEntity.ok(r);
	}

	/**
	 * 根据id修改用户信息
	 * @param user
	 * @return
	 */
	@ApiOperation(value="更新信息", notes="根据url的id来指定更新用户信息")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long",paramType = "path"),
			@ApiImplicitParam(name = "user", value = "用户实体user", required = true, dataType = "User")
	})
	@RequestMapping(value = "user/{id}", method = RequestMethod.PUT)
	public ResponseEntity<JsonResult> update (@PathVariable("id") Integer id, @RequestBody User user){
		JsonResult r = new JsonResult();
		try {
			User u = users.get(id);
			u.setUsername(user.getUsername());
			u.setAge(user.getAge());
			users.put(id, u);
			r.setResult(u);
			r.setStatus("ok");
		} catch (Exception e) {
			r.setResult(e.getClass().getName() + ":" + e.getMessage());
			r.setStatus("error");

			e.printStackTrace();
		}
		return ResponseEntity.ok(r);
	}

	@ApiIgnore//使用该注解忽略这个API
	@RequestMapping(value = "/hi", method = RequestMethod.GET)
	public String  jsonTest() {
		return " hi you!";
	}
}

Json格式输出类 JsonResult.class

package cn.saytime.bean;

public class JsonResult {

	private String status = null;

	private Object result = null;

	// Getter Setter
}

实体User.class

package cn.saytime.bean;

import java.util.Date;

/**
 * @author zh
 * @ClassName cn.saytime.bean.User
 * @Description
 */
public class User {

	private int id;
	private String username;
	private int age;
	private Date ctm;

	// Getter Setter
}

项目结构:

这里写图片描述

四、Swagger2文档

启动SpringBoot项目,访问 http://localhost:8080/swagger-ui.html

这里写图片描述

具体里面的内容以及接口测试,应该一看就懂了。这里就不一一截图了。

五、Swagger注解

swagger通过注解表明该接口会生成文档,包括接口名、请求方法、参数、返回信息的等等。

  • @Api:修饰整个类,描述Controller的作用
  • @ApiOperation:描述一个类的一个方法,或者说一个接口
  • @ApiParam:单个参数描述
  • @ApiModel:用对象来接收参数
  • @ApiProperty:用对象接收参数时,描述对象的一个字段
  • @ApiResponse:HTTP响应其中1个描述
  • @ApiResponses:HTTP响应整体描述
  • @ApiIgnore:使用该注解忽略这个API
  • @ApiError :发生错误返回的信息
  • @ApiImplicitParam:一个请求参数
  • @ApiImplicitParams:多个请求参数

例子:

@ApiOperation("根据clue_id查询")
@GetMapping("/hasBox/{clueId}")
@ApiImplicitParams({
   @ApiImplicitParam(name = "clueId", value = "线索ID", required = true, paramType = "path", dataType = "String")
    })
    public CommonResponseMsg getIsBoxInstalled(@PathVariable String clueId) {

...
}

 

paramType:参数放在哪个地方

  • header-->请求参数的获取:@RequestHeader
  • query-->请求参数的获取:@RequestParam
  • path(用于restful接口)-->请求参数的获取:@PathVariable
  • body(不常用)
  • form(不常用)

例子见:https://blog.youkuaiyun.com/u011059021/article/details/79228458

 

出处 spring boot 教材:https://blog.youkuaiyun.com/saytime/column/info/16272

 

SpringBoot整合Swagger超详细完整指南 本文详细介绍了Swagger在SpringBoot项目中的完整应用指南,主要内容包括: 技术选型与版本对比:比较Springfox与SpringDoc两种实现方案,并提供版本兼容性矩阵 项目配置: 详细的环境准备与项目结构设计 Maven依赖配置示例 多环境(开发/生产)配置文件说明 核心功能实现: 基础配置类与Web配置类详解 完整的注解系统指南(Controller/实体类/枚举类) 实体建模与数据传输设计模式(DTO/VO/统一响应) 企业级实践: 用户管理和认证控制器的完整示例 安全认证配置(JWT 阅读详情

相关推荐

SpringBoot整合Swagger2:从入门到精通(亲测可用)

Swagger2是一款基于OpenAPI规范的开源工具集,用于RESTful API的设计、文档化和测试。本文介绍了Swagger2的核心价值、SpringBoot集成步骤和注解使用。通过对比传统文档方式,Swagger2具有实时同步、可视化测试和交互性等优势。集成过程包含依赖配置、SwaggerConfig类编写和UI访问。文章详细解析了控制器层注解如@Api、@ApiOperation的实战应用,以及参数描述注解的使用技巧,帮助开发者快速构建规范的API文档系统。

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 2761

SpringBoot(七):SpringBoot整合Swagger2

相信各位在公司写API文档数量应该不少,当然如果你还处在自己一个人开发前后台的年代,当我没说,如今为了前后台更好的对接,还是为了以后交接方便,都有要求写API文档。 手写Api文档的几个痛点: 文档需要更新的时候,需要再次发送一份给前端,也就是文档更新交流不及时。接口返回结果不明确不能直接在线测试接口,通常需要使用工具,比如postman接口文档太多,不好管理 Swagg

Saytime 7万+

SpringBoot整合Swagger实战项目示例

在现代微服务与前后端分离开发模式盛行的背景下,API文档的编写与维护成为开发流程中不可或缺的一环。传统方式多依赖人工编写文档,不仅效率低下,且容易与代码脱节,导致信息不一致。Swagger 作为一种开源的 API 文档解决方案,通过代码注解自动生成结构化文档,实现了 API 描述、参数说明、请求测试等核心功能的自动化。它遵循 OpenAPI 规范,支持多语言平台,能够与 SpringBoot 等主流框架无缝集成。

weixin_29443363的博客 881

Springboot整合Swaggar最简单方法

1、导入依赖 参考代码如下: <!--swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> &

weixin_56995925的博客 471

树莓派用网线连着电脑,但是找不到它的ip 以及设置静态IP

第一次的话,树莓派默认是没有ssh的。需要把内存卡取出来,新建一个ssh文件,这个简单,新建一个txt文件重命名就好了。 如果前面配置了连接wifi的conf文件,它是会自动去连接wifi的,wifi连不上,它才会去尝试有线连接。所以把它的wifi关了,才会自动用网线连接。 另外,建议设置静态ip连接,这样避免网络连接突然中断。具体在etc/dhcpcd.conf文件中,把这几行前面的#去掉,然后后面的信息改成自己的就好了。 具体改法: 第一行是ip地址,这个找到自己电脑的ip段,然后改后面两个数字就好了

wander_ing的博客 1万+

哈工大集合论与图论(下)慕课MOOC答案

答案选自2023哈工大集合论与图论慕课,慕课的题重复率很高并且具有极高的相似性,选答案时要格外注意对比选项,能力有限答案不一定面面俱到,整理不易读者且用且珍惜。

qq_34168477的博客 2902

springmvc集成swagger

1、保证项目为maven项目 2、导入jar包依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version>&lt...

weixin_30538029的博客 189

手把手教你用Xilinx SelectIO IP核搞定ADS42LB69高速ADC的DDR数据采集(附仿真调试技巧)

本文详细介绍了如何使用Xilinx SelectIO IP核实现ADS42LB69高速ADC的DDR数据采集,包括IP核配置、仿真验证和硬件调试技巧。通过精准的时序控制和实战调试方法,解决高速数据采集中的时序对齐问题,提升系统稳定性和可靠性。特别适合FPGA工程师和高速ADC接口设计者参考。

weixin_42533622的博客 152

Error creating bean with name ‘s‘ defined in class path resource [applicationContext.xml]: Initiali.

Error creating bean with name 's' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.ExceptionInInitializerError

scarlett1017的博客 5836

Coding Plan:程序员真实工作的可执行编码决策框架

Coding Plan 是一种面向工程实践的编码决策方法论,它超越传统学习路径,聚焦于代码在真实业务系统中的上下文对齐、影响控制与可演进性保障。其核心在于将模糊的开发直觉转化为可度量、可验证、可协作的日常动作,涵盖目标对齐、上下文锁定、验证闭环、协作契约和演进预留五大锚点。结合2026年AI辅助编码新范式,它强调将大模型作为‘上下文翻译器’而非代码生成器,并通过分钟级工作块、技术债主动发行、可观测性前置等机制,显著提升交付确定性与系统长期健康度。本文详解该框架的底层逻辑与落地实践。

weixin_33326218的博客 437

Windows: 深入剖析pip install SSLError与SSL模块缺失的根源及系统级修复

本文深入分析Windows系统下pip install SSLError与SSL模块缺失的根本原因,提供系统级修复方案。从Python安装包缺失SSL支持、OpenSSL库冲突到环境变量配置问题,详细讲解四大成因及对应的解决方案,包括重新安装Python、手动修复OpenSSL依赖等实用技巧,帮助开发者彻底解决HTTPS连接问题。

weixin_28595749的博客 459

项目出现问题:Error creating bean with name报错

Error creating bean with name问题另解

qq_43511320的博客 1万+

C#上位机开发揭秘:从新手到大神的蜕变之路,代码实例全解析!

上位机通常是与硬件设备(如嵌入式系统、PLC、传感器等)进行通信的计算机程序。它的作用是通过某种通信协议(如串口、TCP/IP 等)向设备发送命令,并接收设备的反馈数据。上位机需要有一个图形用户界面(GUI)来展示数据或控制硬件设备。通过本篇教程,我们介绍了 C# 上位机开发的基本步骤,从串口通信的实现,到图形用户界面的构建,再到进阶功能的实现。作为上位机开发的新手,掌握这些基础知识是非常重要的。而随着经验的积累,你可以逐步尝试更复杂的功能,比如多线程处理、数据分析与存储等。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 4828

Springboot 2.6.x整合springfox-swagger 3.0 报 Failed to start bean documentationPluginsBootstrapper的问题

spring boot 2.6整合swagger报错

苦海行舟 2340

CKA-题库-简洁参考答案-反复练习20遍-必过!!!

新版CKA考试已于2020年9月1日正式上线! 考试模式:线上考试 考试时间:2小时 认证有效期:3年 软件版本:Kubernetes v1.19 重考政策:可接受1次重考 经验水平:中級 题目数量:17题 题库量小:随机的题目重复率极高 考试时可打开两个浏览器Tab,一个是考试窗口,一个用来查阅官方文档](https://kubernetes.io/docs/) 01 Task - 英文 Create a new ClusterRole named deployment-clusterrole tha.

随笔记录-分享&记忆 7316

【动态导通电阻】p-GaN HEMTs正向和反向导通下的动态导通电阻

2024年,浙江大学的研究团队通过多组双脉冲测试方法,深入研究了两种商用p-GaN栅极HEMTs在正向和反向导通模式下的动态导通电阻(RON)特性。研究发现,肖特基型p-GaN栅极HEMTs在反向导通时动态RON比正向导通高3%-5%,而混合漏极嵌入栅注入晶体管在反向导通时动态RON降级较轻,降低约10%。此外,随着漏极电流(IDS)的增加,两种器件在反向导通时动态RON先减小后增加,形成“谷底”现象。

荷塘阅色 825

SpringBoot2.x 整合 Swagger2

【简介】 Swagger是一个RESTFUL 接口的文档在线自动生成和功能测试的框架。 Swagger 是一个规范和完整的框架。用于生成、描述、调用和可视化RestFul风格的Web服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新文件的方法、参数和模型紧密集成到服务器的代码,允许Api 来始终保持同步,Swagger让部署管理和使用功能强大的Api。 【官网】 http://swa...

日拱一卒 1398

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

SpringBoot配置swagger

引入依赖 <properties> <swagger.version>2.9.2</swagger.version> <swagger-ui.version>2.9.2</swagger-ui.version> <swagger-annotation-models-version>1.5.21</swagger-annotation-models-version> </p

yichen0429的博客 266

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

springboot /v2/api-docs 无法访问

一、问题描述 springboot 整合swagger 比较简单,博主的博客中有,还没有整合的可以查阅下,swagger 有两种模式,一种是默认模式,一种是分组模式。 1、分组模式 @Bean public Docket loginApi() { return new Docket(DocumentationType.SWAGGER_2) .groupName("登录管理") .apiInfo(apiInfo()

絮落锦乡的博客 2万+

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Springboot 3项目整合Knife4j接口文档(接口分组详细教程)

springboot 3开始javax包改成了jakarta,而swagger-oas等包中依然使用的是javax,所以报错。另外springfox已经停止更新有段时间了,并且不支持OpenAPI 3标准,升级Springboot 3.0以后会有更多问题暴露出来。而SpringBoot 3只支持OpenAPI 3规范,因此Spring官网推荐了Springdocspringfox 3.0.0: 同时兼容OpenAPI 2以及OpenAPI 3,但是停更很久了。

m0_74824496的博客 1168

MOOC课程汇总

1.第一阶段 01-构建聚合工程 02-Restful Web Service 03-Swagger2 UI的使用 04-设置跨域配置实现前后端联调 05-整合log4j打印日志 06-商品推荐 - 实现接口与联调 07-SpringBoot 整合 mybatis-pagehelper 808-购物车的存储形式 09-确认订单-订单流程梳理与订单状态 10- BO数据验证 ...

ella 278

邢台市桥东区社区停车信息管理系统

本项目采用Java语言开发,基于SpringBoot2.x框架构建,兼容MySQL5.7/8.0数据库。开发环境需配置JDK1.8、Maven及IDE工具(推荐IntelliJIDEA),支持传统war包、内嵌容器和Docker部署。运行前需创建数据库并执行初始化脚本,数据库配置可通过application.yml修改。项目已通过JUnit、Postman和JMeter等测试工具验证。

2501_93059031的博客 287

springboot3整合swagger

如参考文章3所述,Spring MVC在Spring Boot 3中将默认的路径匹配策略从。:由于Swagger2并未针对Spring Boot 3进行专门的设计和优化,因此在默认情况下,Swagger2与Spring Boot 3可能不兼容。:由于Swagger2并未针对Spring Boot 3进行专门的设计和优化,因此在默认情况下,Swagger2与Spring Boot 3可。关于Swagger与Spring Boot 3的兼容性问题,从目前的信息和参考文章中可以看出,存在一些兼容性的挑战。

zhengyibeici的博客 3202

springboot整合swagger2

springboot整合swagger

m0_46487331的博客 2206

SpringBoot 整合 Swagger 出现 404 问题

SpringBoot 整合 Swagger 只需要两个步骤: 引入 Swagger 依赖、创建 Swagger 配置类。 相关代码比较简单,不作为本文重点,放置于文末仅供参考。 本文主要讨论配置完成之后,访问遇到 404 的问题: 遇到如上报错,主要还分两种情况: 使用 swagger 3.0 以下 版本 参考【附录1 : 整合 swagger 2.9 相关代码】代码 如遇 404 错误,可能是因为当前环境拦截了 Swagger 默认的静态资源,只需在配置类文件中实现 WebMvcConfigur

新青年1号 5288

Spring Boot整合swagger使用教程(这一篇就够了)

Spring Boot整合swagger使用教程(这一篇就够了)

qq_27480007的博客 4万+
上一篇: 容器化的MySQL性能如何
下一篇: 基于 centOS 7.4 的 Zkui管理zookeeper工具
大树叶
博客等级 码龄12年 1171粉丝 664原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值