在网上看了许多教程,发现很多都是针对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: 8080springdoc:api-docs:#是否开启文档功能enabled: true#swagger后端请求地址path: /api-docsswagger-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 {@Beanpublic 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");// 设置服务器 URLlocalServer.setDescription("Springboot2024-本地环境"); // 服务器描述servers.add(localServer);Server localServer1 = new Server();localServer1.setUrl("http://localhost:83");// 设置服务器 URLlocalServer1.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会自动填入nameprivate Integer userId;/*用户名*/@Schema(description = "用户名描述")@NotEmpty // 字段不能为nullprivate 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 {@AutowiredUserLoginInterceptor userLoginInterceptor;List<String> excludePathPatterns= Arrays.asList("/login/**","/css/**","/js/**","/pic/**","/**.html","/swagger-resources/**","/webjars/.**","/v3/api-docs/**","/swagger-ui/**", "/v3/api-docs/**");//允许访问的路径@Overridepublic 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博客