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

使用thymeleaf模版导出swagger3的word格式接口文档

1.pom配置

 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.8.RELEASE</version></parent><properties><skipTests>true</skipTests><java.version>1.8</java.version><springfox-version>2.6.1</springfox-version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- thymeleaf --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.23</version></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>${springfox-version}</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>${springfox-version}</version></dependency><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId></dependency></dependencies><build><finalName>SwaggerToWord</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.3</version><configuration><source>1.8</source><target>1.8</target><encoding>utf-8</encoding></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>2.6</version><configuration><delimiters><delimiter>${*}</delimiter><delimiter>@</delimiter></delimiters><useDefaultDelimiters>false</useDefaultDelimiters></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.0.1.RELEASE</version><executions><execution><phase>package</phase><!--可以把依赖的包都打包到生成的Jar包中--><goals><goal>repackage</goal></goals><!--可以生成不含依赖包的不可执行Jar包--><configuration><classifier>exec</classifier></configuration></execution></executions></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>

2.application.yml的配置

server:port: 8080tomcat:max-threads: 800uri-encoding: UTF-8spring:application:name: swaggerTowordthymeleaf:prefix: classpath:/templates/suffix: .htmlcache: falseservlet:content-type: text/htmlenabled: trueencoding: UTF-8mode: HTML5

3.实体对象

@Data
public class RequestDto {//参数名称private String name;//参数类型private String type;//参数中文说明private String description;//是否必填private Boolean required;List<RequestDto> modelAttr;
}@Data
public class ResponseDto {// 名称private String name;// 类型private String type;// 子集private List<ResponseDto> properties;//参数中文说明private String description;
}@Data
public class SwaggerUiDto implements Serializable {// 标题private String title;// 版本private String version;private String description;//每个大类下的接口列表private Map<String,List<TableDto>> tableMap;}@Data
public class TableDto {// 请求地址private String url;// 请求方式private String method;// 请求参数举例private String requestParam;// 描述private String description;// 请求参数private List<RequestDto> request;// 响应参数private List<ResponseDto> response;// 响应参数举例private String responseParam;
}

4.controller代码。

@Controller
@Api(tags = "swaggertoWordAPI")
public class Swagger3Controller {@Autowiredprivate ISwagger3Service service;@Autowiredprivate SpringTemplateEngine springTemplateEngine;private String fileName = "toWord";@ApiOperation(value = "将 swaggerv3 文档一键下载为 doc 文档", notes = "", tags = {"Word"})@ApiResponses(value = {@ApiResponse(code = 200, message = "请求成功。")})@RequestMapping(value = "/downloadWord3", method = {RequestMethod.GET})public void wordv3(Model model, @ApiParam(value = "资源地址") @RequestParam(required = true) String url, HttpServletResponse response) {generateModelData3(model, url, 0);writeContentToResponse3(model, response);}private void generateModelData3(Model model, String url, Integer download) {SwaggerUiDto dto = service.getSwaggerUiDto(url);model.addAttribute("url", url);model.addAttribute("download", download);model.addAttribute("param",dto);}private void writeContentToResponse3(Model model, HttpServletResponse response) {Context context = new Context();context.setVariables(model.asMap());String content = springTemplateEngine.process("word2", context);response.setContentType("application/octet-stream;charset=utf-8");response.setCharacterEncoding("utf-8");try (BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream())) {response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".doc", "utf-8"));byte[] bytes = content.getBytes();bos.write(bytes, 0, bytes.length);bos.flush();} catch (IOException e) {e.printStackTrace();}}}

5. 业务实现接口和类

public interface ISwagger3Service {/*** 把swagger3 json解析成swaggerUiDto* @param swaggerUrl* @return*/SwaggerUiDto getSwaggerUiDto(String swaggerUrl);
}import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.word.dto.RequestDto;
import org.word.dto.ResponseDto;
import org.word.dto.SwaggerUiDto;
import org.word.dto.TableDto;
import org.word.service.ISwagger3Service;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;/*** 把json数据解析成对象** @author lyl* @version v1.0* @since 2025/5/8*/
@Service
@Slf4j
public class Swagger3ServiceImpl implements ISwagger3Service {@Autowiredprivate RestTemplate restTemplate;@Overridepublic SwaggerUiDto getSwaggerUiDto(String swaggerUrl) {String jsonStr = restTemplate.getForObject(swaggerUrl, String.class);JSONObject jsonObject = JSON.parseObject(jsonStr);return getSwaggerUiDto(jsonObject);}/*** 开始解析json数据** @param jsonObject json数据* @return 返回SwaggerUiDto对象*/private SwaggerUiDto getSwaggerUiDto(JSONObject jsonObject) {SwaggerUiDto swaggerUiDto = new SwaggerUiDto();JSONObject info = jsonObject.getJSONObject("info");swaggerUiDto.setVersion(info.getString("version"));swaggerUiDto.setTitle(info.getString("title"));swaggerUiDto.setDescription(info.getString("description"));swaggerUiDto.setTableMap(getTableMap(jsonObject));return swaggerUiDto;}/*** 组装接口内容对象** @param jsonObject json数据* @return 返回接口内容列表*/private Map<String, List<TableDto>> getTableMap(JSONObject jsonObject) {Map<String, List<TableDto>> tableMap = new HashMap<>();//获取大类标题JSONArray tags = jsonObject.getJSONArray("tags");for (int i = 0; i < tags.size(); i++) {JSONObject tagObject = tags.getJSONObject(i);String tagName = tagObject.getString("name");String tagDescription = tagObject.getString("description");//获取接口内容JSONObject paths = jsonObject.getJSONObject("paths");List<TableDto> tableDtoList = new ArrayList<>();for (String key : paths.keySet()) {JSONObject pathObject = paths.getJSONObject(key);for (String methodKey : pathObject.keySet()) {JSONObject methodObject = pathObject.getJSONObject(methodKey);//获取请求方法JSONArray tagNames = methodObject.getJSONArray("tags");for (int j = 0; j < tagNames.size(); j++) {if (tagNames.getString(j).equals(tagName)) {//组装接口内容TableDto dto = new TableDto();dto.setUrl(key);dto.setMethod(methodKey.toUpperCase());dto.setDescription(methodObject.getString("summary"));if (methodKey.equals("post")) {//获取请求参数JSONObject requestBody = methodObject.getJSONObject("requestBody");//JSONObject content= requestBody.getJSONObject("content");dto.setRequest(getPostRequest(requestBody, jsonObject));dto.setRequestParam(JSON.toJSONString(dto.getRequest()));} else if (methodKey.equals("get")) {JSONArray parameters = methodObject.getJSONArray("parameters");if (null != parameters) {dto.setRequest(getGetRequest(parameters));}if (null != dto.getRequest()) {//用&拼装参数String param = dto.getRequest().stream().map(requestDto -> requestDto.getName() + "=").collect(Collectors.joining("&"));dto.setRequestParam(param);}}JSONObject responses = methodObject.getJSONObject("responses");dto.setResponse(getResponse(responses, jsonObject));dto.setResponseParam(JSON.toJSONString(dto.getResponse()));tableDtoList.add(dto);break;}}}tableMap.put(tagName, tableDtoList);}}return tableMap;}/*** 返回参数组装** @param responses* @param jsonObject "ResponseResult«ServiceItem»": {*                   "title": "ResponseResult«ServiceItem»",*                   "type": "object",*                   "properties": {*                   "code": {*                   "type": "string",*                   "description": "状态码",*                   "enum": [*                   "AUTHENTICATION_REQUIRED",*                   "BAD_REQUEST",*                   "DATA_ERROR",*                   "INTERNAL_SERVER_ERROR",*                   "LICENSE_CHECK_ERROR",*                   "MODIFY_PASSWORD_ERROR",*                   "PARAMETER_ERROR",*                   "SUCCESS",*                   "UNAUTHORIZED"*                   ]*                   },*                   "data": {*                   "description": "数据",*                   "$ref": "#/components/schemas/ServiceItem"*                   },*                   "message": {*                   "type": "string",*                   "description": "消息"*                   }*                   }*                   },* @return*/private List<ResponseDto> getResponse(JSONObject responses, JSONObject jsonObject) {List<ResponseDto> responseDtoList = new ArrayList<>();for (String key : responses.keySet()) {ResponseDto responseDto = new ResponseDto();responseDto.setName(key);responseDto.setDescription(responses.getJSONObject(key).getString("description"));if (key.equals("200")) {JSONObject content = responses.getJSONObject(key).getJSONObject("content");if (null != content) {List<ResponseDto> properties = new ArrayList<>();content.keySet().forEach(k -> {JSONObject schema = content.getJSONObject(k).getJSONObject("schema");if (schema.containsKey("$ref")) {String ref = schema.getString("$ref");//解析参数路径String refPath = ref.substring(ref.lastIndexOf("/") + 1);properties.addAll(getResponse(refPath, jsonObject));}});responseDto.setProperties(properties);}}responseDtoList.add(responseDto);}return responseDtoList;}/*** 返回参数组装** @param refPath* @param jsonObject* @return*/private List<ResponseDto> getResponse(String refPath, JSONObject jsonObject) {List<ResponseDto> responseDtoList = new ArrayList<>();jsonObject.getJSONObject("components").getJSONObject("schemas").keySet().forEach(p -> {if (p.equals(refPath)) {JSONObject properties = jsonObject.getJSONObject("components").getJSONObject("schemas").getJSONObject(p).getJSONObject("properties");properties.keySet().forEach(p1 -> {ResponseDto responseDto = new ResponseDto();responseDto.setName(p1);responseDto.setDescription(properties.getJSONObject(p1).getString("description"));if (p1.equals("data")) {if (properties.getJSONObject(p1).keySet().contains("items")) {String ChildRef = properties.getJSONObject(p1).getJSONObject("items").getString("$ref");if (null != ChildRef) {String ChildRefPath = ChildRef.substring(ChildRef.lastIndexOf("/") + 1);responseDto.setProperties(getResponse(ChildRefPath, jsonObject));}responseDto.setType("object");} else if (properties.getJSONObject(p1).keySet().contains("properties")) {JSONObject propertyList = properties.getJSONObject(p1).getJSONObject("properties");List<ResponseDto> plist = new ArrayList<>();for (String key : propertyList.keySet()) {ResponseDto d = new ResponseDto();d.setName(key);d.setDescription(propertyList.getJSONObject(key).getString("description"));d.setType(propertyList.getJSONObject(key).getString("type"));if (propertyList.getJSONObject(key).keySet().contains("items")) {String ChildRef = propertyList.getJSONObject(key).getJSONObject("items").getString("$ref");if (null != ChildRef) {String ChildRefPath = ChildRef.substring(ChildRef.lastIndexOf("/") + 1);d.setProperties(getResponse(ChildRefPath, jsonObject));}d.setType("object");}plist.add(d);}responseDto.setProperties(plist);responseDto.setType("object");} else if (properties.getJSONObject(p1).keySet().contains("$ref")) {String ChildRef = properties.getJSONObject(p1).getString("$ref");if (null != ChildRef) {String ChildRefPath = ChildRef.substring(ChildRef.lastIndexOf("/") + 1);responseDto.setProperties(getResponse(ChildRefPath, jsonObject));}responseDto.setType("object");} else {responseDto.setType(properties.getJSONObject(p1).getString("type"));}}responseDtoList.add(responseDto);});}});return responseDtoList;}/*** get请求参数** @param parameters "parameters": [*                   {*                   "name": "service1Type",*                   "in": "query",*                   "description": "服务大类",*                   "required": true,*                   "style": "form",*                   "schema": {*                   "type": "integer",*                   "format": "int32"*                   }*                   }]* @return*/private List<RequestDto> getGetRequest(JSONArray parameters) {List<RequestDto> requestDtoList = new ArrayList<>();parameters.forEach(parameter -> {RequestDto requestDto = new RequestDto();JSONObject parameterObject = (JSONObject) parameter;requestDto.setName(parameterObject.getString("name"));requestDto.setType(parameterObject.getJSONObject("schema").getString("type"));requestDto.setDescription(parameterObject.getString("description"));if (parameterObject.get("required") != null) {requestDto.setRequired(parameterObject.getBoolean("required"));} else {requestDto.setRequired(false);}requestDtoList.add(requestDto);});return requestDtoList;}/*** post请求参数** @param requestBody 请求参数所在路径* @param jsonObject  数据* @return*/private List<RequestDto> getPostRequest(JSONObject requestBody, JSONObject jsonObject) {List<RequestDto> requestDtoList = new ArrayList<>();if (null == requestBody) {return null;}JSONObject content = requestBody.getJSONObject("content");content.keySet().forEach(key -> {JSONObject schema = content.getJSONObject(key).getJSONObject("schema");if (schema.containsKey("$ref")) {String ref = schema.getString("$ref");//解析参数路径String refPath = ref.substring(ref.lastIndexOf("/") + 1);jsonObject.getJSONObject("components").getJSONObject("schemas").keySet().forEach(p -> {if (p.equals(refPath)) {JSONObject properties = jsonObject.getJSONObject("components").getJSONObject("schemas").getJSONObject(p).getJSONObject("properties");properties.keySet().forEach(q -> {JSONObject property = properties.getJSONObject(q);RequestDto requestDto = new RequestDto();requestDto.setName(q);requestDto.setType(property.getString("type"));requestDto.setDescription(property.getString("description"));requestDto.setRequired(false);requestDtoList.add(requestDto);});}});}});return requestDtoList;}
}

6.html实现。

html文件路径:resources->templates->word2.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta http-equiv="Content-Type" content="application/msword; charset=utf-8"/><title>toWord</title><style type="text/css">.bg {font-size: 18px;font-weight: bold;color: #000;background-color: #D7D7D7;}table {border-width: 1px;border-style: solid;border-color: black;table-layout: fixed;border-collapse: collapse;}tr {height: 15px;font-size: 18px;}td {padding-left: 12px;border-width: 1px;border-style: solid;border-color: black;height: 15px;overflow: hidden;word-break: break-all;word-wrap: break-word;font-size: 18px;}.bg td {font-size: 18px;}tr td {font-size: 18px;}.specialHeight {height: 40px;}.first_title {height: 60px;line-height: 60px;margin: 0;font-weight: bold;font-size: 21px;}.second_title {height: 40px;line-height: 40px;margin: 0;font-size: 18.5px;}.doc_title {font-size: 42.5px;text-align: center;}.download_btn {float: right;}body {font-family: 仿宋;}</style>
</head><body>
<div style="width:400px; margin: 0 auto"><div><p class="doc_title" th:text="${param.title +'('+ param.version +')'}"></p><a class="download_btn" th:if="${download == 1}" th:href="${'/downloadWord?url='+ url}">下载文档</a><br></div><div th:each="tableMap:${param.tableMap}" style="margin-bottom:20px;"><!--这个是类的说明--><h2 class="first_title" th:text="${tableMap.key}"></h2><div th:each="table,tableStat:${tableMap.value}"><!--这个是每个请求的说明,方便生成文档后进行整理--><h3 class="second_title" th:text="${tableStat.count} + ')' + ${table.description}"></h3><!--            <div th:text="接口描述"></div>--><!--            <div th:text="${table.description}"></div>--><!--            <div th:text="URL"></div>--><!--            <div th:text="${table.url}"></div>--><table border="1" cellspacing="0" cellpadding="0" width="100%"><tr><td class="bg">名称</td><td colspan="5" th:text="${table.description}"></td></tr><tr><td class="bg">URL样式</td><td colspan="5" th:text="${table.url}">http://ip:端口</td></tr><tr><td class="bg">提交方式</td><td colspan="5" th:text="${table.method}"></td></tr><tr><td class="bg">接口协议</td><td colspan="5">HTTP+JSON</td></tr><tr><td class="bg">内容类型</td><td>名称</td><td>是否必填</td><td>类型</td><td>长度</td><td>说明</td></tr><th:block th:each="request, c:${table.request}"><tr ><td rowspan="${c.count}"></td><td th:text="${request.name}"></td><td th:if="${request.required}" th:text="是"></td><td th:if="${!request.required}" th:text="否"></td><td th:text="${request.type}"></td><td></td><td th:text="${request.description}"></td></tr><th:block th:if="${request.modelAttr}"><tbody th:include="this::request(${request.modelAttr},${c.count} + '.', 1)"/></th:block></th:block><tr><td class="bg">提交数据举例</td><td colspan="5" th:text="${table.requestParam}"></td></tr><tr><td class="bg">返回状态</td><td colspan="5">200,401,403,404</td></tr><tr><td class="bg">返回数据参数</td><td colspan="2">名称</td><td>类型</td><td>长度</td><td>说明</td></tr><tr><th:block th:if="${table.response}"><tbody th:include="this::response(${table.response},'', 1)"/></th:block></tr><tr><td class="bg" >返回数据举例</td><td colspan="5" th:text="${table.responseParam}"></td></tr></table></div></div>
</div><th:block th:fragment="request(properties,count, lv)"><th:block th:each="p,c : ${properties}"><tr><td rowspan="${c.count}"></td><td th:text="${p.name}"></td><td th:if="${p.required}" th:text="是"></td><td th:if="${!p.required}" th:text="否"></td><td th:text="${p.type}"></td><td></td><td th:text="${p.description}"></td></tr><th:block th:unless="${#lists.isEmpty(p.modelAttr)}"th:include="this::request(${p.modelAttr},${count} + '' + ${c.count} + '.',${lv+1})"/></th:block>
</th:block><th:block th:fragment="response(properties,count, lv)"><th:block th:each="p,c : ${properties}"><tr><td th:text="${count} + '' + ${c.count} "> </td><td th:text="${p.name}" colspan="2"></td><td th:text="${p.type}"></td><td ></td><td th:text="${p.description}"></td></tr><th:block th:unless="${#lists.isEmpty(p.properties)}"th:include="this::response(${p.properties},${count} + '' + ${c.count} + '.',${lv+1})"/></th:block>
</th:block></body>
</html>

7.运行

启动springboot项目,打开: http://localhost:8080/swagger-ui.html

点try it out. 运行成功返回下载文档路径。

下载结果:导出word格式接口文档。

相关文章:

使用thymeleaf模版导出swagger3的word格式接口文档

1.pom配置 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.8.RELEASE</version></parent><properties><skipTests>true</skipTests&g…...

Android RecyclerView自带的OnFlingListener,Kotlin

Android RecyclerView自带的OnFlingListener&#xff0c;Kotlin Android启动应用时屏蔽RecyclerView滑动&#xff0c;延时后再允许滑动&#xff0c;Kotlin-CSDN博客 使用了GestureDetectorRecyclerView的setOnTouchListener检测用户的快滑fling事件。发现RecyclerView也自带了监…...

STM32+安信可Ai-WB2-12F连接阿里云物联网平台

第一步&#xff1a;在阿里云物联网平台创建设备 具体操作流程如下 第二步&#xff1a;生成个人client_id,用户名和密码 打开该软件sign.html 将刚才复制的信息粘贴进去 生成自己的client_id,用户名和密码 第三步&#xff1a;打开MQTTfx软件 电机connect旁边的配置&#xff0…...

Python实现中文数字与阿拉伯数字映射生成器(支持0-9999)

文章目录 1. 引言2. 需求分析‌3. 核心实现思路‌4. 完整代码实现‌ 1. 引言 在中文文本处理和自然语言处理(NLP)应用中&#xff0c;经常需要将中文数字转换为阿拉伯数字。本文将介绍如何使用Python根据用户从控制台输入的数字范围&#xff0c;生成相应的中文数字到阿拉伯数字…...

链表的面试题4之合并有序链表

这篇文章我们继续来讲链表中很经典的面试题&#xff1a;合并有序链表。 目录 迭代 递归 我们首先来看一下这张图片里面的要求&#xff0c;给你两个链表&#xff0c;要求把他们按照从小到大的方式排列。 这里涉及到几个问题&#xff0c;首先&#xff0c;我们的头节点是不是要…...

CTF - PWN之ORW记录

CTF - Pwn之ORW记录https://mp.weixin.qq.com/s/uiRtqCSopn6U6NqyKJ8I7Q...

mission planner烧录ardupilot固件报错死机

问题 烧录自己编译的固件&#xff0c;upload done成功后&#xff0c;又跳出以下提示 &#xff0c;返回重新烧录仍然报错 解决 先烧录官方稳定的固件然后使用mission planner连接&#xff0c;此时可能会反复识别串口&#xff0c;因为会死机反复重启&#xff0c;导致灯闪烁又…...

单片机嵌入式滤波算法库

kw_ucFiltering库说明 本科针对常用的滤波算法进行汇总&#xff0c;主要包括&#xff1a; 一阶滤波算法 平滑滤波 中位值滤波 限幅 卡尔曼滤波 截至目前&#xff08;20250508&#xff09;滤波算法持续更新中。 本库开源连接地址&#xff1a;gitee连接 一阶滤波算法实现 原理…...

CAS、CAS自旋、CAS自旋锁、CLH锁与Java AQS:深入理解并发编程核心机制

CAS、CAS自旋、CAS自旋锁、CLH锁与Java AQS&#xff1a;深入理解并发编程核心机制 1. CAS&#xff08;Compare and Swap&#xff09; 什么是CAS&#xff1f; CAS&#xff08;Compare and Swap&#xff09;是一种无锁&#xff08;Lock-Free&#xff09;的原子操作&#xff0c;…...

《运维那些事儿》专栏总目录(持续更新)

《运维那些事儿》专栏以Linux系统为基础&#xff0c;分享作者十年运维生涯中运用到的关键技术要点。本专栏涵盖消息中间件、数据中间件、数据库、虚拟化、Web服务器、高可用架构等运维工作中涉及到的相关内容&#xff0c;每周持续交叉更新一篇高质量技术博文。学生可用于了解、…...

鸿蒙NEXT开发动画案例4

1.创建空白项目 2.Page文件夹下面新建Spin.ets文件&#xff0c;代码如下&#xff1a; /*** TODO SpinKit动画组件 - 双粒子旋转缩放动画* author: CSDN-鸿蒙布道师* since: 2025/05/08*/ ComponentV2 export struct SpinFour {// 参数定义Require Param spinSize: number 36…...

【Linux学习笔记】基础IO之理解文件

【Linux学习笔记】基础IO之理解文件 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;Linux学习笔记 前言 哈喽&#xff0c;各位小伙伴大家好!上期我们讲了进程替换 今天我们讲的是基础IO之理解文件。话不多说&#xff0c;我们进入正题&#…...

动态计算el-table高度

form、搜索框、底部导航栏设置class <el-table :height"tableHeight" /> // 计算表格高度的计算属性 const tableHeight ref(0); proxy.toTableHeight((res)>{tableHeight.value res; });tableHeight.js import { nextTick } from vue;export fun…...

【Linux系列】目录大小查看

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

数据结构*二叉树

树 树是一种非线性数据结构。 这就是抽象的树的结构。 对于一棵树来说&#xff0c;有N个结点&#xff0c;就有N-1条边 其中有许多概念&#xff1a; 根结点&#xff1a;对于上图来说就是A 子树&#xff1a;就是结点下面分开的部分。例如&#xff1a;A的子树就是以B为根结点的…...

RESTful

一&#xff1a;简介 定义 &#xff08;1&#xff09;访问网络资源的格式 &#xff08;2&#xff09;优点 &#xff08;3&#xff09;区分操作 &#xff08;4&#xff09;注意事项...

人工智能的自动驾驶新纪元:端到端智能系统挑战与前沿探索方案

一、引言:从模块化到端到端的范式革命 (一)自动驾驶技术演进的三个时代 自动驾驶技术自诞生以来,经历了从机械化辅助到智能化决策的漫长演进。早期,以定速巡航为代表的 1.0 时代,仅实现了简单的速度控制,车辆仍需驾驶员全程主导操控。随着传感器与算法发展,进入 2.0 时…...

第四章 OpenCV篇—图像梯度与边缘检测—Python

目录 一.Sobel算子 二.Scharr算子与laplacian算子 三.Canny边缘检测 1.高斯滤波器 2.梯度和方向 3.非极大值抑制 4.双阈值检测 此章节主要讲解图像梯度计算方法和边缘检测算法&#xff0c;分别主要是&#xff1a;sobel算子、scharr与lapkacian算子、canny边缘检测流程。…...

幂等的几种解决方案以及实践

目录 什么是幂等&#xff1f; 解决幂等的常见解决方案&#xff1a; 唯一标识符案例 数据库唯一约束 案例 乐观锁案例 分布式锁&#xff08;Distributed Locking&#xff09; 实践精选方案 首先 为什么不直接使用分布式锁呢&#xff1f; 自定义实现幂等组件&#xff01…...

拥塞控制 流量控制 区别

对比项拥塞控制流量控制关注对象整个网络 是否过载接收方主机 是否处理不过来控制目标避免网络路由器、链路拥塞避免发送方发太快&#xff0c;接收方来不及处理发生原因网络中有太多数据包&#xff0c;引起排队、丢包接收方缓存能力有限实现方式基于网络状态动态调整发送速率基…...

AWS VPC架构师指南:从零设计企业级云网络隔离方案

一、VPC核心概念解析 1.1 核心组件 VPC&#xff1a;逻辑隔离的虚拟网络&#xff0c;可自定义IPv4/IPv6地址范围&#xff08;CIDR块&#xff09; 子网&#xff08;Subnet&#xff09;&#xff1a; 公有子网&#xff1a;绑定Internet Gateway&#xff08;IGW&#xff09;&#…...

[逆向工程]什么是DLL注入(二十二)

[逆向工程]什么是DLL注入&#xff08;二十二&#xff09; 引言 DLL注入&#xff08;DLL Injection&#xff09; 是Windows系统下一种重要的进程控制技术&#xff0c;广泛应用于软件调试、功能扩展、安全检测等领域。然而&#xff0c;它也是一把“双刃剑”——恶意软件常借此实…...

极简远程革命:节点小宝 — 无公网IP的极速内网穿透远程解决方案

极简远程革命&#xff1a;节点小宝&#xff0c;让家庭与职场无缝互联 ——打破公网桎梏&#xff0c;重塑数字生活新体验 关键词&#xff1a;节点小宝&#xff5c;内网穿透&#xff5c;P2P直连&#xff5c;家庭网络&#xff5c;企业协作&#xff5c;智能组网节点小宝&#xff5…...

Vue生命周期脚手架工程Element-UI

一 Vue2.x生命周期 每个vue实例再被创建时都要经过一系列的初始化过程&#xff1a; 创建实例 装载模板 渲染模板等等 vue为生命周期中的每个状态都设置了钩子函数&#xff08;监听函数&#xff09;。每个vue实例处于不同的生命周期时&#xff0c;对应的函数就会触发调用 https:…...

LeetCode[226] 翻转二叉树

思路&#xff1a; 使用递归&#xff0c;归根结底还是左右节点互相倒&#xff0c;那么肯定需要一个temp节点在中间传递&#xff0c;最后就是递归&#xff0c;没什么说的 代码&#xff1a; /*** Definition for a binary tree node.* public class TreeNode {* int …...

ConcurrentHashMap解析

ConcurrentHashMap解析 以下是对 Java 8 及以后版本 ConcurrentHashMap 源码的深入解析&#xff0c;涵盖其底层数据结构、并发控制机制、核心操作流程、扩容与迁移、树化/退化策略&#xff0c;以及性能特性。总体来说&#xff0c;ConcurrentHashMap 在 JDK 8 中摒弃了原有的 S…...

windows10 系统显示mov文件格式缩略图

最近做视频剪辑&#xff0c;有些mov格式文件&#xff0c;但是尝试用各种播放器默认播放&#xff0c;都没有缩略图可看&#xff0c; 很影响查看。 遂选择了个插件&#xff0c;来在windows10系统显示mov文件的缩略图。 1.下载安装 K-Lite Codec Pack &#xff08;安装时一路Ne…...

力扣智慧思想小题,目录力扣.跳跃游戏(思想很重要)力扣.跳跃游戏II(还是思想)力扣.分发糖果力扣151.反转字符串中的单词力扣.轮转数组

目录 力扣.跳跃游戏(思想很重要) 力扣.跳跃游戏II&#xff08;还是思想) 力扣.分发糖果 力扣151.反转字符串中的单词 力扣.轮转数组 字符 a97 A65; JRE:Java运行时候的环境 JDK: JAVA开发套件(工具包) java原本是.java文件&#xff0c;编译成.class字节码文件 八种基本数据…...

【LangChain基础系列】深入全面掌握文本分类

文本分类是自然语言处理领域中的一个重要任务,旨在将文本数据自动归类到预定义的类别中。它是实现信息检索、智能推荐、情感分析等应用的基础技术之一。 应用场景 1. 垃圾邮件过滤 &#xff1a;自动识别并过滤垃圾邮件。 2. 情感分析 &#xff1a;分析用户评论或社交媒体内容…...

AI赋能高频PCB信号完整性优化

在5G通信、自动驾驶、卫星导航等高频技术快速迭代的今天&#xff0c;**信号完整性&#xff08;SI&#xff09;**已成为高频PCB设计的核心挑战。如何在高密度布线、复杂电磁环境中实现信号的精准传输&#xff1f;猎板PCB通过**AI驱动设计优化**、**材料与工艺创新**以及**智能化…...

如何从播放器构造角度研究 Media3 源码

Jetpack Media3 是 Android 提供的现代化媒体播放库。 Media3 的核心组件包括&#xff1a; ExoPlayer&#xff1a;播放器核心&#xff0c;负责协调媒体播放。MediaSource&#xff1a;定义媒体来源&#xff08;如 DASH、HLS、Progressive&#xff09;。TrackSelector&#xff…...

大模型深度思考与ReAct思维方式对比

大模型的「深度思考」与「ReAct思维方式」虽然都涉及复杂推理过程&#xff0c;但并非完全等同的概念。它们在目标、机制和应用场景上存在显著差异&#xff0c;以下是具体分析&#xff1a; 一、概念本质差异 深度思考&#xff08;Deep Reasoning&#xff09; 定义&#xff1a;泛…...

视频编解码学习六之视频采集和存储

视频采集的核心原理是用光学元件&#xff08;如摄像头&#xff09;将光信号转换为电信号进行传输和存储。 摄像头的主要功能是将光学图像转换为电信号&#xff08;模拟或数字&#xff09;&#xff0c;核心流程如下&#xff1a; 1. 光学成像 镜头组&#xff1a;聚焦光线到感光…...

Linux开发工具【中】

目录 一、vim 1.1 插入模式 1.2 底行模式 1&#xff09;set nu 2&#xff09;set nonu 3&#xff09; /XXX n 4&#xff09;&#xff01;command 5&#xff09;vs other 1.3 补充 1&#xff09; 批量化操作 2&#xff09;批量化替换 : 3&#xff09;快速定位&am…...

Django之账号登录及权限管理

账号登录及权限管理 目录 1.登录功能 2.退出登录 3.权限管理 4.代码展示合集 这篇文章, 会讲到如何实现账号登录。账号就是我们上一篇文章写的账号管理功能, 就使用那里面已经创建好的账号。这一次登录, 我们分为三种角色, 分别是员工, 领导, 管理员。不同的角色, 登录进去…...

深度学习Y7周:YOLOv8训练自己数据集

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、配置环境 1.官网下载源码 2.安装需要环境 二、准备好自己的数据 目录结构&#xff1a; 主目录 data images&#xff08;存放图片&#xff09; annotati…...

2025年渗透测试面试题总结-某服面试经验分享(附回答)(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 1. 协议类型 2. OSI七层模型 3. 网络层协议 4. HTTP请求头 5. 常见端口 6. 中间件解析漏洞 7. CS…...

手写Promise的静态方法

最近对promise原理的理解&#xff0c;手写下其中的静态方法。 手写Promise的静态方法 1. Promise.resolve2. Promise.reject3. Promise.all4. Promise.any5. Promise.race6. Promise.allSettled 1. Promise.resolve 首先就是resolve方法&#xff0c;它会接收一个值&#xff0…...

Python Cookbook-7.8 使用 Berkeley DB 数据库

任务 你想将一些数据做持久化处理&#xff0c;而且也想体验一下BerkeleyDB数据库的简洁和高效。 解决方案 如果以前在你的计算机中安装过 BerkeleyDB&#xff0c;Python标准库附带的bsddb包(以及可选的 bsddb3&#xff0c;用于访间Berkeley DBrelease 3.2数据库)可以被用来作…...

云手机虚拟地址技术的运营场景

云手机虚拟地址技术通过模拟地理位置&#xff08;GPS/IP地址&#xff09;与设备指纹&#xff0c;结合云端虚拟化能力&#xff0c;在多个商业场景中实现突破性应用。以下是其核心运营场景及技术实现路径的深度解析&#xff1a; 一、跨境电商与区域化运营 本地化合规与流量突破 目…...

操作符详解(2)

目录 9 结构成员访问操作符 9.1.2 结构体变量的定义和初始化 9.2 结构体成员的直接访问 10 操作符的属性&#xff1a;优先级、结合性 10.1 优先级 11 表达式求值 11.1 整型提升 11.2 算术转换 11.3 问题表达式解析 11.3.1 表达式1 11.3.2 表达式2 11.3.3 表达式3 1…...

责任链设计模式

一、核心接口定义 MyAbstractChainHandler<T> 接口继承自 Ordered 接口&#xff0c;用于实现链式处理逻辑。 import org.springframework.core.Ordered;public interface MyAbstractChainHandler<T> extends Ordered {void handle(T requestParam);String getCha…...

【银河麒麟高级服务器操作系统】服务器外挂存储ioerror分析及处理分享

更多银河麒麟操作系统产品及技术讨论&#xff0c;欢迎加入银河麒麟操作系统官方论坛 forum.kylinos.cn 了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;product.kylinos.cn 开发者专区&#xff1a;developer.kylinos.cn 文档中心&a…...

麒麟信安举办特种行业核心代理商中级技术认证培训班

近日&#xff0c;麒麟信安举办为期一周的特种行业核心代理商中级技术认证培训班&#xff0c;吸引了众多来自各地代理商公司的技术骨干踊跃参与。 此次培训班旨在赋能合作伙伴&#xff0c;助力其深入理解并熟练运用麒麟信安产品的核心优势&#xff0c;进一步提升在特种行业中的业…...

非对称加密:为什么RSA让“公开传密”成为可能

在1977年之前&#xff0c;加密世界遵循一个铁律&#xff1a;想要安全通信&#xff0c;必须先秘密交换密钥。无论是凯撒密码还是二战时的恩尼格玛机&#xff0c;都依赖发送方和接收方预先共享同一把“钥匙”。但RSA算法的出现颠覆了这一规则——它让陌生人可以在完全公开的环境下…...

阿里云ddos云防护服务器有哪些功能?ddos防御手段有哪些??

阿里云ddos云防护服务器有哪些功能?ddos防御手段有哪些&#xff1f;&#xff1f; DDoS&#xff08;分布式拒绝服务&#xff09;云防护服务器通过多种技术和策略来抵御大规模网络攻击&#xff0c;确保服务的高可用性。以下是其主要功能和防御手段的详细说明&#xff1a; 一、D…...

如何防止域名DNS被劫持?

防止域名DNS被劫持需要综合技术手段和管理措施&#xff0c;以下是一份详细的防护方案&#xff1a; --- ### **一、基础防护措施** 1. **选择可靠的域名注册商和DNS服务商** - 优先选择支持DNSSEC、提供多因素认证&#xff08;MFA&#xff09;的知名服务商&#xff08;如Cl…...

桥隧坡灾害监测报警:用科技筑起生命安全的“智能防线”

.2024年&#xff0c;梅大高速茶阳路段高边坡塌方事件造成重大伤亡&#xff0c;举国痛心。这场悲剧再次敲响警钟&#xff1a;桥梁、隧道、边坡等高风险区域的实时监测与精准报警&#xff0c;已成为交通安全的生命线。如何用技术手段在灾害发生前“抢跑”&#xff0c;第一时间阻断…...

K8S常见问题汇总

一、 驱逐 master 节点上的所有 Pod 这会“清空”一个节点&#xff08;包括 master&#xff09;上的所有可驱逐的 Pod&#xff1a; kubectl drain <master-node-name> --ignore-daemonsets --delete-emptydir-data--ignore-daemonsets&#xff1a;保留 DaemonSet 类型的…...

ideal创建Springboot项目(Maven,yml)

以下是使用 IntelliJ IDEA 创建基于 Maven 的 Spring Boot 项目并使用 YAML 配置文件的详细步骤&#xff1a; 一、创建 Spring Boot 项目 启动项目创建向导 打开 IntelliJ IDEA&#xff0c;点击“File”->“New”->“Project”。 在弹出的“New Project”窗口中&#…...