鞍山市网站建设_网站建设公司_数据统计_seo优化
2026/1/11 5:59:46 网站建设 项目流程

原SpringBoot2.7.18升级至3.3.0之后,Knife4j进行同步升级(Spring Boot 3 只支持OpenAPI3规范),从原3.0.3(knife4j-spring-boot-starter)版本升级至4.5.0(knife4j-openapi3-jakarta-spring-boot-starter),以下是升级过程与注意事项等

版本信息

  • JDK 21
  • Maven 3.9.6
  • SpringBoot 3.3.0
  • Knife4j 4.5.0(截止2024-06-18最新仍为4.5.0)

一、pom.xml引入依赖

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.3.0</version><!-- 2.7.18↑--> <relativePath/> </parent> <dependencies> ... <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <version>4.5.0</version> </dependency> ... </dependencies>

二、yml中配置

# Knife4j配置 # springdoc-openapi配置 springdoc: # get请求多参数时不需要添加额外的@ParameterObject和@Parameter注解 default-flat-param-object: true # 启用swaggerUI swagger-ui: #自定义swagger前端请求路径,输入http:127.0.0.1:8080/swagger-ui.html会自动重定向到swagger页面 path: /swagger-ui.html enabled: true # tags-sorter: alpha # 标签的排序方式 alpha:按照子母顺序排序(@ApiSupport注解排序不生效,因此需要设置) # operations-sorter: alpha # 接口的排序方式 alpha:按照子母顺序排序(@ApiOperationSupport注解排序生效,因此这里不作设置) operations-sorter: order # 设置规则为order,该规则会使用Knife4j的增强排序扩展规则`x-order` # 启用文档,默认开启 api-docs: path: /v3/api-docs #swagger后端请求地址 enabled: true # knife4j相关配置 可以不用改 knife4j: enable: true #开启knife4j,无需添加@EnableKnife4j注解 setting: language: ZH_CN # 中文:ZH_CN 英文:EN enable-swagger-models: true enable-dynamic-parameter: false footer-custom-content: "<strong>Copyright ?? 2024 Keyidea. All Rights Reversed</strong>" enable-footer-custom: true enable-footer: true enable-document-manage: true documents: #文档补充说明 - name: MarkDown语法说明 locations: classpath:static/markdown/grammar/* group: 01-系统接口 # 此处分组必须使用在Knife4jConfig已存在的分组名group,当存在displayName时,使用displayName名称 - name: 补充文档 locations: classpath:static/markdown/others/* group: 01-系统接口 # 此处分组必须使用在Knife4jConfig已存在的分组名group,当存在displayName时,使用displayName名称

说明:使用knife4j.documents配置补充文档时,需要注意,文档格式必须为markdown格式,另外,文件存放位置如下

Knife4j补充文档存放位置

实际呈现如下

补充文档

三、Knife4jConfig配置

StatusCode类见附录A

package cn.keyidea.common.config; import cn.keyidea.common.constant.StatusCode; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; 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.media.Content; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springdoc.core.models.GroupedOpenApi; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Map; /** * Knife4jConfig * 注意:分组名称暂时只能使用英文或数字,在4.0.0~4.5.0的Knife4j版本中使用中文分组会出现页面访问异常 * <p> * 解决:(2024-06-18)保持原有分组名group不变,新增displayName中文名称; * 特别注意:设置displayName后,knife4j.documents.name配置文档时,需使用displayName名称 * <p> * * @author qyd * @date 2024-04-13 */ @Configuration public class Knife4jConfig { private final static Logger logger = LoggerFactory.getLogger(Knife4jConfig.class); private static final String SERVICE_URL = "http://127.0.0.1:7004/tj4/doc.html"; private static final String API_INFO_TITLE = "软件接口文档"; private static final String API_INFO_VERSION = "V1.0"; private static final String API_INFO_DESCRIPTION = "Api接口列表"; private static final String API_INFO_LICENSE = "2024年度内部文档,违拷必究."; // 2024集同接口 @Bean public GroupedOpenApi api4() { return GroupedOpenApi.builder() .group("04-2024-api") .displayName("04-2024集同接口") .packagesToScan("cn.keyidea.second") // 自定义全局响应码 .addOpenApiCustomizer((this::setCustomStatusCode)) .build(); } // 2023集同接口 @Bean public GroupedOpenApi api3() { return GroupedOpenApi.builder() .group("03-2023-api") .displayName("03-2023集同接口") .packagesToScan("cn.keyidea.control") // 自定义全局响应码 .addOpenApiCustomizer((this::setCustomStatusCode)) .build(); } // 业务接口 @Bean public GroupedOpenApi api2() { return GroupedOpenApi.builder() .group("02-business-api") .displayName("02-业务接口") .packagesToScan("cn.keyidea.business") // .pathsToMatch("/v1/**") .addOpenApiMethodFilter(method -> method.isAnnotationPresent(io.swagger.v3.oas.annotations.Operation.class)) // 自定义全局响应码 .addOpenApiCustomizer((this::setCustomStatusCode)) .build(); } // 系统接口 @Bean public GroupedOpenApi api1() { // 创建了一个api接口的分组 return GroupedOpenApi.builder() // 分组名称,使用英文,中文访问异常(使用displayName设置中文名,避免直接使用group设置中文时访问异常) .group("01-sys-api") .displayName("01-系统接口") // 使用displayName设置中文接口分组名时,group仍不可或缺 .packagesToScan("cn.keyidea.sys") // 自定义全局响应码 .addOpenApiCustomizer((this::setCustomStatusCode)) .build(); } @Bean public OpenAPI openAPI() { return new OpenAPI() .info(new Info() .title(API_INFO_TITLE) .description(API_INFO_DESCRIPTION) .version(API_INFO_VERSION) .contact(new Contact().name("Keyidea").email("support@keyidea.cn")) .license(new License().name(API_INFO_LICENSE).url(SERVICE_URL)) ); } /** * 设置自定义错误码 * * @param openApi openApi对象 */ private void setCustomStatusCode(OpenAPI openApi) { if (openApi.getPaths() != null) { Paths paths = openApi.getPaths(); for (Map.Entry<String, PathItem> entry : paths.entrySet()) { String key = entry.getKey(); PathItem value = entry.getValue(); // put方式自定义全局响应码 Operation put = value.getPut(); // get方式自定义全局响应码 Operation get = value.getGet(); // delete方式自定义全局响应码 Operation delete = value.getDelete(); // post方式自定义全局响应码 Operation post = value.getPost(); if (put != null) { put.setResponses(handleResponses(put.getResponses())); } if (get != null) { get.setResponses(handleResponses(get.getResponses())); } if (delete != null) { delete.setResponses(handleResponses(delete.getResponses())); } if (post != null) { post.setResponses(handleResponses(post.getResponses())); } } } } /** * 处理不同请求方式中的自定义响应码 * - 响应码中使用原有的响应体Content(否则会造成BaseRes中通用的data无法解析各自的对象) * - 使用原生的ApiResponses作为返回体(否则会造成前端响应示例和响应内容中丢失注释) * * @param responses 响应体集合 * @return 返回处理后的响应体集合 */ private ApiResponses handleResponses(ApiResponses responses) { // 设置默认Content Content content = new Content(); // 以下代码注释,因为无论如何都会从原生responses中获取到一个Content // MediaType mediaType = new MediaType(); // Schema schema = new Schema(); // schema.set$ref("#/components/schemas/BaseRes"); // mediaType.setSchema(schema); // content.addMediaType("*/*", mediaType); // 从原来的responses中获取原生Content for (Map.Entry<String, ApiResponse> entry : responses.entrySet()) { String key = entry.getKey(); ApiResponse apiResponse = entry.getValue(); if (apiResponse != null) { content = apiResponse.getContent(); break; } } // 获取全部全局响应自定义列表 Map<Integer, String> map = StatusCode.toMap(); // 设置全局响应码 for (Map.Entry<Integer, String> entry : map.entrySet()) { ApiResponse api = new ApiResponse(); api.setContent(content); api.description(entry.getValue()); responses.addApiResponse(entry.getKey() + "", api); } return responses; } }

四、ShiroConfig中放行Swagger相关路径

如果SpringBoot未集成Shiro,那么此处无需关注。

... // Shiro放行swagger2(Knife4j) // filterMap.put("/doc.html", "anon"); // filterMap.put("/swagger-resources/**", "anon"); // filterMap.put("/v2/**", "anon"); // filterMap.put("/webjars/**", "anon"); // Shiro放行swagger3(Knife4j) filterMap.put("/doc.html", "anon"); filterMap.put("/swagger-resources/**", "anon"); filterMap.put("/v3/**", "anon"); filterMap.put("/webjars/**", "anon"); filterMap.put("/swagger-ui/**", "anon"); ...

五、注解更新

swagger 3 注释的包是io.swagger.v3.oas.annotations

1.原生注解更新
# Controller注解更新 @Api → @Tag @ApiSort → @ApiSupport # 类接口注解更新 @ApiIgnore→@Parameter(hidden = true)或@Operation(hidden = true)或@Hidden @ApiImplicitParam → @Parameter @ApiImplicitParams → @Parameters @ApiOperation(value = "foo", notes = "bar") → @Operation(summary = "foo", description = "bar") @ApiResponse(code = 404, message = "foo") → @ApiResponse(responseCode = "404", description = "foo") # 实体类注解更新 @ApiModel → @Schema @ApiModelProperty(hidden = true) → @Schema(accessMode = READ_ONLY) @ApiModelProperty → @Schema @ApiParam → @Parameter
2.全局替换示例
## 全局替换原有注解 @Api(tags -> @Tag(name @ApiSort( -> @ApiSupport(order = , dataType = "Integer", dataTypeClass = Integer.class -> , in = ParameterIn.DEFAULT , dataType = "String", dataTypeClass = String.class -> , in = ParameterIn.DEFAULT , paramType = "path", in = ParameterIn.DEFAULT , paramType = "path", dataType = "Integer", dataTypeClass = Integer.class -> , in = ParameterIn.PATH , dataType = "Date", dataTypeClass = Date.class -> @ApiOperation(value -> @Operation(summary @ApiImplicitParams -> @Parameters @ApiModel(value | @ApiModelProperty(value -> @Schema(name | @Schema(description required = true | required = false (限定为entity或vo等实体类包进行更换) -> requiredMode = Schema.RequiredMode.REQUIRED requiredMode = Schema.RequiredMode.NOT_REQUIRED ## javax注解更改(jakarta) import javax.xxx; -> import jakarta.xxx;

六、典型应用

1.文件上传(与自定义错误码)

Knife4jConfig类中已经完美解决了全局自定义错误码,因此在单个接口中已不建议再写,除非有特殊要求。
以下接口类中自定义错误码仅为示例。

··· import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; ··· import org.springframework.web.multipart.MultipartFile; ··· /** * 系统公共类 * * @author qyd * @date 2022-10-17 */ @ApiSupport(order = 1) @Tag(name = "1-系统公共类", description = "系统公共类") @RestController // @RequestMapping(name = "/sys/common/", produces = MediaType.APPLICATION_JSON_VALUE) @RequestMapping("/sys/common/") public class CommonController { private final static Logger logger = LoggerFactory.getLogger(CommonController.class); @Autowired private SysFileLogService sysFileService; @SysLogAnnotation(module = "公共类", serviceDesc = "公共类-文件上传", serviceType = ConstantsExpand.ServiceType.UPLOAD) @ApiOperationSupport(author = "qyd", order = 1) @Operation(summary = "文件上传", description = "") @Parameters({ @Parameter(name = "file", description = "单文件上传", required = true, schema = @Schema(type = "file", format = "binary"), in = ParameterIn.DEFAULT), @Parameter(name = "fileType", description = "文件类型", required = true, example = "txt", in = ParameterIn.DEFAULT), @Parameter(name = "type", description = "是否使用文件原始名称:1-使用,其他-不使用(使用随机UUID)", required = false, example = "1", in = ParameterIn.DEFAULT) }) @ApiResponses({ @ApiResponse(responseCode = "1000", description = "响应成功"), @ApiResponse(responseCode = "1001", description = "非法字段"), }) @PostMapping("uploadFile") public BaseRes uploadFile(@RequestPart(value = "file", required = true) MultipartFile file, @RequestParam(value = "fileType", required = true) String fileType, @RequestParam(value = "type", required = false) Integer type) { return sysFileService.uploadFile(file, fileType, type); } }
2.实体类(分页参数基类PageObject
package cn.keyidea.common.bean; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; import java.io.Serializable; /** * 分页基类 分页参数对象 * * @author qyd * @date 2024-06-05 */ @SuperBuilder @AllArgsConstructor @NoArgsConstructor @Data @Schema(name = "PageObject", description = "分页对象") public class PageObject implements Serializable { // 前端实际使用天基三期(React)写法当前页使用的是page @NotNull(message = "当前页不能为NULL") @Schema(description = "当前页,默认1", name = "page", example = "1", type = "integer", requiredMode = Schema.RequiredMode.REQUIRED) private Integer page; @NotNull(message = "分页数不能为NULL") @Schema(description = "分页数,默认15", name = "pageSize", example = "15", type = "integer", requiredMode = Schema.RequiredMode.REQUIRED) private Integer pageSize; @Schema(description = "排序字段", name = "orderBy", example = "", requiredMode = Schema.RequiredMode.NOT_REQUIRED) private String orderBy; @Schema(description = "排序方式:false-asc,true-desc", name = "desc", type = "boolean", example = "false", requiredMode = Schema.RequiredMode.NOT_REQUIRED) private Boolean desc; }
3.接口类-分页查询/新增/更新/删除/导入示例

已TLE数据的增删查改为例进行说明。

package cn.keyidea.business.controller; import cn.keyidea.business.entity.Tle; import cn.keyidea.business.service.TleService; import cn.keyidea.common.annotation.SysLogAnnotation; import cn.keyidea.common.bean.BaseRes; import cn.keyidea.common.constant.ConstantsExpand; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; /** * <p> * 卫星TLE信息表 * </p> * * @author qyd * @since 2022-10-12 */ @ApiSupport(order = 2) @Tag(name = "2-卫星TLE管理", description = "卫星两行根数管理") @RestController @RequestMapping("/v1/tle") public class TleController { private final static Logger logger = LoggerFactory.getLogger(TleController.class); @Autowired private TleService tleService; @SysLogAnnotation(module = "TLE管理", serviceDesc = "TLE管理-分页查询", serviceType = ConstantsExpand.ServiceType.QUERY) @ApiOperationSupport(author = "qyd", order = 1) @Operation(summary = "分页查询") @Parameters({ @Parameter(name = "sceneId", description = "场景ID", required = false, example = "1", in = ParameterIn.DEFAULT), @Parameter(name = "tleCode", description = "节点标识,支撑模糊查询", required = false, example = "0101", in = ParameterIn.DEFAULT), @Parameter(name = "type", description = "卫星类型:0-低轨卫星,1-中轨卫星,2-高轨卫星,3-天基用户", required = false, example = "0", in = ParameterIn.DEFAULT), @Parameter(name = "current", description = "当前页", required = true, example = "1", in = ParameterIn.DEFAULT), @Parameter(name = "pageSize", description = "分页数", required = true, example = "15", in = ParameterIn.DEFAULT) }) @GetMapping("listPage") public BaseRes<BaseRes.DataList<Tle>> listPage(@RequestParam(value = "sceneId", required = false) Integer sceneId, @RequestParam(value = "tleCode", required = false) String tleCode, @RequestParam(value = "type", required = false) Integer type, @RequestParam(value = "current", required = true, defaultValue = "1") Integer pageNumber, @RequestParam(value = "pageSize", required = true, defaultValue = "15") Integer pageSize) { Page<Tle> page = new Page<>(pageNumber, pageSize); return tleService.listPage(page, sceneId, tleCode, type); } @SysLogAnnotation(module = "TLE管理", serviceDesc = "TLE管理-TLE详情", serviceType = ConstantsExpand.ServiceType.QUERY) @ApiOperationSupport(author = "qyd", order = 2) @Operation(summary = "TLE详情") @Parameter(name = "id", description = "主键ID", required = true, example = "1", in = ParameterIn.PATH) @GetMapping("getById/{id}") public BaseRes getById(@PathVariable(value = "id", required = true) Integer id) { return tleService.getOneById(id); } @SysLogAnnotation(module = "TLE管理", serviceDesc = "TLE管理-TLE新增", serviceType = ConstantsExpand.ServiceType.ADD) @ApiOperationSupport(author = "qyd", order = 3, includeParameters = { "tle.tleCode", "tle.line1", "tle.line2", "tle.sceneId", "tle.remark" }) @Operation(summary = "TLE新增", description = "") @PostMapping("add") public BaseRes add(@Valid @RequestBody Tle tle) { return tleService.add(tle); } @SysLogAnnotation(module = "TLE管理", serviceDesc = "TLE管理-TLE更新", serviceType = ConstantsExpand.ServiceType.UPDATE) @ApiOperationSupport(author = "qyd", order = 4, includeParameters = { "tle.id", "tle.tleCode", "tle.line1", "tle.line2", "tle.sceneId", "tle.remark" }) @Operation(summary = "TLE更新") @PutMapping("update") public BaseRes update(@Valid @RequestBody Tle tle) { return tleService.update(tle); } @SysLogAnnotation(module = "TLE管理", serviceDesc = "TLE管理-TLE更新", serviceType = ConstantsExpand.ServiceType.DELETE) @ApiOperationSupport(author = "qyd", order = 5) @Operation(summary = "TLE删除", description = "") @Parameter(name = "id", description = "主键ID", required = true, example = "1", in = ParameterIn.PATH) @DeleteMapping("delete/{id}") public BaseRes delete(@PathVariable(value = "id", required = true) Integer id) { return tleService.delete(id); } @SysLogAnnotation(module = "TLE管理", serviceDesc = "TLE管理-TLE导入", serviceType = ConstantsExpand.ServiceType.IMPORT) @ApiOperationSupport(author = "qyd", order = 6) @Operation(summary = "TLE导入", description = "TLE导入数据格式请参看模板:<a href='template/txt/tle.txt'>TLE文本导入模板</a>") @Parameters({ @Parameter(name = "file", description = "单文件上传", required = true, schema = @Schema(type = "file", format = "binary"), in = ParameterIn.DEFAULT), @Parameter(name = "sceneId", description = "场景ID", required = true, example = "1", in = ParameterIn.DEFAULT) }) @PostMapping(value = "importTle") public BaseRes importTle(@RequestPart(value = "file", required = true) MultipartFile file, @RequestParam(value = "sceneId", required = true) Integer sceneId) { return tleService.importTle(file, sceneId); } }

七、FAQ

1.关于Controller排序说明
a) 使用tags-sorter排序问题说明

使用tags-sorter的alpha排序,是为字母排序,会造成在@Tag的name中使用00-xx/01-xx/02-xx/.../10-xxx进行说明时,排序为00-xx/10-xx/01-xx/.../09-xxx,为了对排序进行强一致,所以废弃使用tags-sorter的alpha排序,使用注解@ApiSupport进行排序定义。

b) 解决使用@ApiSupport不生效问题
  1. 移除yml中对tags-sorter的alpha排序(注释掉);
  2. 在控制器上给@ApiSupport注解,按照order值进行自定义排序,你想让哪个在前,order值就小一些,我一般是从1开始;
  3. 在注解@Tag中的description要给描述,不能是空字符串,否则@ApiSupport不生效;
  4. 弃用tags-sorter的alpha排序更改使用@ApiSupport排序后,需重启程序,此时浏览器最好清除缓存后重新访问Knife4j。
2.关于接口分组无法使用中文问题解决
a) 问题回溯

Knife4jConfig配置类中使用group进行中文分组时,会造成doc.html访问异常,推测是底层编码问题所致。

b) 解决方法
  1. Knife4jConfig配置类中,配置GroupedOpenApi时,group使用英文,displayName使用中文(doc.html最终显示displayName名称);
  2. Knife4jConfig配置类中使用displayName名称时,在yml中配置补充文档时,设置knife4j.documents.name时使用displayName名称,而不是group名称,切记!
3.关于响应内容中不出现注释内容说明

当响应内容中不出现注释时,点击右上角显示说明,触发一次关闭或勾选,即可出现注释内容。(群友推测可能是当响应结果过多时显示BUG问题,必须关闭勾选触发一次显示说明的事件)

4.关于Controller层中GET请求且接收参数为对象时的配置注意事项

参考以下两篇文章

  • Knife4j v4.0版本针对参数解析ParameterObject的问题说明
  • SpringBoot接收参数场景

集成Knife4j后,针对GET请求且接收参数为对象时,需要在yml中配置springdoc.default-flat-param-object=true;且在接受参数时使用注解@ModelAttribute

5.关于过滤参数注解@ApiOperationSupport使用

从Knife4j4.0.0开始,@ApiOperationSupport注解中的ignoreParametersincludeParameters属性不再提供支持。如果需要进行精确显示提供的参数,官方建议是新建VO类。

Knife4j4.5.0注解关于注解@ApiOperationSupport属性说明

官方说明: 3.11 过滤请求参数 | Knife4j

八、待解决问题

1.设置includeParameters无效[影响指数:5/5]【见7.5章节】

POST请求中使用includeParameters给部分对象参数时无效,界面会显示全部对象字段。

includeParameters设置部分参数仍显示全部全部

2.设置多响应码时界面显示响应状态为tab[影响指数:4/5]

接口上设置多响应码时在前端响应状态中会显示多个tab,导致导出文档时,对同一个接口会出现多次响应状态描述

设置多响应码时出现响应码Tab

附录

附录A:状态码枚举定义类(StatusCode.java)
package cn.keyidea.common.constant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 状态码枚举定义 * * @author qyd * @date 2022-10-13 */ public enum StatusCode { SUCCESS(1000, "请求成功"), INVALID_PARAM(1001, "非法字段"), SYSTEM_BUSY(1002, "系统忙"), INVALID_MASTER_KEY(1003, "无接口访问权限"), FAILURE(1004, "请求失败"), UNAUTHORIZED(1005, "未授权"), INVALID_TOKEN(2001, "TOKEN失效"), CONNECT_TIMED_OUT(3001, "请求超时"), HTTP_REQ_ERROR(3002, "HTTP请求出错"); /** * 错误码 */ private final int code; /** * 错误描述信息 */ private final String msg; StatusCode(int code, String msg) { this.code = code; this.msg = msg; } public String getMsg() { return this.msg; } public String getCode() { return this.code + ""; } public int getCodeValue() { return this.code; } /** * 转为Map集合数据 * * @return 枚举对象Map集合 */ public static Map<Integer, String> toMap() { Map<Integer, String> map = new HashMap<>(32); for (StatusCode value : StatusCode.values()) { map.put(value.getCodeValue(), value.getMsg()); } return map; } /** * 转为List集合数据 * * @return 枚举对象List集合 */ public static List<Map<String, String>> toList() { List<Map<String, String>> list = new ArrayList<>(32); Map<String, String> map = null; for (StatusCode item : StatusCode.values()) { map = new HashMap<>(); map.put("code", item.getCode()); map.put("msg", item.getMsg()); list.add(map); } map = null; return list; } }
附录B:通用响应封装类(BaseRes.java)
package cn.keyidea.common.bean; import cn.keyidea.common.constant.StatusCode; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; /** * 通用响应封装,范式返回(Swagger要求) * * @author qyd */ @Data public class BaseRes<T> implements Serializable { /** * 错误码 */ @Schema(name = "code", description = "错误码,当code为1000时返回正常,其余返回异常", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") public Integer code; /** * 错误提示信息 */ @Schema(name = "msg", description = "错误提示信息,当code为非1000时返回提示信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "请求成功") public String msg; /** * 附加返回数据 */ @Schema(name = "data", description = "附加返回数据,当code为1000时返回数据") public T data; public static class DataList<T> { /** * 记录总数 */ @Schema(name = "total", description = "记录总数") public Integer total; /** * 数据列表 */ @Schema(name = "list", description = "数据列表") public T list; public DataList(Integer total, T list) { this.total = total; this.list = list; } } /** * 给ObjectMapper用的,代码中不要调用 */ public BaseRes() { } /** * 自定义返回码和提示消息 * * @param code 错误码 * @param msg 提示文字 */ public BaseRes(int code, String msg) { this.code = code; this.msg = msg; } public BaseRes(int code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } /** * 返回成功,但是没有附加数据 * * @return BaseRes对象 */ public static BaseRes success() { return new BaseRes(StatusCode.SUCCESS.getCodeValue(), "请求成功"); } /** * 返回成功,带附加数据 * * @param data 附加数据 * @return BaseRes对象 */ public static BaseRes successData(Object data) { BaseRes value = new BaseRes(StatusCode.SUCCESS.getCodeValue(), "请求成功"); value.data = data; return value; } /** * 返回参数无效响应 * * @return BaseRes对象 */ public static BaseRes invalidParam() { return new BaseRes(StatusCode.INVALID_PARAM.getCodeValue(), "参数无效"); } /** * 返回参数无效响应,自定义错误提示 * * @param msg 提示文字 * @return BaseRes对象 */ public static BaseRes invalidParam(String msg) { return new BaseRes(StatusCode.INVALID_PARAM.getCodeValue(), msg); } /** * 返回系统忙无效响应 * * @return BaseRes对象 */ public static BaseRes systemBusy() { return new BaseRes(StatusCode.SYSTEM_BUSY.getCodeValue(), "系统忙"); } /** * 返回master key无效响应 * * @return BaseRes对象 */ public static BaseRes invalidMasterkey() { return new BaseRes(StatusCode.INVALID_MASTER_KEY.getCodeValue(), "没有接口访问权限"); } /** * 返回失败,附带说明 * * @return BaseRes对象 */ public static BaseRes fail(String msg) { return new BaseRes(StatusCode.FAILURE.getCodeValue(), msg); } /** * 返回错误信息时,仍然返回数据 * * @param data 数据集 * @param msg 错误信息 * @return BaseRes对象 */ public static BaseRes failData(Object data, String msg) { return new BaseRes(StatusCode.FAILURE.getCodeValue(), msg, data); } /** * 登录失效的错误 * * @return BaseRes对象 */ public static BaseRes invalidToken() { return new BaseRes(StatusCode.INVALID_TOKEN.getCodeValue(), "请先登录"); } /** * 检查响应处理是否成功 * * @return 成功返回true,否则false */ @JsonIgnore public boolean isSuccess() { return (this.code.equals(StatusCode.SUCCESS.getCodeValue())); } /** * 返回分页列表数据 * * @param total 记录总数 * @param list 列表数据 * @return rsp */ public static BaseRes list(long total, Object list) { DataList data = new DataList((int) total, list); return BaseRes.successData(data); } }

参考

以下参考截止[2024-06-20],CSDN等网站链接均能查看全部文章。

官方
  • 3.1 增强模式 | Knife4j
接口排序问题
  • knife4j 4.3.0版本,@ApiSupport、@ApiSort排序不会自动生成x-order扩展属性 · Issue #I7U2I0 · 萧明/knife4j - Gitee.com【解决了类Controller排序问题】

  • knife4j 中接口分组排序的方法_knife4j 接口排序-CSDN博客

SpringBoot2.x升级至3.x相关
  • SpringBoot2.7升级项目到Springboot3.1踩坑指南(jdk17/jdk21)_升级到 jdk17 springboot3.1
  • Spring Boot 3 之SpringBoot 版本升级最佳实践指南
  • 记录从SpringBoot2.x升级到SpringBoot3.x的心得
  • SpringBoot2.7升级到3.0的实践分享 - 踩刀诗人
  • 记录SpringBoot2.7.5升级SpringBoot3.0.0问题_springboot2.7升级3.0
  • Springboot3.0升级填坑-腾讯云开发者社区-腾讯云
  • JeecgBoot 框架升级至 Spring Boot3 的实战步骤-腾讯云开发者社区-腾讯云
  • How to prevent logback from outputting its own status at the start of every log when using a layout - Stack Overflow
  • Spring Boot3.0升级,踩坑之旅,附解决方案(二) - 掘金
MyBatis Plus升级相关
  • springboot3.2 整合 mybatis-plus_java.lang.illegalargumentexception: invalid value【解决引入最新MP依赖报错问题】
Knife4j升级相关
  • 关于SpringBoot2.7.18升级到3.2.x后的Knife4j使用的系列问题汇总(已全部解决) · Issue #775 · xiaoymin/knife4j
  • SpringBoot3整合Knife4j4.x版本(Swagger3、OpenApi3)_knife4j openapi3【有解决单文件多文件示例等】
  • SpringBoot 整合 knfe4j ,使用 OpenAPI3 规范_knife4j-openapi3
  • springboot3.2集成knife4j_springboot3.2 knife4j
  • SpringBoot3整合Knife4j_springboot3 knife4j
  • SpringBoot3中Swagger整合knife4j和springdoc的配置说明
  • SpringBoot3.x版本将swagger2.0升级到swagger3.0,使用knife4j-openapi3-jakarta-spring-boot-starter依赖
  • SpringBoot 使用 OpenAPI3 规范整合 knife4j的详细过程
  • Swagger系列:SpringBoot3.x中使用Knife4j - Code技术分享
  • SpringBoot3登录拦截器导致不能正常访问knife4j_knife4j放行后被拦截
  • Knife4j文档请求异常(基于SpringBoot3,查找原因并解决)
  • SpringBoot整合knife4j_knife4j集成springboot
  • SpringBoot 3.0整合OpenAPI使用教程_knife4j-openapi3-jakarta-spring-boot-starter
  • knife4j文档请求异常 · Issue #749 · xiaoymin/knife4j【Knife4j纯yml配置参考】
涉及Redis相关
  • Springboot从2.x升级到3.x以后redis默认配置调整-阿里云开发者社区
  • SpringBoot 2.x / 3.x 整合 Redis ( RedisTemplate 操作五大常用数据类型)
其他【启动告警解决】
  • Spring源码系列:BeanDefinition源码解析 - 掘金
  • 解决is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) - 神一样的存在 - 博客园
  • 解决:is not eligible for getting processed by all BeanPostProcessors-CSDN博客

最后编辑于:2024-12-09 22:14:37

著作权归作者所有,转载或内容合作请联系作者

喜欢的朋友记得点赞、收藏、关注哦!!!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询