springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。

导言

Swagger2、Knife4j 都是后端API接口文档。
knife4j swagger2 官方文档:https://doc.xiaominfo.com/docs/quick-start

一、swagger2介绍

其实无论是前端调用后端,还是后端调用后端,都期望有一个好的接口文档。但是这个接口文档对于程序员来说,就跟注释一样,经常会抱怨别人写的代码没有写注释,然而自己写起代码起来,最讨厌的,也是写注释。所以仅仅只通过强制来规范大家是不够的,随着时间推移,版本迭代,接口文档往往很容易就跟不上代码了。

​ 使用Swagger你只需要按照它的规范去定义接口及接口相关的信息。再通过Swagger衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,生成多种语言的客户端和服务端的代码,以及在线接口调试页面等等。

​ 这样,如果按照新的开发模式,在开发新版本或者迭代版本的时候,只需要更新Swagger描述文件,就可以自动生成接口文档和客户端服务端代码,做到调用端代码、服务端代码以及接口文档的一致性。

​为了简化swagger的使用,Spring框架对swagger进行了整合,建立了Spring-swagger项目,后面改成了现在的Springfox。通过在项目中引入Springfox,可以扫描相关的代码,生成描述文件,进而生成与代码一致的接口文档和客户端代码。

二、springBoot-swagger2实战演练

1. 快速创建项目

创建springboot项目细节请看博文:
这里只放出来主要的内容

  1. 描述
    在这里插入图片描述
  2. 插件,选择web和Lombok(上一篇博文讲的)(这里的版本,创建完项目后,我手动改成了2.7.2)
    在这里插入图片描述
  3. 项目结构
    在这里插入图片描述

2. 引入是swagger2 依赖

        <!--swagger2 依赖-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

3. swagger2 常用注解

注解 说明
@Api 用在请求的类上,例如Controller,表示对类的说明
@ApiModel 用在类上,通常是实体类,表示一个返回响应数据的信息
@ApiModelProperty 用在属性上,描述响应类的属性
@ApiOperation 用在请求的方法上,说明方法的用途、作用
@ApiImplicitParams 用在请求的方法上,表示一组参数说明
@ApiImplicitParam 用在@ApiImplicitParams注解中,指定一个请求参数的各个方面

4. 配置 application.yml(重要)

  1. 修改配置文件后缀为 application.yml
  2. 配置内容如下```
    server:
    port: 9000

    配置 swagger2 knife4j

    spring:
    mvc:

    pathmatch:
      # 配置策略
      matching-strategy: ant-path-matcher
    

    ```

  3. 官网指出:
    在这里插入图片描述
    如果不配置spring.mvc.pathmatch.matching-strategy,会爆下面错误:
    Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException

5. 创建 swagger 配置类:SwaggerConfig

创建 config/SwaggerConfig.java

package com.feng.springboot_swagger2.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;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

// 启用swagger
@EnableSwagger2
@Configuration
public class SwaggerConfig {
    // 用户接口组
    // Docket表示接口文档,用于封装接口文档相关信息(如记录扫描哪些包、文档名字、文档信息等)
    @Bean
    public Docket createRestApi1() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                // groupName : 接口文档组名字
                .apiInfo(apiInfo()).groupName("用户接口组")//创建该Api的基本信息(这些基本信息会展现在文档页面中)
                .select() //函数返回一个ApiSelectorBuilder实例用来控制哪些接口暴露给Swagger ui来展现
                // basePackage 表示扫描那个包
                .apis(RequestHandlerSelectors.basePackage("com.feng.springboot_swagger2.controller")) //指定需要扫描的包路路径
                .paths(PathSelectors.any()) //
                .build();
        return docket;
    }

    //构建 api文档的详细信息
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                //页面标题
                .title("API接口文档")
                //创建人
                .contact(new Contact("springBoot-swagger2", "https://blog.csdn.net/qq_40036754", ""))
                //版本号
                .version("1.0")
                //描述
                .description("API 描述")
                .build();
    }

}

6. 创建请求类:UserReqVO

创建/vo/req/UserReqVO.java

package com.feng.springboot_swagger2.vo.req;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
// @ApiModel用在类上,通常是实体类,表示一个返回响应数据的信息
@ApiModel(description = "用户实体")
public class UserReqVO {
    @ApiModelProperty(value = "名字")
    private String name;

    @ApiModelProperty(value = "年龄")
    private Integer age;

    @ApiModelProperty(value = "电话")
    private String phone;

}

7. 创建控制器:UserController

创建/controller/UserController.java

package com.feng.springboot_swagger2.controller;

import com.feng.springboot_swagger2.vo.req.UserReqVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Api(tags = "测试 swagger User 模块")
@RequestMapping("/api")
public class UserController {

    @ApiOperation(value = "第一个swagger接口")
    @PostMapping("/swagger")
    public UserReqVO testSwagger(@RequestBody UserReqVO vo){
        return vo;
    }
}

8. 项目结构

在这里插入图片描述

9. 测试结构

http://localhost:9000/swagger-ui.html

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
测试成功

10. pom.xml(全)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.feng</groupId>
    <artifactId>springboot_swagger2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot_swagger2</name>
    <description>springboot_swagger2 project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>

        <!--swagger2 依赖-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

三、knife4j介绍

knife4j是为Java MVC框架 集成Swagger生成Api文档的增强解决方案 ,前身是swagger-bootstrap-ui,取名knife4j是希望它能像一把匕首一样小巧、轻量,并且功能强悍。其底层是对Springfox的封装,使用方式也和Springfox一致,只是对接口文档UI进行了优化。
核心功能:

  • 文档说明:根据Swagger的规范说明,详细列出接口文档的说明,包括接口地址、类型、请求示例、请求参数、响应示例、响应参数、响应码等信息,对该接口的使用情况一目了然。

  • 在线调试:提供在线接口联调的强大功能,自动解析当前接口参数,同时包含表单验证,调用参数可返回接口响应内容、headers、响应时间、响应状态码等信息,帮助开发者在线调试。

四、springboot-knife4j 实战演练

1. 快速创建项目

  1. 项目细节
    在这里插入图片描述
  2. 插件,选择web和Lombok(上一篇博文讲的)(这里的版本,创建完项目后,我手动改成了2.7.2)
    在这里插入图片描述

2. 引入依赖

我们通过查看依赖关系发现,knife4j内部已经集成了 springfox-swagger2

        <!-- API 文档,knife4j依赖 -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.4</version>
        </dependency>

3. 创建实体类 UserReqVO 和 MenuReqVO

a、UserReqVO.java

package com.feng.springBoot_knife4j.vo.req;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "用户实体")
public class UserReqVO {

    @ApiModelProperty(value = "名字")
    private String name;

    @ApiModelProperty(value = "年龄")
    private Integer age;

    @ApiModelProperty(value = "电话")
    private String phone;
}

b、MenuReqVO.java

package com.feng.springBoot_knife4j.vo.req;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "菜单实体")
public class MenuReqVO {
    @ApiModelProperty(value = "主键")
    private int id;
    @ApiModelProperty(value = "菜单名称")
    private String name;
}

4. 创建user.controller

a、user/UserController

package com.feng.springBoot_knife4j.controller.user;

import com.feng.springBoot_knife4j.vo.req.UserReqVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/api/user")
@Api(tags = "用户模块")
public class UserController {

    @GetMapping("/getUsers")
    @ApiOperation(value = "查询所有用户", notes = "查询所有用户信息")
    public List<UserReqVO> getUser(){
        UserReqVO user = new UserReqVO();
        user.setAge(23);
        user.setName("冯坚持");
        user.setPhone("15106757434");
        List<UserReqVO> list = new ArrayList<>();
        list.add(user);
        return list;
    }

    @PostMapping("/user/list")
    @ApiOperation(value = "查询用户", notes = "查询用户信息")
    public UserReqVO getUser(@RequestBody UserReqVO user){
        return user;
    }

    @PutMapping("/update")
    @ApiOperation(value = "修改用户", notes = "修改用户信息")
    public String update(@RequestBody UserReqVO user){
        return "OK";
    }

    @DeleteMapping("/delete")
    @ApiOperation(value = "删除用户", notes = "删除用户信息")
    public String delete(int id){
        return "OK";
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页码",
                    required = true, type = "Integer"),
            @ApiImplicitParam(name = "pageSize", value = "每页条数",
                    required = true, type = "Integer"),
    })
    @ApiOperation(value = "分页查询用户信息")
    @GetMapping(value = "page/{pageNum}/{pageSize}")
    public String findByPage(@PathVariable Integer pageNum,
                             @PathVariable Integer pageSize) {
        return "OK";
    }
}

b、menu/MenuController

package com.feng.springBoot_knife4j.controller.menu;

import com.feng.springBoot_knife4j.vo.req.MenuReqVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/api/menu")
@Api(tags = "菜单模块")
public class MenuController {

    @GetMapping("/getMenus")
    @ApiOperation(value = "查询所有菜单", notes = "查询所有菜单信息")
    public List<MenuReqVO> getMenus(){
        MenuReqVO menu = new MenuReqVO();
        menu.setId(100);
        menu.setName("feng");
        List<MenuReqVO> list = new ArrayList<>();
        list.add(menu);
        return list;
    }

    @PostMapping("/save")
    @ApiOperation(value = "新增菜单", notes = "新增菜单信息")
    public String save(@RequestBody MenuReqVO menu){
        return "OK";
    }

    @PutMapping("/update")
    @ApiOperation(value = "修改菜单", notes = "修改菜单信息")
    public String update(@RequestBody MenuReqVO menu){
        return "OK";
    }

    @DeleteMapping("/delete")
    @ApiOperation(value = "删除菜单", notes = "删除菜单信息")
    public String delete(int id){
        return "OK";
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页码", required = true, type = "Integer"),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, type = "Integer"),
    })
    @ApiOperation(value = "分页查询菜单信息")
    @GetMapping(value = "page/{pageNum}/{pageSize}")
    public String findByPage(@PathVariable Integer pageNum, @PathVariable Integer pageSize) {
        return "OK";
    }
}

5. 创建属性配置类SwaggerProperties

创建配置属性类SwaggerProperties,相比于之前我们对swagger的直接在配置文件中写死,这样可以对接口文档进行灵活的配置,这样我们直接可以通过在application.yml中进行接口文档的配置分组以及不分组。

package com.feng.springBoot_knife4j.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/*
 * 配置属性类,用于封装接口文档相关属性,从配置文件读取信息封装成当前对象
 */
@Data
@ConfigurationProperties(prefix = "feng.swagger")
public class SwaggerProperties {
    private String title;            // 标题 interface document
    private String group = "";       // 自定义组名
    private String description;      // 描述 this is a interface document
    private String version;          // 版本 1.0
    private Contact contact = new Contact(); //联系人
    private String basePackage;      // swagger会解析的包路径: com.feng.springBoot_knife4j
    private Map<String, DocketInfo> docket = new HashMap<>(); //分组文档
    private List<String> basePath = new ArrayList<>(); // swagger 会解析的url规则
    private List<String> excludePath = new ArrayList<>();//在basePath基础上需要排除的url规则

    public String getGroup() {
        if (group == null || "".equals(group)) {
            return title;
        }
        return group;
    }
    @Data
    public static class DocketInfo {
        // 下面这三个走的时配置文件
        private String title;       //标题
        private String group;       //自定义组名
        private String basePackage; //swagger会解析的包路径

        // 下面的是默认的,多出来的字段
        private String description = "在线文档"; //描述
        private String version = "1.0"; //版本
        private Contact contact = new Contact(); //联系人
        private List<String> basePath = new ArrayList<>(); //swagger会解析的url规则
        private List<String> excludePath = new ArrayList<>();//在basePath基础上需要排除的url
        public String getGroup() {
            if (group == null || "".equals(group)) {
                return title;
            }
            return group;
        }
    }
    @Data
    public static class Contact {
        private String name = "FengJianChi"; //联系人
        private String url = ""; //联系人url
        private String email = ""; //联系人email
    }
}

6. application.yml

server:
  port: 7788

# 配置 swagger2 knife4j
spring:
  mvc:
    pathmatch:
      # 配置策略
      matching-strategy: ant-path-matcher

# swagger 配置
feng:
  swagger:
    title: interface document   # 接口文档
    description: this is a interface document # 这是接口文档
    version: 1.0
    basePackage: com.feng.springBoot_knife4j
    enabled: true   # 是否启用 swagger
    docket:         # 对接口文档进行分组,不写则不进行分组,我们在 SwaggerProperties 定义 docket 为 Map<String, DocketInfo>
      user:         # user接口文档组
        title: user_module #  用户模块
        group: user_module_group # 用户模块组
        base-package: com.feng.springBoot_knife4j.controller.user
      menu:         # menu接口文档组
        title: menu_module # 菜单模块
        group: menu_module_group # 菜单模块组
        base-package: com.feng.springBoot_knife4j.controller.menu

7. 创建配置类SwaggerAutoConfiguration(认真读)

package com.feng.springBoot_knife4j.config;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

@Configuration
// swagger开关,这里表示 feng.swagger.enabled为true,即我们在 application.yml 中配置 feng.swagger.enabled: true才会启用,
// matchIfMissing = true 表示不写则默认为true
@ConditionalOnProperty(name = "feng.swagger.enabled", havingValue = "true",
        matchIfMissing = true)
// 启用swagger
@EnableSwagger2
// 指定配置属性类
@EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerAutoConfiguration implements BeanFactoryAware {

    @Autowired
    private SwaggerProperties swaggerProperties;

    private BeanFactory beanFactory;

    @Bean
    @ConditionalOnMissingBean
    // 接口文档不分组则list为1个,分组则为多个
    public List<Docket> createRestApi(){
        // 强转为可配置的bean工厂
        ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
        // 创建一个容器
        List<Docket> docketList = new LinkedList<>();

        // 如果:没有分组,则走 默认接口文档
        if (swaggerProperties.getDocket().isEmpty()) {
            Docket docket = createDocket(swaggerProperties);
            // 注册为单例对象,通过bean工厂来进行管理,使用 title 作为key,value 为 docket 接口文档对象
            configurableBeanFactory.registerSingleton(swaggerProperties.getTitle(), docket);
            docketList.add(docket);
            return docketList;
        }

        // 否则:分组创建,遍历
        for (String groupName : swaggerProperties.getDocket().keySet()){
            SwaggerProperties.DocketInfo docketInfo = swaggerProperties.getDocket().get(groupName);
            ApiInfo apiInfo = new ApiInfoBuilder()
                    //页面标题
                    .title(docketInfo.getTitle())
                    //创建人
                    .contact(new Contact(docketInfo.getContact().getName(),
                            docketInfo.getContact().getUrl(),
                            docketInfo.getContact().getEmail()))
                    //版本号
                    .version(docketInfo.getVersion())
                    //描述
                    .description(docketInfo.getDescription())
                    .build();

            // base-path处理
            // 当没有配置任何path的时候,解析/**
            if (docketInfo.getBasePath().isEmpty()) {
                docketInfo.getBasePath().add("/**");
            }

            List<Predicate<String>> basePath = new ArrayList<>();
            for (String path : docketInfo.getBasePath()) {
                basePath.add(PathSelectors.ant(path));
            }

            // exclude-path处理,
            List<Predicate<String>> excludePath = new ArrayList<>();
            for (String path : docketInfo.getExcludePath()) {
                excludePath.add(PathSelectors.ant(path));
            }

            Docket docket = new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo)
                    .groupName(docketInfo.getGroup())
                    .select()
                    //为当前包路径
                    .apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage()))
                    .paths(Predicates.and(Predicates.not(Predicates.or(excludePath)),Predicates.or(basePath)))
                    .build();
            // 注册为单例对象,通过bean工厂来进行管理,使用title作为key,value为docket接口文档对象
            configurableBeanFactory.registerSingleton(groupName, docket);
            // 添加
            docketList.add(docket);
        }
        return docketList;
    }

    //构建 api文档的详细信息
    private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
        return new ApiInfoBuilder()
                //页面标题
                .title(swaggerProperties.getTitle())
                //创建人
                .contact(new Contact(swaggerProperties.getContact().getName(),
                        swaggerProperties.getContact().getUrl(),
                        swaggerProperties.getContact().getEmail()))
                //版本号
                .version(swaggerProperties.getVersion())
                //描述
                .description(swaggerProperties.getDescription())
                .build();
    }

    //创建 默认接口文档 对象
    private Docket createDocket(SwaggerProperties swaggerProperties) {
        //API 基础信息
        ApiInfo apiInfo = apiInfo(swaggerProperties);

        // base-path处理
        // 当没有配置任何path的时候,解析/**
        if (swaggerProperties.getBasePath().isEmpty()) {
            swaggerProperties.getBasePath().add("/**");
        }
        List<Predicate<String>> basePath = new ArrayList<>();
        for (String path : swaggerProperties.getBasePath()) {
            basePath.add(PathSelectors.ant(path));
        }

        // exclude-path处理
        List<Predicate<String>> excludePath = new ArrayList<>();
        for (String path : swaggerProperties.getExcludePath()) {
            excludePath.add(PathSelectors.ant(path));
        }

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo)
                .groupName(swaggerProperties.getGroup())
                .select()
                .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
                .paths(Predicates.and(Predicates.not(Predicates.or(excludePath)),Predicates.or(basePath)))
                .build();
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        // 获取bean工厂对象
        this.beanFactory = beanFactory;
    }
}

8. 启动项目/测试

  1. 执行启动类main方法启动项目
  2. 访问地址:http://localhost:7788/doc.html
    在这里插入图片描述
  3. 之后我们可以对api接口进行调试,如删除用户调试,
    在这里插入图片描述

9. 不分组,修改 application.yml

server:
  port: 7788
pinda:
  swagger:
    enabled: true #是否启用swagger
    title: test模块
    base-package: cn.itcast.controller

再次访问地址:http://localhost:7788/doc.html
在这里插入图片描述
可以看到所有的接口在一个分组中。

10. 定制starter(一个小的技术点)

这里就不讲了,送上博文,最下面就是定制start
https://blog.csdn.net/qq_45745964/article/details/122525640

项目结构

相关文章
|
16天前
|
机器学习/深度学习 Python
堆叠集成策略的原理、实现方法及Python应用。堆叠通过多层模型组合,先用不同基础模型生成预测,再用元学习器整合这些预测,提升模型性能
本文深入探讨了堆叠集成策略的原理、实现方法及Python应用。堆叠通过多层模型组合,先用不同基础模型生成预测,再用元学习器整合这些预测,提升模型性能。文章详细介绍了堆叠的实现步骤,包括数据准备、基础模型训练、新训练集构建及元学习器训练,并讨论了其优缺点。
33 3
|
15天前
|
监控 Java 数据库连接
详解Spring Batch:在Spring Boot中实现高效批处理
详解Spring Batch:在Spring Boot中实现高效批处理
82 12
|
15天前
|
安全 Java 测试技术
详解Spring Profiles:在Spring Boot中实现环境配置管理
详解Spring Profiles:在Spring Boot中实现环境配置管理
55 10
|
11天前
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
46 5
|
1月前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
2月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
97 2
|
2月前
|
安全 Java API
SpringSecurity结合knife4j实现swagger文档
通过将Spring Security与Knife4j相结合,我们不仅能够为RESTful API提供强大的安全防护,还能保证API文档的易用性和可访问性,这对于API的设计、开发和维护来说至关重要。这种集成方式不仅提升了开发效率,也优化了API使用者的体验,是现代API驱动开发中不可或缺的一环。
91 0
|
Java 数据库连接 数据库
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
197 2
|
18天前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
36 1
SpringBoot入门(7)- 配置热部署devtools工具