在网上看了许多教程,发现很多都是针对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按钮填写身份信息在输入框内
本文参考:
Springboot整合Swagger3全注解配置(springdoc-openapi-ui)_swagger.v3-CSDN博客