easyExcel動態應用案例

代碼鏈接:https://download.csdn.net/download/ly1h1/91940299

1.案例說明:

? ? 1.1.導入功能

導入數據實現轉換成? List<List<String>> headers和? List<List<String>> datas,后續補充可以與數據模型注解結合,形成類對象集合;

? ? 1.2.導出功能

復合表頭、下拉框選擇、列寬、表頭高度,均引出到業務層進行自定義設置。

2.引入依賴

<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel-core</artifactId><version>3.3.4</version><scope>compile</scope>
</dependency>

2.導入

2.1 Controller接口

2.2? 導入工具類-DymaticExcelImportUtil

package com.ruoyi.common.security.utils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;/*** 修復類型轉換異常的Excel導入工具類* 解決:java.lang.String cannot be cast to com.alibaba.excel.metadata.data.ReadCellData*/
public class DymaticExcelImportUtil {private static final Logger log = LoggerFactory.getLogger(DymaticExcelImportUtil.class);/*** 解析Excel輸入流為表頭和數據列表* @param inputStream Excel文件輸入流* @return 包含表頭和數據的結果對象*/public static ExcelParseResult importToList(InputStream inputStream) {if (Objects.isNull(inputStream)) {throw new IllegalArgumentException("輸入流不能為空");}ExcelReadListener listener = new ExcelReadListener();try {// 關鍵修復:指定讀取原始數據(不自動轉換為String)EasyExcel.read(inputStream).registerReadListener(listener).headRowNumber(1) // 指定表頭所在行數(默認第一行).doReadAll();} catch (Exception e) {log.error("Excel解析失敗: {}", e.getMessage(), e);throw new RuntimeException("Excel導入錯誤: " + e.getMessage());} finally {try {inputStream.close();} catch (Exception e) {log.warn("輸入流關閉失敗: {}", e.getMessage());}}return listener.getResult();}/*** 自定義監聽器(修復泛型類型匹配問題)*/private static class ExcelReadListener implements ReadListener<Map<Integer, Object>> {private final List<List<String>> headerLists = new ArrayList<>();private final List<List<String>> dataLists = new ArrayList<>();private boolean isHeaderParsed = false;/*** 處理表頭數據*/@Overridepublic void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {if (!isHeaderParsed) {List<String> headerRow = new ArrayList<>();// 遍歷表頭單元格并轉換為字符串for (int i = 0; i < headMap.size(); i++) {ReadCellData<?> cellData = headMap.get(i);headerRow.add(cellData.getStringValue() != null ? cellData.getStringValue().trim() : "");}headerLists.add(headerRow);isHeaderParsed = true;}}/*** 處理數據行(使用Object接收所有類型,避免強制轉換)*/@Overridepublic void invoke(Map<Integer, Object> dataMap, AnalysisContext context) {List<String> dataRow = new ArrayList<>();// 遍歷數據單元格,兼容所有類型for (int i = 0; i < dataMap.size(); i++) {Object cellValue = dataMap.get(i);dataRow.add(convertToString(cellValue));}dataLists.add(dataRow);}/*** 解析完成回調*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {log.info("Excel解析完成 - 表頭行數: {}, 數據行數: {}",headerLists.size(), dataLists.size());}/*** 萬能類型轉換:將任意單元格值轉換為字符串*/private String convertToString(Object value) {if (value == null) {return "";}// 處理ReadCellData類型(原始單元格數據)if (value instanceof ReadCellData<?>) {ReadCellData<?> cellData = (ReadCellData<?>) value;if (cellData.getStringValue() != null) {return cellData.getStringValue().trim();} else if (cellData.getNumberValue() != null) {return cellData.getNumberValue().toString();} else if (cellData.getBooleanValue() != null) {return cellData.getBooleanValue().toString();}}// 處理其他類型(如String、Number等)return value.toString().trim();}public ExcelParseResult getResult() {return new ExcelParseResult(headerLists, dataLists);}}/*** Excel解析結果封裝類*/public static class ExcelParseResult {private final List<List<String>> headerLists;private final List<List<String>> dataLists;public ExcelParseResult(List<List<String>> headerLists, List<List<String>> dataLists) {this.headerLists = headerLists;this.dataLists = dataLists;}public List<List<String>> getHeaderLists() {return headerLists;}public List<List<String>> getDataLists() {return dataLists;}}
}

3.導出

3.1?接口

package com.ruoyi.system.controller;import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.system.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;/*** 用戶控制器*/
@RestController
@RequestMapping("/api/user")
public class UserController {@Autowiredprivate IUserService userService;/*** 導出用戶Excel*/@GetMapping("/export/excel")public void exportUserExcel(HttpServletResponse response) {try {// 獲取Excel字節數組byte[] excelBytes = userService.exportUsersToExcel();// 設置響應頭response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("UTF-8");String fileName = URLEncoder.encode("用戶數據列表", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + fileName + ".xlsx");// 寫入響應流response.getOutputStream().write(excelBytes);response.getOutputStream().flush();} catch (Exception e) {// 異常處理try {response.setContentType("text/html;charset=utf-8");response.getWriter().write("導出失敗:" + e.getMessage());} catch (IOException ex) {throw new ServiceException("導出失敗!");}}}
}

3.2 Service

package com.ruoyi.system.service.impl;import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.security.utils.*;
import com.ruoyi.system.api.domain.SysDictData;
import com.ruoyi.system.domain.RpCompanyconfig;
import com.ruoyi.system.domain.User;
import com.ruoyi.system.mapper.RpCompanyconfigMapper;
import com.ruoyi.system.service.IRpCompanyconfigService;
import com.ruoyi.system.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.util.*;import org.springframework.stereotype.Service;import java.util.List;import static com.ruoyi.common.security.utils.ExcelFieldExtractor.extractField;/*** 用戶服務實現類*/
@Service
public class UserServiceImpl implements IUserService
{@Overridepublic List<User> listAllUsers() {// 模擬數據庫查詢return new ArrayList<>(Arrays.asList(new User(1L, "張三", 25, "zhangsan@example.com"),new User(2L, "李四", 30, "lisi@example.com"),new User(3L, "王五", 28, "water"),new User(4L, "趙六", 32, "zhaoliu@example.com")));}@Overridepublic byte[] exportUsersToExcel() throws IOException {// 1. 獲取用戶數據List<User> userList = listAllUsers();// 2. 構建表頭List<List<String>> headList = new ArrayList<>();List<String> H1=  new ArrayList<>();List<String> H2=  new ArrayList<>();List<String> H3=  new ArrayList<>();List<String> H4=  new ArrayList<>();H1.add("用戶ID");H1.add("用戶ID");H2.add("信息");H2.add("姓名");H3.add("信息");H3.add("年齡");H4.add("郵箱");H4.add("郵箱");headList.add(H1);headList.add(H2);headList.add(H3);headList.add(H4);// 設置下拉框數據(key:列索引,value:下拉選項數組)// 為第4列(性別列,索引從0開始)設置下拉框Map<Integer, String[]> dropdownDataMap = new HashMap<>();dropdownDataMap.put(3, new String[]{"男", "女", "未知"});// 3. 轉換數據格式List<List<String>> dataList = new ArrayList<>();for (User user : userList){List<String> row = new ArrayList<>();row.add(String.valueOf(user.getId()));row.add(user.getName());row.add(String.valueOf(user.getAge()));row.add(user.getEmail());dataList.add(row);}// 4. 設置列寬List<Integer> widthList = Arrays.asList(60, 15, 8, 50);List<List<ExceSortModelVO>> list= GenericExcelModelConverter.convertToExcelModelList(userList);for(int i=0;i<list.get(0).size();i++){if (!list.get(0).get(i).getDictType().equals("")){List<String> listItem = new ArrayList<>();List<SysDictData> sysDic =  DictUtils.getDictCache(list.get(0).get(i).getDictType());for (SysDictData item : sysDic){listItem.add(item.getDictLabel());}dropdownDataMap.put(i, listItem.toArray(new String[listItem.size()]));}}List<List<String>> nameList =  ExcelFieldExtractor.extractField(list, ExcelFieldExtractor.FieldType.NAME);List<List<String>> valueList =  ExcelFieldExtractor.extractField(list, ExcelFieldExtractor.FieldType.VALUE);List<List<Integer>> widthList2 =  ExcelFieldExtractor.extractField(list, ExcelFieldExtractor.FieldType.WIDTH);// 表頭行高設置(30點,比默認更高,適合顯示較長表頭)float headerHeight = 30f;// 5. 調用工具類生成Excelreturn DymaticExcelUtil.exportToBytes(headList, valueList, "用戶數據列表", widthList,dropdownDataMap,headerHeight);}
}

3.3?下拉框類

package com.ruoyi.common.security.utils;import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*** Excel下拉框數據處理器* 支持基于Map配置多列下拉框選項*/
public class DropdownDataHandler implements SheetWriteHandler {// 存儲列索引與下拉選項的映射關系 (列索引 -> 下拉選項數組)private final Map<Integer, String[]> dropdownDataMap;/*** 構造方法* @param dropdownDataMap 列索引與下拉選項的映射*/public DropdownDataHandler(Map<Integer, String[]> dropdownDataMap) {this.dropdownDataMap = dropdownDataMap != null ? dropdownDataMap : new HashMap<>();}@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {// 工作表創建前無需操作}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {Sheet sheet = writeSheetHolder.getSheet();Workbook workbook = writeWorkbookHolder.getWorkbook();// 獲取所有需要設置下拉框的列Set<Map.Entry<Integer, String[]>> entries = dropdownDataMap.entrySet();for (Map.Entry<Integer, String[]> entry : entries) {int columnIndex = entry.getKey();String[] options = entry.getValue();if (options == null || options.length == 0) {continue;}// 創建下拉框約束DataValidationHelper helper = sheet.getDataValidationHelper();DataValidationConstraint constraint = helper.createExplicitListConstraint(options);// 設置下拉框作用范圍(從第2行到第1000行,可根據實際需求調整)CellRangeAddressList addressList = new CellRangeAddressList(1, // 起始行索引(0表示表頭行,1表示數據開始行)1000, // 結束行索引columnIndex, // 起始列索引columnIndex  // 結束列索引);// 創建數據驗證并應用到工作表DataValidation dataValidation = helper.createValidation(constraint, addressList);// 設置錯誤提示if (dataValidation instanceof XSSFDataValidation) {dataValidation.setShowErrorBox(true);dataValidation.setSuppressDropDownArrow(true);} else {dataValidation.setShowErrorBox(true);}sheet.addValidationData(dataValidation);}}
}

3.4? 邊框類

package com.ruoyi.common.security.utils;import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import com.alibaba.excel.write.style.AbstractCellStyleStrategy;
import org.apache.poi.ss.usermodel.*;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Sheet;public class BorderStyleHandler implements CellWriteHandler {private void setBorderStyle(Cell cell) {if (cell == null) {return;}// 現在可以正確調用 POI Cell 的 getSheet() 方法Sheet sheet = cell.getSheet();if (sheet == null) {return;}Workbook workbook = sheet.getWorkbook();CellStyle cellStyle = workbook.createCellStyle();// 設置邊框樣式cellStyle.setBorderTop(BorderStyle.THIN);cellStyle.setBorderBottom(BorderStyle.THIN);cellStyle.setBorderLeft(BorderStyle.THIN);cellStyle.setBorderRight(BorderStyle.THIN);// 設置邊框顏色cellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());cellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());cellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());cellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());cell.setCellStyle(cellStyle);}// 其他接口方法實現...@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,List<WriteCellData<?>> cellDataList, Cell cell, Head head,Integer relativeRowIndex, Boolean isHead) {setBorderStyle(cell);}
}

3.5?列寬設定類

package com.ruoyi.common.security.utils;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import java.util.ArrayList;
import java.util.List;/*** 正確實現 SheetWriteHandler 接口(而非 WriteHandler 的子接口)* 適配 easyexcel-core:3.3.4 版本*/
public class FixedColumnWidthHandler implements SheetWriteHandler {private static final int DEFAULT_COLUMN_WIDTH = 15;/*** 存儲每列寬度(單位:1/256 字符寬度,EasyExcel 底層單位)*/private final List<Integer> columnWidths = new ArrayList<>();/*** 添加列寬配置* @param columnIndex 列索引(從0開始)* @param width 列寬(單位:字符)*/public void addColumnWidth(int columnIndex, int width) {// 確保列表容量足夠,避免索引越界while (columnWidths.size() <= columnIndex) {columnWidths.add(DEFAULT_COLUMN_WIDTH * 256); // 默認寬度轉底層單位}columnWidths.set(columnIndex, width * 256); // 傳入寬度轉底層單位}/*** 工作表創建前觸發(無需處理)*/@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {// 空實現}/*** 工作表創建后觸發(核心:設置列寬)*/@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {// 遍歷設置每列寬度for (int i = 0; i < columnWidths.size(); i++) {writeSheetHolder.getSheet().setColumnWidth(i, columnWidths.get(i));}}
}

3.6?表頭高度類

package com.ruoyi.common.security.utils;import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Row;/*** 表頭行高處理器(在表頭行創建后立即設置高度)*/
public class HeaderHeightHandler implements RowWriteHandler {private final float headerHeight; // 表頭行高(單位:點)// 構造方法接收表頭行高參數public HeaderHeightHandler(float headerHeight) {// 確保行高不小于10點,避免過小導致不可見this.headerHeight = Math.max(headerHeight, 10f);}/*** 行創建后立即設置高度(關鍵修復:在此處設置表頭行高)*/@Overridepublic void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {// 只處理表頭行(isHead為true時)if (Boolean.TRUE.equals(isHead)) {// 直接設置行高(單位:點),POI會自動轉換為內部單位row.setHeightInPoints(headerHeight);}}// 其他接口方法空實現@Overridepublic void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, Integer relativeRowIndex, Boolean isHead) {}
}

3.7 導出數據模型類

package com.ruoyi.common.security.utils;public class ExceSortModelVO {private String name;private String value;private int sort;private  int width;private  String dictType;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public int getSort() {return sort;}public void setSort(int sort) {this.sort = sort;}public int getWidth() {return width;}public void setWidth(int width) {this.width = width;}public String getDictType() {return dictType;}public void setDictType(String dictType) {this.dictType = dictType;}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/97022.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/97022.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/97022.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【數據結構入門】排序算法(5):計數排序

目錄 1. 比較排序和非比較排序 2. 計數排序的原理 2.1 計數排序的弊端 3.代碼復現 3.1 代碼分析 3.2 排序核心 3.3 時間、空間復雜度 1. 比較排序和非比較排序 比較排序是根據排序元素的具體數值比較來進行排序&#xff1b;非比較排序則相反&#xff0c;非比較排序例如&…

輸入3.8V~32V 輸出2A 的DCDC降壓芯片SCT9320

同志們&#xff0c;今天來個降壓芯片SCT9320。輸入3.8V~32V&#xff0c;輸出最高可以達到2A。0.8V的參考電壓。500k的開關頻率。一共八個引腳&#xff0c;兩個NC&#xff08;為什么不做成六個引腳呢&#xff1f;&#xff09;。EN引腳懸空或者接到VIN都可以直接啟動&#xff0c;…

C++類和對象詳解(2);初識類的默認成員函數

1.類的默認成員函數默認成員函數就是用戶沒有顯示實現&#xff0c;編譯器會自動生成的成員函數稱為默認成員函數。一個類我們不寫的情況下編譯器會默認生成以下的6個默認成員函數。&#xff08;1&#xff09;構造函數&#xff1a;主要完成初始化的工作&#xff08;2&#xff09…

PLC通信 Tpc客戶端Socket

1.PLC通信 namespace _2.PLC通信 {public partial class Form1 : Form{public Form1(){InitializeComponent();}//連接//1.型號: 跟PLC溝通 使用哪個型號的PLC//2.IP 同上//3.機臺號:同上//4.插槽號:同上Plc plc new Plc(CpuType.S71200, "192.168.25.80", 0, 1);pr…

Android 開發實戰:從零到一集成 espeak-ng 實現中文離線 TTS(無需賬號開箱即用)

簡介 在移動應用開發中,語音合成(TTS)技術是提升用戶體驗的重要工具。然而,許多開發者在集成 TTS 時面臨依賴網絡、需注冊賬號、功能受限等問題。本文將帶你從零開始,通過開源項目 espeak-ng,實現無需賬號、開箱即用的中文離線語音播報。 文章將覆蓋以下核心內容: esp…

直播APP集成美顏SDK詳解:智能美妝功能的開發實戰

在這個“顏值即正義”的時代&#xff0c;用戶對直播APP的第一印象&#xff0c;往往來自主播的畫面質量。高清的視頻固然重要&#xff0c;但如果缺少自然美顏和智能美妝功能&#xff0c;觀眾體驗就會大打折扣。于是&#xff0c;美顏SDK成了直播行業的“標配”。今天&#xff0c;…

C++內存管理:new與delete的深層解析

1. 引言在C的世界里&#xff0c;動態內存管理是一個核心話題。對于從C語言過渡到C的開發者來說&#xff0c;一個常見的困惑是&#xff1a;既然C語言的malloc和free依然可以在C中使用&#xff0c;為什么C還要引入new和delete這兩個操作符&#xff1f;本文將深入探討這兩對內存管…

【AI開發】【前后端全棧】[特殊字符] AI 時代的快速開發思維

&#x1f680; AI 時代的快速開發思維 —— 以 Django Vue3 為例的前后端分離快捷開發流程 一、AI 時代的開發新思路 在 AI 的加持下&#xff0c;軟件開發不再是“純體力活”&#xff0c;而是 思維工具自動化 的協作。 過去&#xff1a;需求 → 設計 → 開發 → 測試 → 上…

Day24_【深度學習(3)—PyTorch使用—張量的創建和類型轉換】

一、創建張量1.張量基本創建方式torch.tensor 根據指定數據創建張量 &#xff08;最重要&#xff09;torch.Tensor 根據形狀創建張量, 其也可用來創建指定數據的張量torch.IntTensor、torch.FloatTensor、torch.DoubleTensor 創建指定類型的張量1.1 torch.tensor# 方式一&…

3-12〔OSCP ? 研記〕? WEB應用攻擊?利用XSS提權

鄭重聲明&#xff1a; 本文所有安全知識與技術&#xff0c;僅用于探討、研究及學習&#xff0c;嚴禁用于違反國家法律法規的非法活動。對于因不當使用相關內容造成的任何損失或法律責任&#xff0c;本人不承擔任何責任。 如需轉載&#xff0c;請注明出處且不得用于商業盈利。 …

AI 大模型賦能智慧礦山:從政策到落地的全棧解決方案

礦山行業作為能源與工業原料的核心供給端&#xff0c;長期面臨 “安全生產壓力大、人工效率低、技術落地難” 等痛點。隨著 AI 大模型與工業互聯網技術的深度融合&#xff0c;智慧礦山已從 “政策引導” 邁入 “規模化落地” 階段。本文基于 AI 大模型智慧礦山行業解決方案&…

Node.js 項目依賴包管理

h5打開以查看 一、核心理念&#xff1a;從“能用就行”到“精細化管理” 一個規范的依賴管理體系的目標是&#xff1a; 可復現&#xff1a;在任何機器、任何時間都能安裝完全一致的依賴&#xff0c;保證構建結果一致。 清晰可控&#xff1a;明確知道每個依賴為何存在&#x…

洛谷P1835素數密度 詳解

題目如下&#xff1a;這里面有部分代碼比較有意思&#xff1a;1&#xff0c;為何開始先遍歷&#xff0c;最終值小于50000&#xff1f;因為題目要求的右邊與左邊差小于 10^6 &#xff0c;所以最多有10^3個素數&#xff0c;所以保存里面的素數數量大于1000&#xff0c;而50000的化…

突破限制:FileCodeBox遠程文件分享新體驗

文章目錄【視頻教程】1.Docker部署2.簡單使用演示3. 安裝cpolar內網穿透4. 配置公網地址5. 配置固定公網地址在隱私日益重要的今天&#xff0c;FileCodeBox與cpolar的協同為文件傳輸提供了安全高效的解決方案。通過消除公網IP限制和隱私顧慮&#xff0c;讓每個人都能掌控自己的…

以太網鏈路聚合實驗

一、實驗目的掌握使用手動模式配置鏈路聚合的方法掌握使用靜態 LACP 模式配置鏈路聚合的方法掌握控制靜態 LACP 模式下活動鏈路的方法掌握靜態 LACP 的部分特性的配置二、實驗環境安裝有eNSP模擬器的PC一臺&#xff0c;要求PC能聯網。三、實驗拓撲LSW1與LSW2均為S3700交換機。L…

autMan安裝教程

一、安裝命令 如果你系統沒安裝docker&#xff0c;請看往期教程 以下為通用命令 docker run -d --name autman --restart always -p 8080:8080 -p 8081:8081 -v /root/autman:/autMan --log-opt max-size10m --log-opt max-file3 hdbjlizhe/autman:latest解釋一下以上命令&…

【無人機】自檢arming參數調整選項

檢查項目 (英文名)中文含義檢查內容四旋翼建議 (新手 → 老手)理由說明All所有檢查啟用下面所有的檢查項目。? 強烈建議勾選這是最安全的設置&#xff0c;確保所有關鍵系統正常。Barometer氣壓計檢查氣壓計是否健康、數據是否穩定。? 必須勾選用于定高模式&#xff0c;數據異…

數字圖像處理(1)OpenCV C++ Opencv Python顯示圖像和視頻

Open CV C顯示圖像#include <iostream> #include <opencv2/opencv.hpp> using namespace cv;//包含cv命名空間 int main() {//imread(path)&#xff1a;從給定路徑讀取一張圖片&#xff0c;儲存為Mat變量對象Mat img imread("images/love.jpg");//named…

【芯片設計-信號完整性 SI 學習 1.2.2 -- 時序裕量(Margin)】

文章目錄1. 什么是時序裕量&#xff08;Margin&#xff09;1. 背景&#xff1a;為什么需要數字接口時序分析2. 時鐘周期方程3. Setup 裕量 (tMARGIN_SETUP)4. Hold 裕量 (tMARGIN_HOLD)5. 設計注意事項6. 實際應用場景2. 時序裕量的來源3. 測試方法(1) 眼圖測試 (Eye Diagram)(…

AOP 切面日志詳細

在業務方法上打注解package com.lib.service;Service public class BookService {LogExecution(description "查詢圖書")public Book query(int id) {return repo.findById(id);}LogExecution(description "借閱圖書")public void borrow(int id) {// 模…