Springboot3.x整合swagger3

在网上看了许多教程,发现很多都是针对Spring Boot 2 框架的,即使有针对Spring Boot 3 的,用法也不太一样,配置项经常找不到类,经过对比测试,最后我使用的是 SpringDoc OpenAPI Starter WebMvc UI.

pom为

复制代码
<!--swaggerdoc-->
		<dependency>
			<groupId>org.springdoc</groupId>
			<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
			<version>2.2.0</version>
		</dependency>

该jar包不是swagger官方推荐的springfox包,只是前端ui一样,配置会有些许不同,并且不与swagger2配置兼容,请读者注意.

它是 Spring Boot 项目中用于自动生成 API 文档的一个依赖库。它结合了 Swagger UI,提供了一个可视化的界面来展示和测试你的 RESTful APIs。这个依赖库特别适用于使用 Spring Web MVC 框架构建的项目。
这个依赖项包括了 Swagger UI 和 SpringDoc OpenAPI Starter WebMvc API,无需额外引入其他依赖即可使用。

yml配置 (实测不加也没有报错)

复制代码
server:

  port: 8080

springdoc:

  api-docs:

    #是否开启文档功能

    enabled: true

    #swagger后端请求地址

    path: /api-docs

  swagger-ui:

    #自定义swagger前端请求路径,输入http:127.0.0.1:8080/test会自动重定向到swagger页面

    path: /test

  #包扫描路径

  packages-to-scan: com.hello.controller,com.hello.dto

  #这里定义了两个分组,可定义多个,也可以不定义

  group-configs:

      #分组名

    - group: admin

      #按路径匹配

      pathsToMatch: /admin/**

      #分组名

    - group: user

      #按包路径匹配

      packagesToScan: com.hello.api.user

新建配置类

复制代码
package cn.gdgm.jsj.springboot2024.config;




import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.headers.Header;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.annotations.security.SecuritySchemes;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;



import java.util.ArrayList;
import java.util.List;
@OpenAPIDefinition(security = @SecurityRequirement(name = "userId"))//在所有接口加上"userId"身份信息
@SecurityScheme(type = SecuritySchemeType.APIKEY, name = "userId", scheme = "", in = SecuritySchemeIn.HEADER) //in表示在请求的哪部分添加 scheme是身份参数前默认添加的字符
@SecuritySchemes({@SecurityScheme(type = SecuritySchemeType.HTTP, name = "userId2", in = SecuritySchemeIn.COOKIE),
        @SecurityScheme(type = SecuritySchemeType.APIKEY, name = "userId3", in = SecuritySchemeIn.QUERY)})//添加多个身份验证
//swagger3前端地址http://localhost:82/swagger-ui/index.html
@Configuration
public class SwaggerConfig {
    
    @Bean
    public OpenAPI springShopOpenAPI() {
        // 定义联系人信息
        Contact contact = new Contact()
                .name("Pieory") // 联系人姓名
                .url("Pieory") // 联系人网址
                .email("[email protected]"); // 联系人邮箱
        
        // 定义许可证信息
        License license = new License()
                .name("许可证名称") // 许可证名称
                .url("许可证网址 http://springdoc.org"); // 许可证网址
        
        // 定义外部文档信息
        ExternalDocumentation externalDoc = new ExternalDocumentation()
                .description("外部文档描述") // 外部文档描述
                .url("外部文档网址 https://springshop.wiki.github.org/docs"); // 外部文档网址
        // 创建 OpenAPI 实例
        return new OpenAPI()
                .info(new Info()
                        .title("API标题-后端测试") // API 标题
                        .contact(contact) // 联系人信息
                        .description("API描述-我的API文档") // API 描述
                        .version("API版本号-v1") // API 版本号
                        .license(license)) // 许可证信息
                .servers(serversList()) // 服务器列表
                .components(new Components()) // 组件定义
                .externalDocs(externalDoc); // 外部文档信息
        
    }
    
    // 获取服务器列表
    private List<Server> serversList() {
        List<Server> servers = new ArrayList<>();
        // 添加本地服务器信息
        Server localServer = new Server();
        localServer.setUrl("http://localhost:82");// 设置服务器 URL
        localServer.setDescription("Springboot2024-本地环境"); // 服务器描述
        servers.add(localServer);
        Server localServer1 = new Server();
        
        localServer1.setUrl("http://localhost:83");// 设置服务器 URL
        localServer1.setDescription("Springboot2024-本地环境2"); // 服务器描述
        servers.add(localServer1);
        
        return servers;
    }

}

在使用SecuritySchemeType.HTTP时,scheme 需要为"bearer"

复制代码
@SecurityScheme(type = SecuritySchemeType.HTTP, name = "token2",scheme = "bearer", in = SecuritySchemeIn.HEADER)

常用参数详解

@OpenAPIDefinition全局只能定义一个,主要配置文档信息和安全配置,这里列举了session的安全配置模式

@OpenAPIDefinition下的info属性配置文档信息

@OpenAPIDefinition下的security配置认证方式,name属性引入自定义的认证模式

@SecurityScheme注解就是自定义的认证模式,配置请求头携带userId

@SecurityScheme 注解的主要属性:

type:必填身份认证类型,使用SecuritySchemeType枚举定义

name:自定义认证模式名字

description:模式的描述

paramName:参数名

in:添加到请求的哪一部分使用SecuritySchemeIn枚举定义

scheme:认证参数的值前默认添加的字符串

ref:填写参数时的正则校验

在接口方法上添加@Operation注解

复制代码
import cn.gdgm.jsj.springboot2024.R.AjaxJsonResult;
import cn.gdgm.jsj.springboot2024.R.Status;
import cn.gdgm.jsj.springboot2024.domain.SysUser;
import cn.gdgm.jsj.springboot2024.service.ISysUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.headers.Header;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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;

@Tag(name = "登录接口", description = "这里为登录标签详情")
@SecurityRequirement(name = "")//单独为接口配置身份验证 这里的name要和swagger配置类中@SecurityScheme配置的name匹配 置空表示不需要身份信息
@RestController
@RequestMapping("/login")
public class LoginController {
    
    
    @Autowired
    @Qualifier("userService")
    private ISysUserService userService;
    
    @Operation(
            tags = {"注册"}, // 标签组,用于组织 API,会分配到新的"注册"文档组里
            summary = "根据SysUser查询用户信息", description = "根据SysUser查询用户信息,并返回响应结果信息",
            parameters = {
                    // @Parameter(name = "id", description = "用户ID", required = false, example = "1")//参数描述 没有的参数不要写因为会自动在方法里加参数
            },
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "响应成功",
                            content = @Content(
                                    mediaType = "application/json",
                                    schema = @Schema(
                                            title = "Resul和StudentVO组合模型",
                                            description = "返回实体,AjaxResult内data为SysUserVO模型",
                                            anyOf = {AjaxJsonResult.class, SysUser.class}//返回参数的组合模型
                                    )
                            )
                    ),
                    @ApiResponse(
                            responseCode = "500",
                            description = "响应失败",
                            content = @Content(
                                    mediaType = "application/json",
                                    schema = @Schema(
                                            title = "Resul模型",
                                            description = "返回实体,AjaxResult内 data为空",
                                            implementation = AjaxJsonResult.class//返回参数的模型
                                    )
                            )
                    )
            },
            security = {@SecurityRequirement(name = "")//将name设置为空,则表示该接口不需要身份验证 也可以在类上注解实现全部方法不需要身份验证
            }
    )
    /*登录*/
    @PostMapping("/login")
    public AjaxJsonResult login(@Parameter(description = "登录名登录密码", required = true) // 参数描述
    
                                //@Pattern(regexp = "\S{6,20}", message = "密码长度必须在6到20个字符之间") // 密码格式验证
                                @RequestBody SysUser sysUser, HttpServletRequest request) {
        
        System.out.println("login=>" + sysUser);
        SysUser user = null;
        try {
            user = userService.login(sysUser);
            if (user == null) {
                return new AjaxJsonResult<>(Status.LOGIN_FAIL.getCode(), Status.LOGIN_FAIL.getMsg(), "查询user为空");
            }
        } catch (Exception e) {
            System.out.println("登录查询失败");
            e.printStackTrace();
            return new AjaxJsonResult<>(Status.ERROR.getCode(), Status.ERROR.getMsg(), e.getMessage());
        }
        HttpSession session = request.getSession();
//        session.setAttribute(user.getUserId().toString(),user.getUserName());
        session.setAttribute(user.getUserId().toString(), user.getUserName());
        session.setMaxInactiveInterval(20);
        System.out.println("/login-user=> " + user);
        return new AjaxJsonResult<SysUser>(Status.SUCCESS.getCode(), Status.SUCCESS.getMsg(), user);
    }
    
    
    /*退出*/
    @Operation(
            tags = {"注册"}, // 标签组,用于组织 API,?会自动分配一个新的文档组
            summary = "注册", // 接口的功能简述
            description = "用户注册操作", // 更详细的描述
            responses = {//responses内容写法自行百度
                    @ApiResponse(responseCode = "200", description = "登录成功"),
                    @ApiResponse(responseCode = "400", description = "登录名或密码错误"),
                    @ApiResponse(responseCode = "500", description = "服务器内部错误", headers = @Header(name = "Content-Type", description = "返回类型"))
            },
            security = {@SecurityRequirement(name = "")//将name设置为空,则表示该接口不需要身份验证 也可以在类上注解实现全部方法不需要身份验证
            }
    )
    @PostMapping("/logout")
    public AjaxJsonResult<SysUser> logout(@RequestBody SysUser sysUser) {
        
        System.out.println("login=>" + sysUser);
        AjaxJsonResult ajaxJsonResult = new AjaxJsonResult();
        SysUser user = null;
        try {
            user = userService.register(sysUser);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return new AjaxJsonResult<>(Status.ERROR.getCode(), Status.ERROR.getMsg(), null);
        }
        
        System.out.println("/getUserBySysUserTest-user=> " + user);
        return new AjaxJsonResult<SysUser>(Status.SUCCESS.getCode(), Status.SUCCESS.getMsg(), user);
    }
    
    /*注册*/
    @Operation(
            tags = {"注册"}, // 标签组,用于组织 API,?会自动分配一个新的文档组
            summary = "注册", // 接口的功能简述
            description = "用户注册操作", // 更详细的描述
            responses = {//responses内容写法自行百度
                    @ApiResponse(responseCode = "200", description = "登录成功"),
                    @ApiResponse(responseCode = "400", description = "登录名或密码错误"),
                    @ApiResponse(responseCode = "500", description = "服务器内部错误", headers = @Header(name = "Content-Type", description = "返回类型"))
            },
            security = {@SecurityRequirement(name = "")//将name设置为空,则表示该接口不需要身份验证 也可以在类上注解实现全部方法不需要身份验证
            }
    )
    @PostMapping("/register")
    public AjaxJsonResult<SysUser> register(@RequestBody SysUser sysUser) {
        
        System.out.println("register=>" + sysUser);
        int flag = 0;
        SysUser user = null;
        try {
            user = userService.register(sysUser);
            if (user != null) {
                System.out.println("/getUserBySysUserTest-user=> " + user);
                return new AjaxJsonResult<SysUser>(Status.SUCCESS.getCode(), Status.SUCCESS.getMsg(), user);
            } else {
                System.out.println("注册失败");
                return new AjaxJsonResult<>(Status.ERROR.getCode(), Status.ERROR.getMsg(), null);
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return new AjaxJsonResult<>(Status.ERROR.getCode(), Status.ERROR.getMsg(), null);
        }
        
        
    }
    
    
}

@Operation 注解支持的主要属性:

summary:一个简短的摘要描述。

description:一个详细的描述,可以包含 Markdown 格式的文本。

tags:用于对操作进行分类的字符串数组。

operationId:一个唯一的标识符,如果未提供,则默认为方法名。

responses:一个包含预期响应的列表,可以描述不同状态码对应的响应信息。

deprecated:一个布尔值,表示该操作是否已被废弃。

externalDocs:指向外部文档的链接。

security:一个包含安全需求的对象,指定了需要哪些安全方案才能访问该操作。

servers:一个服务器列表,指定了哪些服务器支持该操作。

callbacks:一个回调列表,用于异步操作。

parameters:一个参数列表,用于描述请求中的参数。

复制代码
@ApiResponse(
                            responseCode = "500",
                            description = "响应失败",
                            content = @Content(
                                    mediaType = "application/json",
                                    schema = @Schema(
                                            title = "Resul模型",
                                            description = "返回实体,AjaxResult内 data为空",
                                            implementation = AjaxJsonResult.class//返回参数的模型
                                    )
                            )
                    )

@ApiResponse 注解的主要属性:

description:返回描述

responseCode:返回状态码

headers:响应头

content:返回信息定义 包括响应头,响应体模型

extensions:外部文档

用户实体类

复制代码
package cn.gdgm.jsj.springboot2024.domain;

import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.io.Serializable;

@Schema(name = "SysUser", description = "用户信息")
@Tag(name = "用户实体", description = "描述")
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class SysUser implements Serializable {
    
    /*用户id*/
    @Schema( description = "用户id描述")//name不能使用中文 而且要和变量名一样 因为在测试的json会自动填入name
    private Integer userId;
    
    /*用户名*/
    @Schema(description = "用户名描述")
    @NotEmpty // 字段不能为null
    private String userName;
    
    /*用户密码*/
    @Schema(description = "用户密码描述")
    private String userPassword;
    
    /*用户电话*/
    @Schema(description = "用户电话描述")
    private String userPhone;
    
}

统一返回类

复制代码
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class AjaxJsonResult <T>{
    
    private String code;
    private String msg;
    private T data;
    
}

状态码枚举

复制代码
public enum Status {
    SUCCESS("2000", "操作成功"),
    LOGIN_FAIL("4002", "用户名或密码错误"),
    ERROR("4000", "操作失败"),
    UNAUTHORIZED("4001", "未授权"),
    NOT_FOUND("4004", "未找到资源"),
    INTERNAL_SERVER_ERROR("5000", "服务器内部错误"),
    RESPONSE_FAIL_FLAG("4003", "登录状态失效"),
    RESPONSE_CODE_ERROR("4005","验证码错误");

    private String code;
    private String msg;

    Status(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public String getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

最后在拦截器配置放行 "/v3/api-docs/**","/swagger-ui/**", "/v3/api-docs/**"

复制代码
import cn.gdgm.jsj.springboot2024.Interceptor.UserLoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Arrays;
import java.util.List;

@Configuration
public class LoginConfig implements WebMvcConfigurer {
    @Autowired
    UserLoginInterceptor userLoginInterceptor;
    List<String> excludePathPatterns= Arrays.asList("/login/**","/css/**","/js/**","/pic/**","/**.html",
            "/swagger-resources/**","/webjars/.**","/v3/api-docs/**","/swagger-ui/**", "/v3/api-docs/**");//允许访问的路径
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(userLoginInterceptor)
               .addPathPatterns("/**")//设置拦截器拦截的请求路径( /** 表示拦截所有请求
               .excludePathPatterns(excludePathPatterns)//设置拦截器不拦截哪些请求路径
                ;
    }
    
}

效果如下

使用登录接口登录后点击Authorize按钮填写身份信息在输入框内

本文参考:

Spring Boot 3.x 引入springdoc-openapi (内置Swagger UI、webmvc-api)_springdoc-openapi-starter-webmvc-ui-CSDN博客

Springboot整合Swagger3全注解配置(springdoc-openapi-ui)_swagger.v3-CSDN博客

相关推荐
RainbowSea9 分钟前
6. RabbitMQ 死信队列的详细操作编写
java·消息队列·rabbitmq
RainbowSea16 分钟前
5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
java·消息队列·rabbitmq
李少兄2 小时前
Unirest:优雅的Java HTTP客户端库
java·开发语言·http
此木|西贝2 小时前
【设计模式】原型模式
java·设计模式·原型模式
可乐加.糖2 小时前
一篇关于Netty相关的梳理总结
java·后端·网络协议·netty·信息与通信
s9123601012 小时前
rust 同时处理多个异步任务
java·数据库·rust
9号达人2 小时前
java9新特性详解与实践
java·后端·面试
cg50172 小时前
Spring Boot 的配置文件
java·linux·spring boot
啊喜拔牙3 小时前
1. hadoop 集群的常用命令
java·大数据·开发语言·python·scala
anlogic3 小时前
Java基础 4.3
java·开发语言