瞧瞧人家用SpringBoot写的后端API接口,那叫一个优雅!

springboot写接口 今天来写一下springboot的接口,也是初学者,有报错的自己调试哈 第一步,创建项目 点击下一步就是了 勾选这几项 数据库选择mySQL,勾选mybatis,后续用mabatis写sql语句。 好,接下来就是。。。 等待项目的生成。 项目生成之后就是这鸟样了。。 个人喜好用yml的写法,看起来舒服些 接下来我们来创建表 mysql数据库客户端个人建议用下面这玩意,看着挺舒服的 创建了一个名为练习的库,然后往这个库里添加表,添加数据就可以... 阅读详情

点击上方“芋道源码”,选择“设为星标”

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 

19aabff8bde84ad8ebc7efecbf9726ba.png


日常工作中,我们开发接口时,一般都会涉及到参数校验、异常处理、封装结果返回 等处理。如果每个后端开发在参数校验、异常处理等都是各写各的,没有统一处理的话,代码就不优雅,也不容易维护。所以,作为一名合格的后端开发工程师,我们需要统一校验参数,统一异常处理、统一结果返回 ,让代码更加规范、可读性更强、更容易维护。

  • 使用注解,优雅进行参数校验

  • 统一结果返回

  • 统一异常处理

  • 唠叨几句

1. 使用注解,统一参数校验

假设小田螺 实现一个注册用户的功能,在controller 层,他会先进行校验参数,如下:

@RestController
@RequestMapping
public class UserController {

    @RequestMapping("addUser")
    public String addUser(UserParam userParam) {

        if (StringUtils.isEmpty(userParam.getUserName())) {
            return "用户名不能为空";
        }
        if (StringUtils.isEmpty(userParam.getPhone())) {
            return "手机号不能为空";
        }
        if (userParam.getPhone().length() > 11) {
            return "手机号不能超过11";
        }
        if (StringUtils.isEmpty(userParam.getEmail())) {
            return "邮箱不能为空";
        }

        //省略其他参数校验

        //todo 插入用户信息表
        return "SUCCESS";
    }

}

以上代码有什么问题嘛?其实没什么问题,就是校验有点辣眼睛 。正常的添加用户业务还没写,参数校验就一大堆啦。假设后来,小田螺又接了一个需求:编辑用户信息。实现编辑用户信息前,也是先校验信息,如下:

@RequestMapping("editUser")
public String editUser(UserParam userParam) {

    if (StringUtils.isEmpty(userParam.getUserName())) {
        return "用户名不能为空";
    }
    if (StringUtils.isEmpty(userParam.getPhone())) {
        return "手机号不能为空";
    }
    if (userParam.getPhone().length() > 11) {
        return "手机号不能超过11";
    }
    
    if (StringUtils.isEmpty(userParam.getEmail())) {
        return "邮箱不能为空";
    }

    //省略其他参数校验

    //todo 编辑用户信息表
    return "SUCCESS";
}

我们可以使用注解的方式,来进行参数校验,这样代码更加简洁,也方便统一管理。实际上, spring boot有个validation的组件,我们可以拿来即用。引入这个包即可:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

引入包后,参数校验就非常简洁啦,如下:

public class UserParam {

    @NotNull(message = "用户名不能为空")
    private String userName;

    @NotNull(message = "手机号不能为空")
    @Max(value = 11)
    private String phone;

    @NotNull(message = "邮箱不能为空")
    private String email;

然后在UserParam参数对象中,加入@Validated注解哈,把错误信息接收到BindingResult对象,代码如下:

@RequestMapping("addUser")
    public String addUser(@Validated UserParam userParam, BindingResult result) {
        
        List<FieldError> fieldErrors = result.getFieldErrors();
        if (!fieldErrors.isEmpty()) {
            return fieldErrors.get(0).getDefaultMessage();
        }

        //todo 插入用户信息表
        return "SUCCESS";
    }

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。

项目地址:https://github.com/YunaiV/ruoyi-vue-pro

2. 接口统一响应对象返回

如果你在你们项目代码中,看到controller 层报文返回结果,有这样的:

@RequestMapping("/hello")
public String getStr(){
  return "hello,捡田螺的小男孩";
}

//返回
hello,捡田螺的小男孩

也有这样的:

@RequestMapping("queryUser")
public UserVo queryUser(String userId) {
    return new UserVo("666", "捡田螺的小男孩");
}
//返回:
{"userId":"666","name":"捡田螺的小男孩"}

显然,如果接口返回结果不统一,前端处理就不方便,我们代码也不好维护。再比如小田螺 喜欢用Result处理结果,大田螺 喜欢用Response处理结果,可以想象一下,这些代码有多乱。

所以作为后端开发,我们项目的响应结果,需要统一标准的返回格式 。一般一个标准的响应报文对象,都有哪些属性呢?

  • code :响应状态码

  • message :响应结果描述

  • data:返回的数据

响应状态码一般用枚举表示哈:

public enum CodeEnum {

    /**操作成功**/
    SUCCESS("0000","操作成功"),
    /**操作失败**/
    ERROR("9999","操作失败"),;

    /**
     * 自定义状态码
     **/
    private String code;
    /**自定义描述**/
    private String message;

    CodeEnum(String code, String message){
        this.code = code;
        this.message = message;
    }

    public String getCode() {
        return code;
    }
    public String getMessage() {
        return message;
    }
}

因为返回的数据类型不是确定的,我们可以使用泛型,如下:

/**
 * @author 捡田螺的小男孩
 * @param <T>
 */
public class BaseResponse<T> {

    /**
     * 响应状态码(0000表示成功,9999表示失败
     */
    private String code;

    /**
     * 响应结果描述
     */
    private String message;

    /**
     * 返回的数据
     */
    private T data;

    /**
     * 成功返回
     * @param data
     * @param <T>
     * @return
     */
    public static <T> BaseResponse<T> success(T data) {
        BaseResponse<T> response= new BaseResponse<>();
        response.setCode(CodeEnum.SUCCESS.getCode());
        response.setMessage(CodeEnum.SUCCESS.getMessage());
        response.setData(data);
        return response;
    }

    /**
     *  失败返回
     * @param code
     * @param message
     * @param <T>
     * @return
     */
    public static <T> BaseResponse<T> fail(String code, String message) {
        BaseResponse<T> response = new BaseResponse<>();
        response.setCode(code);
        response.setMessage(message);
        return response;
    }
    
    public void setCode(String code) {
        this.code = code;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void setData(T data) {
        this.data = data;
    }
}

有了统一的响应体,我们就可以优化一下controller 层的代码啦:

@RequestMapping("/hello")
public BaseResponse<String> getStr(){
    return BaseResponse.success("hello,捡田螺的小男孩");
}
//output
{"code":"0000","message":"操作成功","data":"hello,捡田螺的小男孩"}

@RequestMapping("queryUser")
public BaseResponse<UserVo> queryUser(String userId) {
    return BaseResponse.success(new UserVo("666", "捡田螺的小男孩"));
}
//output
{"code":"0000","message":"操作成功","data":{"userId":"666","name":"捡田螺的小男孩"}}

基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。

项目地址:https://github.com/YunaiV/onemall

3. 统一异常处理

日常开发中,我们一般都是自定义统一的异常类,如下:

public class BizException extends RuntimeException {

    private String retCode;

    private String retMessage;

    public BizException() {
        super();
    }

    public BizException(String retCode, String retMessage) {
        this.retCode = retCode;
        this.retMessage = retMessage;
    }

    public String getRetCode() {
        return retCode;
    }

    public String getRetMessage() {
        return retMessage;
    }
}

在controller 层,很可能会有类似代码:

@RequestMapping("/query")
public BaseResponse<UserVo> queryUserInfo(UserParam userParam) {
     try {
        return BaseResponse.success(userService.queryUserInfo(userParam));
    } catch (BizException e) {
        //doSomething
    } catch (Exception e) {
        //doSomething
    }
    return BaseResponse.fail(CodeEnum.ERROR.getCode(),CodeEnum.ERROR.getMessage());
}

这块代码,没什么问题哈,但是如果try...catch太多,不是很优雅。

可以借助注解@RestControllerAdvice,让代码更优雅。@RestControllerAdvice是一个应用于Controller层的切面注解,它一般配合@ExceptionHandler注解一起使用,作为项目的全局异常处理。我们来看下demo代码哈。

还是原来的UserController,和一个会抛出异常的userService的方法,如下:

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/query")
    public BaseResponse<UserVo> queryUserInfo1(UserParam userParam) {
        return BaseResponse.success(userService.queryUserInfo(userParam));
    }
}

@Service
public class UserServiceImpl implements UserService {
    //抛出异常
    @Override
    public UserVo queryUserInfo(UserParam userParam) throws BizException {
        throw new BizException("6666", "测试异常类");
    }
}

我们再定义一个全局异常处理器,用@RestControllerAdvice注解,如下:

@RestControllerAdvice(annotations = RestController.class)
public class ControllerExceptionHandler {
}

我们有想要拦截的异常类型,比如想拦截BizException类型,就新增一个方法,使用@ExceptionHandler注解修饰,如下:

@RestControllerAdvice(annotations = RestController.class)
public class ControllerExceptionHandler {

    @ExceptionHandler(BizException.class)
    @ResponseBody
    public BaseResponse<Void> handler(BizException e) {
        System.out.println("进入业务异常"+e.getRetCode()+e.getRetMessage());
        return BaseResponse.fail(CodeEnum.ERROR.getCode(), CodeEnum.ERROR.getMessage());
    }
}

唠叨几句

本文大家学到了哪些知识呢?

  1. 为了写出更优雅、更简洁、更容易维护的代码,我们需要统一参数校验、统一响应对象返回、统一异常处理

  2. 参数校验更简洁,可以使用注解实现。

  3. 如何统一响应对象返回,一般要包括状态码、描述信息、返回数据。

  4. Controller层如何统一全局异常处理?@RestControllerAdvice+@ExceptionHandler

  5. 进阶篇?大家可以自己实现自定义注解哈,也建议去看看@RestControllerAdvice实现原理,它其实就是一个切面注解,看下它的源码即可。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:

8f3b6855643d9b133464b86ad6adbbe1.png

已在知识星球更新源码解析如下:

0abb89f41be8593f1dbc15cb22bc5e6d.png

c6477d9389feb71d29eb9533833381c7.png

7e05468b7dc5f36815f273782814f3d1.png

2dfa6fba5d76badf9f0d44d4e35446c5.png

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
springboot 如何编写增删改查后端接口,小白极速入门,附完整代码 然后 @GetMapping @DeleteMapping @PutMapping @PostMapping 都是 @RequestMapping 的衍生注解,分别对应不同的请求方式,然后有一些细节是不同的,这里不做过多的描述。这里因为是入门嘛,所以就直接对应一张表的crud,增删改查,以及一个列表查询,然后左侧的小鸟是装了一个mybatis的插件(它可以帮助提示,你的每个mapper接口和mapper.xml的映射关系)。注意观察每个接口的请求方式,以及请求的参数和请求体。 阅读详情

相关推荐

PyQtWebEngine安装避坑指南:快速解决ModuleNotFoundError

本文详细解析了PyQt5开发中常见的ModuleNotFoundError: No module named 'PyQt5.QtWebEngineWidgets'错误。核心原因是PyQt5 5.11版本后,网页引擎组件被独立为PyQtWebEngine包。文章对比了退回旧版本、独立安装及使用Conda等多种解决方案,并提供了针对Windows、macOS和Linux不同平台的实战安装指南与验证方法,帮助开发者快速解决依赖问题。

weixin_29056101的博客 428

SpringBoot API 参数校验

这套 API 参数校验方案是 SpringBoot 项目的标准化通用方案,核心由请求体校验、查询参数校验、统一异常返回三部分组成,覆盖绝大多数接口开发场景。针对新增、修改类 POST/PUT 接口,采用 @Valid 注解实现复杂嵌套参数的全自动校验,从源头避免参数漏验、非法参数穿透业务层的问题;针对 GET 查询、分页接口,通过类注解 @Validated 快速完成简单参数的合法性校验,有效防止越界查询、非法字段查询导致的数据库性能问题。

Speical的博客 470

手把手教你搭建幽冥传奇手游:从环境配置到常见Bug修复(附完整避坑指南)

本文详细指导如何从零搭建幽冥传奇手游,涵盖服务器选型、数据库部署、双区架构配置等关键步骤,并提供通天塔闪退、技能显示异常等常见Bug的修复方案。附完整避坑指南,帮助开发者高效解决90%的典型问题,确保游戏稳定运行。

weixin_29232121的博客 244

Springboot优雅的参数校验(一)

在后端的接口开发过程,实际上每一个接口都或多或少有不同规则的参数校验,有一些是基础校验,如非空校验、长度校验、大小校验、格式校验;也有一些校验是业务校验,如学号不能重重复、手机号不能重复注册等;对于业务校验,是需要和数据库交互才能知道校验结果;对于参数的基础校验,是有一些共有特征可以抽象出来,可以做成一个通用模板(java就是一种面向对象的编程语言,还记得天天快要说烂问烂的面向对象的三大特性吗?)。基于实际场景的需要,java API中定义了一些Bean校验的规范标准(JSR303:validation-a

凡夫编程 4906

AI数字人短视频数字人口播数字人分身建模流程全解析

在人工智能与计算机图形学蓬勃发展的当下,数字人建模作为打造虚拟数字人的核心环节,其流程复杂且精妙,融合了多种前沿技术与创意构思,为栩栩如生的数字人形象奠定基石。​。

2403_87518095的博客 1447

将点云坐标转换成世界坐标的demo

将点云坐标转换成世界坐标的demo

howard789的博客 2208

Spring 参数校验及通用异常信息返回

叙述用注解 @Validated、@Valid 进行参数验证,相对于以前常用的 if 等条件,会显得简练很多,而且显得更加优雅。然后是他俩的区别@Validated:用在方法入参上无法单独提供嵌套验证功能,不能用在成员属性(字段)上,也无法提示框架进行嵌套验证,能配合嵌套验证注解 @Valid 进行嵌套验证。@Valid:用在方法入参上无法单独提供嵌套验证功能,能够用在成员属性(字段)上,提示验证框架进行嵌套验证,能配合嵌套验证注解 @Valid 进行嵌套验证。

gys9895的博客 877

SAP SD跨公司销售IDOC自动记账配置实战指南

本文详细介绍了SAP SD模块中跨公司销售IDOC自动记账的配置实战指南。通过IDOC技术实现集团企业间交易的自动化处理,显著提升财务效率和准确性。文章涵盖前置配置、RFC连接、合作伙伴参数设置及财务科目分配等关键步骤,并提供了常见错误排查和性能优化建议,帮助用户快速掌握这一高效业务流程。

weixin_29284885的博客 772

花10分钟写个漂亮的后端API接口模板!

你好,我是田哥在这微服务架构盛行的黄金时段,加上越来越多的前后端分离,导致后端API接口规范变得越来越重要了。比如:统一返回参数形式、统一返回码、统一异常处理、集成swagger等。目的主要是规范后端项目代码,以及便于前端沟通联通以及问题的排查。本文内容:统一返回参数形式目前主流的返回参数形式:{ "code":200000, "message":"成功", "data":{ ...

田维常 2449

2024.6.15丨基于VFDB数据库的致病菌毒力因子注释实战指南

本文提供了一份基于VFDB数据库进行致病菌毒力因子本地化注释的实战指南。详细介绍了从环境准备、DIAMOND工具安装、VFDB数据库选择与构建,到核心比对操作及结果解读与过滤的全流程。重点阐述了本地化分析相较于在线工具在速度、稳定性和批量处理上的优势,旨在帮助微生物基因组研究人员高效、精准地识别致病菌的关键毒力因子。

weixin_29220405的博客 272

全面分析总结解决Could not transfer artifact org.apache.maven.plugins等此类问题的方法

全面分析总结解决Could not transfer artifact org.apache.maven.plugins,Could not transfer artifact xxx from/to xxx等此类问题的方法

ccjjjjdff的博客 1万+

瞧瞧人家用SpringBoot写的后端API接口,那叫一个优雅

日常工作中,我们开发接口时,一般都会涉及到参数校验、异常处理、封装结果返回等处理。如果每个后端开发在参数校验、异常处理等都是各写各的,没有统一处理的话,代码就不优雅,也不容易维护。所以,作为一名合格的后端开发工程师,我们需要统一校验参数,统一异常处理、统一结果返回,让代码更加规范、可读性更强、更容易维护。假设小田螺实现一个注册用户的功能,在controller 层,他会先进行校验参数,如下: 以上代码有什么问题嘛?其实没什么问题,就是校验有点辣眼睛。正常的添加用户业务还没写,参数校验就一大堆啦。假设后来

m0_67645544的博客 2288

IC版图设计布局经验90条!

13 如果一个cell调用其它cell,被调用的cell的vssx,vddx,vssb,vddb如果没有和外层cell连起来,要打上PIN,否则通不过diva检查.尽量在布局低层cell时就连起来。48 在匹配电路的mos管左右画上dummy,用poly,poly的尺寸与管子尺寸一样,dummy与相邻的第一个poly gate的间距等于poly gate之间的间距。8 更改cell时查看路径,一定要在正确的library下更改,以防copy过来的cell是在其他的library下,被改错。

weixin_44606964的博客 912

优雅后端API接口(转载)

更优雅、更简洁、更容易维护的代码

azhang190426的博客 158

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

瞧瞧别人家的参数校验,那叫一个优雅!

???? 这是一个或许对你有用的社群???? 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料:《项目实战(视频)》:从书中学,往事上“练”《互联网高频面试题》:面朝简历学习,春暖花开《架构 x 系统设计》:摧枯拉朽,掌控面试高频场景题《精进 Java 学习指南》:系统学习,互联网主流技术栈《必读 Java 源码专栏》:知其然,知其所以然????这是一个或许...

芋艿V 107

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

瞧瞧别人家的跨域方案,那叫一个优雅!

???? 欢迎加入小哈的星球,你将获得:专属的项目实战 /1v1 提问/Java 学习路线 /学习打卡/每月赠书/社群讨论新项目:《从零手撸:仿小红书(微服务架构)》正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...,点击查看项目介绍;《从零手撸:前后端分离博客项目(全栈开发)》2期已完结,演示链接:http...

犬小哈 135

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

深入浅出Spring Boot接口

深入浅出Spring Boot接口

CERTAINTY的博客 770

Spring boot 写一个接口

1-首先,创建一个Spring boot 项目 2-配置环境,需要配置pom和application.yml (1)pom 里添加 lombok 因为之后可能会用到: <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> (2)application的后缀名改为yml,.

m0_60549667的博客 5473

(一)还不会用springboot写接口?快看这里,手把手操作,一发入魂~

springboot入门项目,包括简单的接口开发(api),数据库操作(mybatis plus)和接口文档调试生成(knife4j)。

隐风的博客 1万+

springboot如何写一个具有RESTFul风格的后端接口

一、创建Spring Boot项目 二、 定义模型 四、创建服务层接口和实现类 1. 服务层接口   2. 服务层实现类 五、创建控制器(Controller) 六、异常处理 七、测试你的API 八、运行你的应用

sugar657657765的博客 1810

后端Springboot框架搭建APi接口开发(第一章)

快速直观的利用Stringboot搭建简易的API接口。实现后端对数据库增删改查

周彰健的博客 1万+

基于springboot接口的编写

目录1、模糊分页查询2、批量删除3、新增4、编辑此接口非彼接口。此接口是MVC的设计模式中的Controller层,一般我们会叫Controller层里的方法为接口。他们是负责接收前端或者其它服务的传来的请求,并对请求进行相应的处理,最终再将处理结果返回给前端或者其它服务。 1)Controller层 在进行模糊查询操作的时候,往往有时候需要查询的参数很多,这时候也可以考虑使用实体类接收前端传参,更改如下: 接收前端传参实体类代码如下: 2)service层定义service层接口(此接口

胜人者有力,自胜者强! 1622

用Spring Boot开发API接口

引言 前后端分离、APP交互等,大多都是通过API接口实现的。既然要进行数据交互,那么这接口就得有讲究了:既要实用,又要优雅好看! 那么,如何写一套(个)漂亮的API接口呢? 一、返回格式 API接口要求返回的格式是 text/json,我们知道网页返回的格式一般是 text/html,因此,Spring Boot为写接口,提供了两种实现方式:类注解 和 方法注解。 类注解 @Re...

冯文议技术博客 13万+

Spring Boot入门系列(二十一)如何优雅的设计 Restful API 接口版本号,实现 API 版本控制!...

前面介绍了Spring Boot 如何快速实现Restful api 接口,并以人员信息为例,设计了一套操作人员信息的接口。不清楚的可以看之前的文章:https://www.cnblogs.com/zhangweizhong/category/1657780.html。 有些人可能会问,为什么我看到很多公司的api接口文档里面,都有/api/v1/ 这样的地址呢?其实,/api 就是为了...

章为忠的专栏 1900

Springboot写简单的接口

1. 首先建一个spring的项目,选择java的版本,jdk等等参数。2.选择依赖,如图所示的四个依赖 ,然后点击create即创建项目成功。首先,声明,这个是我用来记录学习的,不是教学,本人菜鸟。note: 数据库配置要和user里边的字段保持一致。引入lombok,可以不用写get/set方法。10.然后执行成功后,在本地访问。

博客 2317
上一篇: 微服务架构及设计模式
下一篇: 是时候为 SpringBoot 3.0 做准备了!
公众号-芋道源码
博客等级 码龄10年 1634粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值