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("1112@qq.com"); // 联系人邮箱
        
        // 定义许可证信息
        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博客

相关推荐
小金的学习笔记几秒前
SpringBootWeb案例-2
java·服务器·springboot·web
杰九3 分钟前
【全栈】SprintBoot+vue3迷你商城(2)
java·数据库·spring boot·mysql
华年源码3 分钟前
基于springboot的课程作业管理系统(源码+数据库+文档)
java·数据库·毕业设计·源码·springboot
Java知识日历3 小时前
【内含例子代码】Spring框架的设计模式应用(第二集)
java·开发语言·后端·spring·设计模式
尘浮生5 小时前
Java项目实战II基于微信小程序的家庭大厨(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven
Java知识技术分享6 小时前
spring boot通过文件配置yaml里面的属性
java·spring boot·后端
一休哥助手6 小时前
深入解析Spring Boot项目的类加载与启动流程
java·spring boot·后端
丁总学Java6 小时前
定义一个名为 MyCache 的 Spring 配置类
java·spring
m0_634601666 小时前
2025.1.2
java·服务器·数据库