当前位置: 首页 > news >正文

SpringBoot3.3.0集成Knife4j4.5.0实战

原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# 启用swaggerUIswagger-ui:#自定义swagger前端请求路径,输入http:127.0.0.1:8080/swagger-ui.html会自动重定向到swagger页面path: /swagger-ui.htmlenabled: 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 英文:ENenable-swagger-models: trueenable-dynamic-parameter: falsefooter-custom-content: "<strong>Copyright ©️ 2024 Keyidea. All Rights Reversed</strong>"enable-footer-custom: trueenable-footer: trueenable-document-manage: truedocuments: #文档补充说明- 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集同接口@Beanpublic GroupedOpenApi api4() {return GroupedOpenApi.builder().group("04-2024-api").displayName("04-2024集同接口").packagesToScan("cn.keyidea.second")// 自定义全局响应码.addOpenApiCustomizer((this::setCustomStatusCode)).build();}// 2023集同接口@Beanpublic GroupedOpenApi api3() {return GroupedOpenApi.builder().group("03-2023-api").displayName("03-2023集同接口").packagesToScan("cn.keyidea.control")// 自定义全局响应码.addOpenApiCustomizer((this::setCustomStatusCode)).build();}// 业务接口@Beanpublic 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();}// 系统接口@Beanpublic GroupedOpenApi api1() {// 创建了一个api接口的分组return GroupedOpenApi.builder()// 分组名称,使用英文,中文访问异常(使用displayName设置中文名,避免直接使用group设置中文时访问异常).group("01-sys-api").displayName("01-系统接口") // 使用displayName设置中文接口分组名时,group仍不可或缺.packagesToScan("cn.keyidea.sys")// 自定义全局响应码.addOpenApiCustomizer((this::setCustomStatusCode)).build();}@Beanpublic 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) {// 设置默认ContentContent 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中获取原生Contentfor (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(descriptionrequired = 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);@Autowiredprivate 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);@Autowiredprivate 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*/@JsonIgnorepublic 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


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

相关文章:

SpringBoot3.3.0集成Knife4j4.5.0实战

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

C# 的反射窗体的使用

C# 的反射窗体的使用 using System; using System.Reflection; using System.Windows.Forms;public class ReflectedFormFactory {public static Form CreateForm(string formName, string assemblyName){// 加载程序集Assembly assembly Assembly.Load(assemblyName);// 获取…...

大模型呼出机器人能够解决哪些问题?

大模型呼出机器人能够解决哪些问题&#xff1f; 原作者&#xff1a;开源呼叫中心FreeIPCC&#xff0c;其Github&#xff1a;https://github.com/lihaiya/freeipcc 大模型呼出机器人作为现代科技在客户服务领域的创新应用&#xff0c;能够解决多个方面的问题&#xff0c;以下是…...

密码学——密码学概述、分类、加密技术(山东省大数据职称考试)

大数据分析应用-初级 第一部分 基础知识 一、大数据法律法规、政策文件、相关标准 二、计算机基础知识 三、信息化基础知识 四、密码学 五、大数据安全 六、数据库系统 七、数据仓库. 第二部分 专业知识 一、大数据技术与应用 二、大数据分析模型 三、数据科学 密码学 大数据…...

Linux 入门教程:从命令行开始

Linux 是一个强大且灵活的操作系统&#xff0c;广泛应用于服务器、嵌入式设备、开发环境等领域。如果你是刚接触 Linux 的新手&#xff0c;最重要的一步就是掌握命令行操作。虽然 Linux 提供了图形界面&#xff0c;但很多强大功能只能通过命令行来实现。今天&#xff0c;我们就…...

Python中的异步编程:从基础到实践

在现代编程中,异步编程已经成为提高程序性能和响应能力的重要手段。Python,作为一种动态、解释型的高级编程语言,提供了多种异步编程的解决方案。本文将从Python异步编程的基础知识出发,逐步深入到实际应用中,帮助读者理解和掌握这一技术。 1. 异步编程简介 异步编程是一…...

如何使用 Python 实现简单的 Web 服务器?

为了实现一个简单的Web服务器&#xff0c;Python提供了多种方法。对于快速原型设计和学习目的来说&#xff0c;最简单的方法之一是使用内置的http.server模块。 然而&#xff0c;在实际开发中&#xff0c;更常见的做法是使用像Flask或Django这样的框架来构建更为复杂的应用程序…...

【unity小技巧】unity最完美的CharacterController 3d角色控制器,实现移动、跳跃、下蹲、奔跑、上下坡、物理碰撞效果,复制粘贴即用(2024/12/12补充)

最终效果 文章目录 最终效果更好的方式&#xff08;2024/12/12补充&#xff09;前言为什么使用CharacterControllerSimpleMove和Move如何选择&#xff1f;1. SimpleMove2. Move 配置CharacterController参数控制相机移动跳跃方式一方式二 下蹲处理下坡抖动问题实现奔跑和不同移…...

6_Sass 选择器函数 --[CSS预处理]

Sass 提供了一系列的选择器函数&#xff0c;用于操作和组合CSS选择器。这些函数可以帮助你更灵活地创建样式规则&#xff0c;并且可以减少重复代码。以下是几个常用的选择器函数及其用法&#xff1a; 1. selector-append($selector1, $selector2...) selector-append($select…...

系列2:基于Centos-8.6Kubernetes 集成GPU资源信息

每日禅语 自省&#xff0c;就是自我反省、自我检查&#xff0c;自知己短&#xff0c;从而弥补短处、纠正过失。佛陀强调自觉觉他&#xff0c;强调以达到觉行圆满为修行的最高境界。要改正错误&#xff0c;除了虚心接受他人意见之外&#xff0c;还要不忘时时观照己身。自省自悟之…...

C# 探险之旅:第三十五节 - 类型class之抽象类 (Abstract Class) 和 抽象方法 (Abstract Method)

&#x1f44b; 嗨&#xff0c;勇敢的探险家们&#xff01;欢迎再次踏上C#的神秘之旅。今天&#xff0c;我们要进入一片既神秘又充满无限可能的领域——抽象类与抽象函数的奇幻森林。想象一下&#xff0c;你是一名勇敢的骑士&#xff0c;要在这片森林里寻找传说中的“编程之宝”…...

npm内存溢出

项目过大运行项目内存溢出 报错代码 运行内存溢出 increase-memory-limit ‘“node --max-old-space-size8192”’ 不是内部或外部命令&#xff0c;也不是可运行的程序 FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of m…...

CSS|08 浮动清除浮动

浮动 需求: 能够实现让多个元素排在同一行&#xff0c;并且给这些元素设置宽度与高度! 让多个元素排在同一行:行内元素的特性 给这些元素设置宽高:块级元素的特性 在标准文档流中的元素只有两种:块级元素和行内元素。如果想让一些元素既要有块级元素的特点也要有行内元素的特…...

【学习笔记】反向传播到底是如何进行的?

文章目录 一、写在前面二、举个例子三、混合损失函数如何进行呢&#xff1f; 一、写在前面 不知道小伙伴们有没有考虑过这种感觉&#xff0c;在最开始学习深度学习的时候&#xff0c;一定都了解过前向传播&#xff0c;反向传播等等&#xff0c;但是在实际的操作过程中却“几乎…...

利用cnocr库完成中文扫描pdf文件的文字识别

很多pdf文件文字识别软件都会收费&#xff0c;免费的网页版可能会带来信息泄露&#xff0c;还有一些类似于腾讯AI和百度AI的接口都有调用次数限制&#xff0c;因此&#xff0c;利用识别正确率极高且免费的cnocr库来自己动手做个pdf文件文字识别程序就是一个很不错的选择。以下程…...

el-table ToggleRowSelection实现取消选中没效果(virtual-scroll)

场景&#xff1a; 就是在虚拟列表el-table选中之后 点击查询 默认之前选中的 现象&#xff1a; 就是实现选中&#xff0c; 但是无法去除勾选等等 问题发现&#xff1a; 看定位的数据 有多个一样的&#xff0c;我想着勾选之前 先去掉勾选 &#xff0c;但是没效果或者说“相同的…...

Vue入门到精通:运行环境

Vue入门到精通&#xff1a;运行环境 Vue3的运行环境搭建主要有两种方法&#xff1a;一种是直接在页面中引入Vue库&#xff0c;另一种是通过脚手架工具创建Vue项目。 &#xff08;一&#xff09;页面直接引入Vue库 页面直接引入Vue库的方法&#xff0c;是指在HTML网页中通过s…...

LNK2001: virtual struct QMetaObject const 错误的解决方法和原因

目录 1.现象 2.原因分析 3.解决方法 3.1.方法1 3.2.方法2 1.现象 今天调整了下工程目录结构(环境是VS2019Qt5.12.12)&#xff0c;重新编译突然出现以下错误&#xff1a; 没有修改代码&#xff0c;怎么就出现这个错误了呢&#xff1f;从上面的错误来看&#xff0c;其实就是…...

电脑win11家庭版升级专业版和企业版相关事项

我的是零刻ser9&#xff0c;自带win11家庭版&#xff0c;但是我有远程操控需求&#xff0c;想用windows系统自带的远程连接功能&#xff0c;所以需要升级为专业版。然后在系统激活页面通过更改序列号方式&#xff0c;淘宝几块钱买了个序列号升级成功专业版了。但是&#xff0c;…...

用户认证系统登录界面

下面是使用HTML和JavaScript实现的一个中文版登录界面&#xff0c;包含登录、注册和修改密码功能。注册成功后会显示提示信息&#xff0c;在登录成功后进入一个大大的欢迎页面。 1.代码展示 <!DOCTYPE html> <html lang"zh-CN"> <head><meta …...

深圳国威HB1910数字IP程控交换机 generate.php 远程命令执行漏洞复现

0x01 产品描述: 深圳国威主营国威模拟、数字、IP 交换机、语音网关、IP 电话机及各种电话机。深圳国威电子有限公司HB1910是一款功能强大的网络通信设备,适用于各种企业通信需求。 0x02 漏洞描述: 深圳国威电子有限公司HB1910数字IP程控交换机generate.php存在远程命令执行…...

客户端(浏览器)vue3本地预览txt,doc,docx,pptx,pdf,xlsx,csv,

预览文件 1、入口文件preview/index.vue2、预览txt3、预览doc4、预览pdf5、预览pptx6、预览xlsx7、预览csv 1、入口文件preview/index.vue 预览样式&#xff0c;如pdf 文件目录如图所示&#xff1a; 代码如下 <template><div class"preview-wrap" ref&…...

(八)机器学习 - 线性回归

线性回归&#xff08;Linear Regression&#xff09;是一种统计学方法&#xff0c;用于建立一个或多个自变量&#xff08;解释变量&#xff09;与因变量&#xff08;响应变量&#xff09;之间的线性关系。线性回归的目的是通过最小化预测误差来找到最佳的线性拟合模型&#xff…...

Springboot 整合 Java DL4J 打造金融风险评估系统

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s…...

CSDN博客:如何使用Python的`datasets`库转换音频采样率

CSDN博客&#xff1a;如何使用Python的datasets库转换音频采样率 什么是采样率&#xff1f;代码用途&#xff1a;调整音频数据的采样率完整代码示例代码详解运行结果&#xff08;示例&#xff09;总结 在这篇文章中&#xff0c;我们将学习如何使用Python的datasets库对音频数据…...

geoserver(1) 发布sql 图层 支持自定义参数

前提使用postgis 数据库支持关联 join 支持 in,not in,like,及其他sql原生函数 新增sql图层 编写自定义sql 编辑sql语句必须输出带有geom数据 正则表达式去除 设置id以及坐标参考系 预览sql图层效果 拼接sql参数 http://xxx.com/geoserver/weather/wms?SERVICEWMS&VERSI…...

从 Router 到 Navigation:HarmonyOS 路由框架的全面升级与迁移指南

在本教程中&#xff0c;我们深入探讨了 Router 和 Navigation 在 HarmonyOS 中的用法差异及如何从 Router 切换到 Navigation 的方法。重点涵盖了页面跳转、转场动画、生命周期管理以及跨包路由的实现。 页面结构对比 Router 页面结构 每个页面需要使用 Entry 注解。 页面需要…...

http1.1 vs http2.0 速度对比实测

首先对比一下http1.1 vs http2.0 区别&#xff1a; 1. 连接管理&#xff1a; HTTP/1.1: 每个请求/响应都需要一个独立的 TCP 连接&#xff0c;虽然可以使用持久连接&#xff08;keep-alive&#xff09;来复用连接&#xff0c;但仍然存在请求队头阻塞&#xff08;Head-of-Line…...

uniappp配置导航栏自定义按钮(解决首次加载图标失败问题)

1.引入iconfont的图标&#xff0c;只保留这两个文件 2.App.vue引入到全局中 import "./static/fonts/iconfont.css"3.pages.json中配置text为图标对应的unicode {"path": "pages/invite/invite","style": {"h5": {"…...

vue运行项目时local有显示 但是network却显示unavailable

问题描述 日常开发中 和后端本地调试时 后端需要使用你的本地去访问页面 可运行项目时会出现network显示unavailable的情况 解决方式 1.其实这只是vue脚手架对于ip地址获取的方式兼容上有一些问题 但其实是不影响ip访问本地的 你可以直接cmd内ipconfig去查看自己的ip然后…...

【Java学习笔记】JUnit

一、为什么需要 JUnit 二、基本介绍 三、实现方法 第一次添加&#xff1a; 在需要测试的方法处输入 Test注解&#xff0c;快捷键AltInsert选择添加版本&#xff08;常用JUnit5.4&#xff09; 出现绿色箭头可进行测试和编译...

Next.js配置教程:构建自定义服务器

更多有关Next.js教程&#xff0c;请查阅&#xff1a; 【目录】Next.js 独立开发系列教程-CSDN博客 目录 前言 1. 什么是自定义服务器&#xff1f; 2. 配置自定义服务器 2.1 基础配置 2.2 集成不同的服务器框架 使用Fastify 使用Koa 3. 自定义服务器的高级功能 3.1 路…...

el-table 动态计算合并行

原始表格及代码 <el-table:data"tableData"class"myTable"header-row-class-name"tableHead" ><el-table-column prop"date" label"日期"> </el-table-column><el-table-column prop"name" …...

【杭州电商商城系统开发建设】

杭州电商商城系统开发建设是一项综合性的工程&#xff0c;它涉及到多个方面的内容。以下是对杭州电商商城系统开发建设的详细分析&#xff1a; 需求分析&#xff1a;深入了解用户需求&#xff0c;包括用户群体特征、购物习惯、支付偏好等&#xff0c;为系统设计提供基础。明确…...

架构实践05-互联网架构模板

零、文章目录 架构实践05-互联网架构模板 1、技术演进的方向 &#xff08;1&#xff09;技术演进的方向判断 潮流派&#xff1a;热衷于新技术&#xff0c;紧跟技术潮流&#xff0c;但可能面临技术不成熟的风险和学习成本。保守派&#xff1a;强调稳定&#xff0c;对新技术持…...

家校通小程序实战教程10部门管理前后端连接

目录 1 加载后端的数据2 为什么不直接给变量赋值3 保存部门信息4 最终的效果5 总结 现在部门管理已经完成了后端功能和前端开发&#xff0c;就需要在前端调用后端的数据完成界面的展示&#xff0c;而且在录入部门信息后需要提交到数据库里&#xff0c;本篇我们介绍一下前后端如…...

【前端面试题】书、定位问题、困难

看过什么书 《JavaScript 高级程序设计&#xff08;第 4 版&#xff09;》&#xff08;作者&#xff1a;Matt Frisbie&#xff09; 这是一本深入学习 JavaScript 语言的经典书籍。它详细地涵盖了 JavaScript 的高级特性&#xff0c;包括原型链、闭包、异步编程等复杂概念。以闭…...

VSCode设置字体

参考文章&#xff1a;【面向小白】vscode最佳实践&#xff08;2&#xff09;—— 字体设置&#xff08;fira code更纱黑体&#xff09;&#xff0c;这篇文章末尾给了安装字体的链接。 配置的字体还是很好看的。 ‘Fira Code Retina’, ‘Sarasa Mono Sc’ 需要注意的一个点&am…...

《机器学习》2.4假设检验 t分布 F分布

目录 t发布 注意是这个东西服从t分布 数据服从t分布通常是在以下情况下&#xff1a; 以下是一些具体的例子&#xff0c;说明在何种情况下数据会服从t分布&#xff1a; t检验 交叉验证t检验 样本方差​编辑 F分布&#xff08;fisher Friedman检验是一种非参数统计方法&a…...

Mysql之视图

MySQL 视图&#xff08;View&#xff09; 1. 概念 视图是一个虚拟的表&#xff0c;它是基于 SELECT 查询的结果集。视图不存储实际数据&#xff0c;而是动态地从基表中提取数据。视图可以简化复杂查询、提高数据安全性&#xff08;限制访问特定列或行&#xff09;以及提供数据…...

kafka学习笔记

kafka消息中间件精讲 - B站动力节点 JDK17在Windows安装及环境变量配置超详细的教程 Windows 多版本java 装多个版本jdk Windows同时安装多个JDK jdk17下载与安装教程&#xff08;win10&#xff09;&#xff0c;超详细 jdk17-archive-downloads 如何在IDEA中配置指定JDK版…...

【保姆级教程】基于OpenCV+Python的人脸识别上课签到系统

【保姆级教程】基于OpenCVPython的人脸识别上课签到系统 一、软件安装及环境配置1. 安装IDE&#xff1a;PyCharm2. 搭建Python的环境3. 新建项目、安装插件、库 二、源文件编写1. 采集人脸.py2. 训练模型.py3. 生成表格.py4. 识别签到.py5. 创建图形界面.py 三、相关函数分析1.…...

LVS能否实现两台服务器的负载均衡

LVS能否实现两台服务器的负载均衡 是的&#xff0c;LVS&#xff08;Linux Virtual Server&#xff09;可以实现两台服务器的负载均衡&#xff0c;并且它非常适合这种场景。 LVS&#xff08;Linux Virtual Server&#xff09;简介&#xff1a; LVS 是一种基于 Linux 的负载均…...

智能人体安全防护:3D 视觉技术原理、系统架构与代码实现剖析

随着工业化程度的提高&#xff0c;生产安全已成为企业关注的重点。尤其是在一些存在禁区的工业厂区和车间&#xff0c;人员误入或违规进入将带来严重的安全隐患。为了解决这一问题&#xff0c;迈尔微视推出了智能人体安全检测解决方案&#xff0c;为企业提供全方位的人员安全监…...

JAVA后端实现全国区县下拉选择--树形结构

设计图如图&#xff1a; 直接上代码 数据库中的格式&#xff1a; JAVA实体类&#xff1a; Data public class SysAreaZoningDO {private Long districtId;private Long parentId;private String districtName;private List<SysAreaZoningDO> children; } MapperSQL语句…...

DVWA及其他常见网络靶场

常见网络靶场 Metasploitable2 介绍&#xff1a; Metasploitable2 是一个用于安全培训和测试渗透测试工具的虚拟靶机。它故意配置了许多已知的安全漏洞&#xff0c;涵盖了操作系统、网络服务等多个方面。基于 Ubuntu Linux 操作系统构建&#xff0c;包含了如 Apache、MySQL、FT…...

API接口安全:电商数据保护的坚固防线

随着电子商务的蓬勃发展&#xff0c;电商平台的数据安全和隐私保护成为了至关重要的议题。API&#xff08;应用程序编程接口&#xff09;作为电商平台与外部系统交互的桥梁&#xff0c;其安全性直接关系到整个平台的数据保护能力。本文将从API接口安全的重要性、面临的安全威胁…...

springboot437校园悬赏任务平台(论文+源码)_kaic

摘 要 使用旧方法对校园悬赏任务平台的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在校园悬赏任务平台的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。这次开发的校…...

可视化报表如何制作?一文详解如何用报表工具开发可视化报表

在如今这个数据驱动的商业时代&#xff0c;众多企业正如火如荼地推进数字化转型&#xff0c;力求在激烈的市场竞争中占据先机。然而&#xff0c;随着业务规模的扩大和运营复杂度的提升&#xff0c;企业的数据量爆炸式增长&#xff0c;传统报表格式单一、信息呈现密集且不易解读…...

STM32 HAL库之SDIO例程 Micro SD卡 - 2

1、硬件图 2、示例代码 根据提示配置SDCLK为72/3 24MHz。 static void MX_SDIO_SD_Init(void) {/* USER CODE BEGIN SDIO_Init 0 */SD_InitTypeDef Init;Init.ClockEdge SDIO_CLOCK_EDGE_RISING;Init.ClockBypass SDIO_CLOCK_BYPASS_DISABLE;Init.ClockPo…...