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

EasyExcel实现图片导出功能(记录)

背景:在旧系统的基础上,导出一些工单信息时,现需要新添加处理人的签名或者签章,这就涉及图片的上传、下载、写入等几个操作。

1、EasyExcel工具类

(1)支持下拉框的导出。

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com..common.handler.DropDownHandler;
import com..modules.device.convert.ImageCellWriteHandler;
import com..modules.device.domain.vo.DeviceAndTypeVO;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;@Slf4j
public class ExcelExportUtil {private static final String CHARACTER = "UTF-8";private static final String CONTENT_TYPE = "application/vnd.ms-excel;charset=utf-8";private static final String CONTENT_DISPOSITION = "Content-Disposition";private static final String CACHE_CONTROL = "Cache-Control";private static final String NO_STORE = "no-store";private static final String MAX_AGE = "max-age=0";private static final String PASSWORD = "excel_unlock";private static final Integer colSplit = 0;private static final Integer rowSplit = 1;private static final Integer leftmostColumn = 0;private static final Integer topRow = 1; 
/*** 通用导出 Excel 方法(支持下拉框和每行图片插入)** @param response         HttpServletResponse* @param data             导出数据,数据行顺序与 Excel 中顺序一致(表头在第0行,第一条数据为第1行)* @param clazz            数据模型 Class* @param fileName         导出文件名(不包含后缀)* @param dropDownHandler  下拉框处理器(可选,可传 null)* @param imagesList       每条记录对应的图片数据列表,List中每个元素为 byte[2] 数组,*                         第0位为签名图片, 第1位为签章图片(可有可无)* @param signCol          签名图片插入列(0-based)* @param signatureCol     签章图片插入列(0-based)* @throws IOException     I/O 异常时抛出*/public static void exportExcel(HttpServletResponse response, List<?> data, Class<?> clazz, String fileName,Object dropDownHandler, List<byte[][]> imagesList,int signCol, int signatureCol) throws IOException {String fullFileName = fileName + ".xlsx";String encodedFileName = URLEncoder.encode(fullFileName, StandardCharsets.UTF_8.toString());response.setCharacterEncoding(CHARACTER);response.setContentType(CONTENT_TYPE);response.setHeader(CONTENT_DISPOSITION, "attachment; filename=" + encodedFileName);response.setHeader(CACHE_CONTROL, NO_STORE);response.addHeader(CACHE_CONTROL, MAX_AGE);ServletOutputStream out = null;ExcelWriter excelWriter = null;try {out = response.getOutputStream();ExcelWriterBuilder writerBuilder = EasyExcelFactory.write(out, clazz);// 注册下拉框处理器(需确保 dropDownHandler 是 WriteHandler 类型)if (dropDownHandler != null && dropDownHandler instanceof WriteHandler) {writerBuilder.registerWriteHandler((WriteHandler) dropDownHandler);}excelWriter = writerBuilder.build();WriteSheet writeSheet = EasyExcelFactory.writerSheet(fileName).build();excelWriter.write(data, writeSheet);// 获取 Workbook 和 SheetWorkbook workbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook();Sheet sheet = workbook.getSheetAt(0);// 遍历数据行插入图片(从第1行开始)if (imagesList != null && !imagesList.isEmpty()) {for (int i = 0; i < data.size(); i++) {int targetRowIndex = i + 1; // 数据行从第1行开始if (i < imagesList.size()) {byte[][] images = imagesList.get(i);if (images != null) {insertImages(sheet, workbook, targetRowIndex, images, signCol, signatureCol);}}}}// 必须显式调用 finish 确保数据写入流excelWriter.finish();out.flush();} catch (Exception e) {throw new IOException("导出 Excel 失败: " + e.getMessage(), e);} finally {// 手动关闭资源(注意顺序:先关闭 excelWriter,再关闭流)if (excelWriter != null) {excelWriter.finish(); // finish() 包含关闭操作}if (out != null) {try {out.close();} catch (IOException e) {log.error("关闭输出流异常: ", e);}}}}/*** 通用的图片插入方法,在指定的 Excel 行中插入签名和签章图片** @param sheet         目标 Sheet* @param workbook      Excel Workbook* @param targetRow     目标行索引(0-based;表头为0,第一条数据为1)* @param images        byte[2] 数组,其中 images[0] 为签名图片,images[1] 为签章图片* @param signCol       签名图片插入列(0-based)* @param signatureCol  签章图片插入列(0-based)*/private static void insertImages(Sheet sheet, Workbook workbook, int targetRow, byte[][] images,int signCol, int signatureCol) {if (sheet == null || workbook == null) {return;}Row row = sheet.getRow(targetRow);if (row == null) {row = sheet.createRow(targetRow);}Drawing<?> drawing = sheet.createDrawingPatriarch();if (images[0] != null && images[0].length > 0) {int pictureIdx = workbook.addPicture(images[0], Workbook.PICTURE_TYPE_PNG);ClientAnchor anchor = new XSSFClientAnchor(0, 0, 1023, 255, signCol, targetRow, signCol + 1, targetRow + 1);drawing.createPicture(anchor, pictureIdx);}if (images[1] != null && images[1].length > 0) {int pictureIdx = workbook.addPicture(images[1], Workbook.PICTURE_TYPE_PNG);ClientAnchor anchor = new XSSFClientAnchor(0, 0, 1023, 255, signatureCol, targetRow, signatureCol + 1, targetRow + 1);drawing.createPicture(anchor, pictureIdx);}}
}

(2)无下拉框实现

/*** 配合insertImages(Sheet sheet, Workbook workbook, byte[] signImage, byte[] signatureImage,*                                      int targetRowIndex, int signCol, int signatureCol) 方法使用* @param response* @param data* @param clazz* @param fileName* @param signImage* @param signatureImage* @param targetRow* @param signCol* @param signatureCol* @throws IOException*/public static void exportExcel(HttpServletResponse response, List<?> data, Class<?> clazz, String fileName,byte[] signImage, byte[] signatureImage,int targetRow, int signCol, int signatureCol) throws IOException {String encodedFileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");response.setCharacterEncoding("UTF-8");response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName);response.setHeader("Cache-Control", "no-store");response.addHeader("Cache-Control", "max-age=0");ExcelWriter excelWriter = null;ServletOutputStream out = null;try {out = response.getOutputStream();excelWriter = EasyExcelFactory.write(out, clazz).build();WriteSheet writeSheet = EasyExcelFactory.writerSheet(fileName).build();excelWriter.write(data, writeSheet);// 获取 Workbook 和 SheetWorkbook workbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook();Sheet sheet = workbook.getSheetAt(0);// 插入图片insertImages(sheet, workbook, signImage, signatureImage, targetRow, signCol, signatureCol);// 必须显式调用 finish 确保写入完成excelWriter.finish();out.flush();} finally {// 手动关闭资源(EasyExcel 3.x 中 finish() 已包含关闭操作)if (excelWriter != null) {excelWriter.finish(); // 确保资源释放}if (out != null) {out.close();}}}/*** 通用inserImages方法,和没有的DropDownHandler dropDownHandler参数的exportExcel方法一起配合使用* @param sheet* @param workbook* @param signImage* @param signatureImage* @param targetRowIndex* @param signCol* @param signatureCol*/private static void insertImages(Sheet sheet, Workbook workbook, byte[] signImage, byte[] signatureImage,int targetRowIndex, int signCol, int signatureCol) {if (sheet == null || workbook == null) {log.warn("插入图片失败: sheet 或 workbook 为空");return;}// 确保目标行存在Row row = sheet.getRow(targetRowIndex);if (row == null) {row = sheet.createRow(targetRowIndex);}Drawing<?> drawing = sheet.createDrawingPatriarch();// 插入签名图片if (signImage != null && signImage.length > 0) {int pictureIdx = workbook.addPicture(signImage, Workbook.PICTURE_TYPE_PNG);ClientAnchor anchor = new XSSFClientAnchor(0, 0, 1023, 255, signCol, targetRowIndex, signCol + 1, targetRowIndex + 1);drawing.createPicture(anchor, pictureIdx);}// 插入签章图片if (signatureImage != null && signatureImage.length > 0) {int pictureIdx = workbook.addPicture(signatureImage, Workbook.PICTURE_TYPE_PNG);ClientAnchor anchor = new XSSFClientAnchor(0, 0, 1023, 255, signatureCol, targetRowIndex, signatureCol + 1, targetRowIndex + 1);drawing.createPicture(anchor, pictureIdx);}}

2、实体类和自定义转换类

//使用自定义转换器,写入空内容,但表头显示“签名”@ExcelProperty(value = "处理人签名", converter = ImageHeaderConverter.class, index = 15)private byte[] signImage;// 使用自定义转换器,写入空内容,但表头显示“签名”@ExcelProperty(value = "处理人签章", converter = ImageHeaderConverter.class, index = 16)private byte[] signatureImage;/*** 自定义Converter*/
public class ImageHeaderConverter implements Converter<byte[]> {@Overridepublic Class supportJavaTypeKey() {return byte[].class;}@Overridepublic WriteCellData<?> convertToExcelData(byte[] value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {// 返回空数据,防止自动转换报错,但表头信息仍会根据@ExcelProperty的value显示return new WriteCellData<>("");}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return null;}public byte[] convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {return new byte[0];}
}

3、根据图片路径下载图片工具类

public class ImagesUtils {public static byte[] downloadImage(String imageUrl) {if (imageUrl == null || imageUrl.trim().isEmpty()) {log.warn("下载图片失败: imageUrl 为空");return null;}HttpURLConnection connection = null;try {URL url = new URL(imageUrl);connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("GET");connection.setConnectTimeout(10000);  // 增加超时时间到10秒connection.setReadTimeout(10000);connection.setInstanceFollowRedirects(true); // 允许自动重定向// 检查 HTTP 响应码int statusCode = connection.getResponseCode();if (statusCode != HttpURLConnection.HTTP_OK) {log.warn("下载图片失败: {},HTTP状态码: {},响应消息: {}",imageUrl, statusCode, connection.getResponseMessage());return null;}try (InputStream inputStream = connection.getInputStream();ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {byte[] buffer = new byte[4096];  // 增大缓冲区提升读取效率int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}return outputStream.toByteArray();}} catch (Exception e) {log.warn("下载图片失败: {},错误类型: {},详细信息: {}",imageUrl, e.getClass().getSimpleName(), e.getMessage(), e); // 输出完整异常return null;} finally {if (connection != null) {connection.disconnect(); // 显式断开连接}}}
}

4、业务逻辑实现

// 1. 查询 Channel_SIGN_SIGNATURE 表,获取所有处理记录List<ChannelSignSignature> processList = channelSignSignatureMapper.selectList(new LambdaQueryWrapper<ChannelSignSignature>().in(ChannelSignSignature::getDisposeChannelId, ids));if (CollectionUtils.isEmpty(processList)) {return ReposeResult.failed(ResultCode.CHANNEL_EXPORT_NULL);}//根据前端传入的ids顺序排序处理记录Map<Long, ChannelSignSignature> processMap = processList.stream().collect(Collectors.toMap(ChannelSignSignature::getDisposeChannelId, Function.identity()));List<ChannelSignSignature> sortedProcessList =  new ArrayList<>();for (Long id :ids) {if (!processMap.containsKey(id)) {return ReposeResult.failed("部分导出ID未保存处理记录,请先处理记录再导出");}sortedProcessList.add(processMap.get(id));}// 2. 获取所有处理人姓名(保持原顺序)List<String> userNames = sortedProcessList.stream().map(ChannelSignSignature::getChannelRecordName).collect(Collectors.toList());// 3. 批量查询用户信息(userId 映射表)Map<String, Long> userIdMap;if (CollectionUtils.isEmpty(userNames)) {userIdMap = new HashMap<>();} else {List<User> users = userMapper.selectList(new LambdaQueryWrapper<User>().in(User::getUsername, userNames));userIdMap = users.stream().collect(Collectors.toMap(User::getUsername, User::getId, (u1, u2) -> u1));}// 4. 查询用户签名 & 签章Map<Long, List<String>> signMap = new HashMap<>();Map<Long, List<String>> signatureMap = new HashMap<>();if (!userIdMap.isEmpty()) {// 4.1 批量查询用户签名(userId -> 签名列表)List<UserSign> userSigns = userSignMapper.selectList(new LambdaQueryWrapper<UserSign>().in(UserSign::getUserId, userIdMap.values()));signMap = userSigns.stream().collect(Collectors.groupingBy(UserSign::getUserId,LinkedHashMap::new,Collectors.mapping(UserSign::getContent, Collectors.toList())));// 4.2 批量查询用户签章(userId -> 签章列表)List<UserSignature> userSignatures = userSignatureMapper.selectList(new LambdaQueryWrapper<UserSignature>().in(UserSignature::getUserId, userIdMap.values()));signatureMap = userSignatures.stream().collect(Collectors.groupingBy(UserSignature::getUserId,LinkedHashMap::new,Collectors.mapping(UserSignature::getContent, Collectors.toList())));}Integer grading = UserUtils.getUser().getGrading();HashMap<Integer, String[]> dropDownMap = new HashMap<>();String[] results = Arrays.stream(ChannelResultEnum.values()).map(ChannelResultEnum::getDesc).toArray(String[]::new);dropDownMap.put(13, results);List<ChannelVO> channels = channelMapper.selectJoinList(ChannelVO.class, new MPJLambdaWrapper<>(DataChannel.class).selectAll(DataChannel.class).select(Dept::getDeptName).selectAs(Period::getDescription, "period").select(BenchInfo::getBench).selectCollection(MachineInfo.class, ChannelVO::getMachineInfos).leftJoin(ChannelModel.class, ChannelModel::getChannelId, DataChannel::getId).leftJoin(MachineInfo.class, MachineInfo::getId, ChannelModel::getModelId).leftJoin(Dept.class, Dept::getId, DataChannel::getDeptId).leftJoin(Period.class, Period::getId, DataChannel::getPeriodId).leftJoin(BenchInfo.class, BenchInfo::getId, DataChannel::getBenchId).ge(ObjectUtils.isNotEmpty(grading), DataChannel::getGrading, grading).in(DataChannel::getId, ids));channels.forEach(channelVO -> {List<String> models = channelVO.getMachineInfos().stream().map(MachineInfo::getModel).collect(Collectors.toList());channelVO.setModel(String.join(",", models));});//根据前端传入的ids顺序排序channelVOMap<Long, ChannelVO> channelVoMap= channels.stream().collect(Collectors.toMap(ChannelVO::getId, Function.identity()));List<ChannelVO> sortedChannelVOs = new ArrayList<>();for (Long id:ids) {if (!channelVoMap.containsKey(id)) {return ReposeResult.failed("部分导出ID未保存检查记录,请先保存处理记录再导出");}sortedChannelVOs.add(channelVoMap.get(id));}List<ExportChannelDTO> exportChannelDTOS = CopyUtils.copyList(sortedChannelVOs, ExportChannelDTO.class);// 5. 按 `userNames` 生成 `signUrls` 和 `signatureUrls`(保证顺序)List<String> signUrls = new ArrayList<>();List<String> signatureUrls = new ArrayList<>();for (String userName : userNames) {Long userId = userIdMap.get(userName);if (userId != null) {List<String> signs = signMap.getOrDefault(userId, Collections.emptyList());List<String> signatures = signatureMap.getOrDefault(userId, Collections.emptyList());// 如果有签名,添加签名;如果有签章,添加签章;如果都有,则都添加if (!signs.isEmpty()) {signUrls.addAll(signs);} else {signUrls.add(null);}if (!signatures.isEmpty()) {signatureUrls.addAll(signatures);} else {signatureUrls.add(null);}} else {// 处理人无签名/签章,则填充 nullsignUrls.add(null);signatureUrls.add(null);}}// 7. 赋值到 DTOfor (int i = 0; i <  exportChannelDTOS.size(); i++) {ExportChannelDTO dto =  exportChannelDTOS.get(i);// 取签名图片if (signUrls.get(i) != null) {dto.setSignImage(downloadImage(BASE_IMAGE_URL + signUrls.get(i)));} else {dto.setSignImage(null);}// 取签章图片if (signatureUrls.get(i) != null) {dto.setSignatureImage(downloadImage(BASE_IMAGE_URL + signatureUrls.get(i)));} else {dto.setSignatureImage(null);}}// 8. 构造图片数据列表,与 checkDTOS 顺序一致List<byte[][]> imagesList = exportChannelDTOS.stream().map(dto -> new byte[][]{dto.getSignImage() != null ? dto.getSignImage() : new byte[0],dto.getSignatureImage() != null ? dto.getSignatureImage() : new byte[0]}).collect(Collectors.toList());ExcelExportUtil.exportExcel(response,exportChannelDTOS,ExportChannelDTO.class,ConstantUtil.DATA_CHANNEL,new DropDownHandler(dropDownMap),imagesList,15,16);log.info("---导出数据通道信息完成---");         

代码不可直接使用,只是自己记录一下,方便下次使用,你完全可以使用AI来帮你写这些部分。

相关文章:

EasyExcel实现图片导出功能(记录)

背景&#xff1a;在旧系统的基础上&#xff0c;导出一些工单信息时&#xff0c;现需要新添加处理人的签名或者签章&#xff0c;这就涉及图片的上传、下载、写入等几个操作。 1、EasyExcel工具类 &#xff08;1&#xff09;支持下拉框的导出。 import com.alibaba.excel.Easy…...

PCL拟合空间3D圆周 fit3DCircle

PCL版本 1.15.0 main.cpp #include<vector> #include<iostream> #include <array> #include <string> #include <windows.h> #include <omp.h> #include <charconv> // C17 #include <cstdlib> #include<chrono> #in…...

ansible 实现达梦7数据库初始化数据脚本写入

关于使用ansible 对ARM版达梦7的k8s自动化部署参考我的这篇操作 ansible-playbook 写arm版达梦7数据库的一键安装脚本-CSDN博客文章浏览阅读303次&#xff0c;点赞5次&#xff0c;收藏3次。达梦官方提供镜像目前是dm8_x86 版本&#xff0c;因为众所周知的国产化方面的需求&…...

leetcode每日刷题

Day18 Title45.jump(跳跃游戏 II) 解法一&#xff1a;动态规划 依然分三步走&#xff1a; 1.状态方程 2.dp[i]的意义 3.边界条件及初始值 优先思考第二个问题&#xff1a; dp[i]表示到达i时需要的最少跳数 第一个问题&#xff1a; dp[ij]min(dp[i]1,dp[ij]) 为什么&am…...

Ubuntu安装Nginx

Ubuntu安装Nginx 由于 Ubuntu 的 apt 命令内置了 nginx 源&#xff0c;因此不用配置 apt 就可以直接下载安装&#xff1a; apt install nginx -y查看 nginx 是否启动&#xff1a; ps -ef |grep nginx如果没有启动则需要手动启动&#xff1a; nginx1. 配置Nginx 使用浏览器…...

Hadoop的序列化

&#xff08;一&#xff09;什么是序列化与反序列化 序列化就是把内存中的对象&#xff0c;转换成字节序列&#xff08;或其他数据传输协议&#xff09;以便于存储到磁盘&#xff08;持久化&#xff09;和网络传输。 反序列化就是将收到字节序列&#xff08;或其他数据传输协议…...

拼多多商品详情接口爬虫实战指南

一、引言 在电商运营和数据分析中&#xff0c;获取商品详情数据是至关重要的一步。拼多多作为国内知名的社交电商平台&#xff0c;提供了丰富的商品详情接口&#xff0c;允许开发者通过API获取商品的详细信息。本文将详细介绍如何通过爬虫技术结合拼多多商品详情接口&#xff…...

python网络爬虫

一、Python爬虫核心库 HTTP请求库 requests&#xff1a;简单易用的HTTP请求库&#xff0c;处理GET/POST请求。aiohttp&#xff1a;异步HTTP客户端&#xff0c;适合高并发场景。 HTML/XML解析库 BeautifulSoup&#xff1a;基于DOM树的解析库&#xff0c;支持多种解析器&#xf…...

java线程安全-单例模式-线程通信

首先看看单例模式的写法 首先我们先来回顾一下饿汉式单例模式&#xff1a; class Singleton{private static Singleton singletonnew Singleton();private Singleton(){}public static Singleton getInstrance(){return singleton;} } public class Test{public static void …...

ASP.NET中将 PasswordHasher 使用的 PBKDF2 算法替换为更现代的 Scrypt 或 Argon2 算法

相关博文&#xff1a; .Net实现SCrypt Hash加密_scrypt加密-CSDN博客 密钥派生算法介绍 及 PBKDF2(过时)&#xff1c;Bcrypt(开始淘汰)&#xff1c;Scrypt&#xff1c; Argon2(含Argon2d、Argon2i、Argon2id)简介-CSDN博客 浅述.Net中的Hash算法&#xff08;顺带对称、非对称…...

力扣刷题-热题100题-第34题(c++、python)

23. 合并 K 个升序链表 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/merge-k-sorted-lists/?envTypestudy-plan-v2&envIdtop-100-liked 顺序合并 合并两个有序链表作为子函数&#xff0c;创建一个空链表&#xff0c;然后对含有多个链表的数组进…...

【SpringCloud】从入门到精通【上】

今天主播我把黑马新版微服务课程MQ高级之前的内容都看完了&#xff0c;虽然在看视频的时候也记了笔记&#xff0c;但是看完之后还是忘得差不多了&#xff0c;所以打算写一篇博客再温习一下内容。 课程坐标:黑马程序员SpringCloud微服务开发与实战 微服务 认识单体架构 单体架…...

如何给路由器配置代理IP?更改网络ip地址时出现错误怎么解决?

在现代网络环境中&#xff0c;无论是家庭用户还是企业用户&#xff0c;经常需要配置路由器以实现网络访问的灵活性和匿名性。其中&#xff0c;给路由器配置代理IP是一个常见的需求&#xff0c;尤其是在需要绕过地域限制、增强网络安全或进行匿名浏览时。然而&#xff0c;配置过…...

程序化广告行业(70/89):ABTester系统助力落地页优化实践

程序化广告行业&#xff08;70/89&#xff09;&#xff1a;ABTester系统助力落地页优化实践 在程序化广告领域摸爬滚打多年&#xff0c;深知持续学习和知识共享的重要性。写这篇博客&#xff0c;就是希望能和大家一起深入探索程序化广告行业&#xff0c;共同学习、共同进步。今…...

远程监控系统项目里练习

1、项目目标 设备端&#xff1a; &#xff08;1&#xff09;基于stm32mp157开发板&#xff0c;裁剪linux5.10.10&#xff0c;完成ov5640摄像头移植&#xff1b; &#xff08;2&#xff09;完成用户层程序&#xff0c;完成对摄像头的控制及与云端服务的数据交互。 云端&…...

Spring Boot 通过全局配置去除字符串类型参数的前后空格

1、问题 避免前端输入的字符串参数两端包含空格&#xff0c;通过统一处理的方式&#xff0c;trim掉空格 2、实现方式 /*** 去除字符串类型参数的前后空格* author yanlei* since 2022-06-14*/ Configuration AutoConfigureAfter(WebMvcAutoConfiguration.class) public clas…...

设计模式 --- 观察者模式

设计模式 --- 观察者模式 什么是观察者模式观察者模式典型应用 --- C#中的事件使用观察者模式实现事件处理机制 什么是观察者模式 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式&#xff0c;用于在对象之间建立一对多的依赖关系。当一个对象&#x…...

组播网络构建:IGMP、PIM 原理及应用实践

IP组播基础 组播基本架构 组播IP地址 一个组播IP地址并不是表示具体的某台主机&#xff0c;而是一组主机的集合&#xff0c;主机声明加入某组播组即标识自己需要接收目的地址为该组播地址的数据IP组播常见模型分为ASM模型和SSM模型ASM&#xff1a;成员接收任意源组播数据&…...

Java常见的23种设计模式

Java常见的23种设计模式 大家好&#xff0c;我是钢板兽&#xff01; 本文将系统梳理 Java 的设计模式&#xff0c;涵盖创建型、结构型和行为型三大类&#xff0c;结合定义、原理、优点、应用场景、示例代码&#xff0c;帮助你初步了解常见的23种设计模式。 一、设计模式分类…...

兔单B细胞单抗制备服务

1.兔单B细胞技术原理 兔单B细胞技术是近年来新发展的一类快速制备单克隆抗体的技术&#xff0c;是一种通过分离和单克隆化兔子体内的B细胞来制备单一来源的高特异性抗体的方法。基于流式细胞分选技术进行单B细胞单抗制备&#xff0c;利用每个B细胞只含有一个功能性重链可变区D…...

MySQL基础 [六] - 内置函数+复合查询+表的内连和外连

内置函数一般要用select调用 内置函数 日期函数 current_date函数 current_date函数用于获取当前的日期。如下&#xff1a; current_time函数 current_time函数用于获取当前的时间。如下&#xff1a; now函数 now函数用于获取当前的日期时间。如下&#xff1a; date函数 dat…...

nginx路径匹配的优先级

在 Nginx 配置中&#xff0c;当请求 /portal/agent/sse 时&#xff0c;会匹配 location ~* /sse$ 规则&#xff0c;而不是 location /portal。原因如下&#xff1a; 匹配规则解析 location ~* /sse$ ~* 表示 不区分大小写的正则匹配/sse$ 表示以 /sse 结尾的路径匹配结果&#…...

tcp/ip攻击及防范

作为高防工程师&#xff0c;我每天拦截数以万计的恶意流量&#xff0c;其中TCP/IP协议层攻击是最隐蔽、最具破坏性的威胁之一。常见的攻击手法包括&#xff1a; 1. SYN Flood攻击&#xff1a;攻击者发送大量伪造的SYN包&#xff0c;耗尽服务器连接资源&#xff0c;导致正常用…...

2025年3月中国电子学会青少年软件编程(Python)等级考试试卷(一级)答案 + 解析

更多真题在线练习系统&#xff1a;历年真题在线练习系统 一、单选题 1、下列哪个软件不能运行 Python 程序&#xff1f;&#xff08; &#xff09; A、JupyterNotebook B、Pycharm C、原版的Scratch D、IDLE 正确答案&#xff1a;C 答案解析&#xff1a;本题考察的 Pyt…...

TreeMap 核心知识点与面试题解析

TreeMap 核心知识点与面试题解析 一、TreeMap 基础概念 TreeMap 是 Java 集合框架中基于 红黑树&#xff08;Red-Black Tree&#xff09; 实现的 Map&#xff0c;具有以下特点&#xff1a; 有序性&#xff1a;默认按 key 的自然顺序&#xff08;Comparable&#xff09;或自定…...

深入理解 DevOps 与 CI/CD:概念、流程及优势

在当今快速发展的数字化时代,软件开发和交付的速度与质量成为企业在激烈竞争中脱颖而出的关键因素。DevOps 和 CI/CD 作为现代软件开发领域的重要理念和实践,正深刻地改变着软件开发生命周期的运作方式。本文将深入探讨 DevOps 的概念,详细解析 CI/CD 的内涵、管道阶段以及实…...

Flutter BloC 架构入门指南

BLoC (Business Logic Component) 是 Flutter 中一种流行的状态管理架构&#xff0c;它可以帮助你将业务逻辑与 UI 分离&#xff0c;使代码更清晰、可测试性更强。 核心概念 1. BloC 的核心组件 Events&#xff1a;用户交互或系统事件&#xff08;如按钮点击、网络请求完成&…...

OpenHarmony-AI调研

OpenHarmony-AI调研 文章目录 OpenHarmony-AI调研前言一、当前版本部署组件二、AI架构1.mindspore-lite2.ai_engine3.neural_network_runtime4.intelligent_voice_framework5.HDI驱动 三、应用1.命令行以及web运行deepseek-r12.与deepseek通过语音进行交互3.物品识别4.人脸识别…...

zk基础—zk实现分布式功能

1.zk实现数据发布订阅 (1)发布订阅系统一般有推模式和拉模式 推模式&#xff1a;服务端主动将更新的数据发送给所有订阅的客户端。 拉模式&#xff1a;客户端主动发起请求来获取最新数据(定时轮询拉取)。 (2)zk采用了推拉相结合来实现发布订阅 首先客户端需要向服务端注册自己关…...

Tips:用proxy解决前后端分离项目中的跨域问题

在前后端分离项目中&#xff0c;"跨域问题"是浏览器基于同源策略&#xff08;Same-Origin Policy&#xff09;对跨域请求的安全限制。当你的前端&#xff08;如运行在 http://localhost:3000 &#xff09;和后端&#xff08;如运行在 http://localhost:8080 &#…...

JMeterPlugins-Standard-1.4.0 插件详解:安装、功能与使用指南

JMeterPlugins-Standard-1.4.0 是 Apache JMeter&#xff08;一款流行的开源负载和性能测试工具&#xff09;的插件包&#xff0c;它扩展了 JMeter 的功能&#xff0c;提供了更多监听器&#xff08;Listeners&#xff09;、采样器&#xff08;Samplers&#xff09;和辅助组件&a…...

JMeter 中,Token 和 Cookie 的区别及实际应用

在 JMeter 中,Token 和 Cookie 都是用于处理用户会话和身份验证的机制,但它们的 工作原理、存储方式 和 应用场景 有显著区别。以下是详细对比和实际应用指南: 1. 核心区别 特性Token (如 JWT、OAuth)Cookie存储位置通常存储在 HTTP 请求头(如 Authorization: Bearer <t…...

蓝桥杯真题——好数、R格式

目录 蓝桥杯2024年第十五届省赛真题-好数 【模拟题】 题目描述 输入格式 输出格式 样例输入 样例输出 提示 代码1&#xff1a;有两个案例过不了&#xff0c;超时 蓝桥杯2024年第十五届省赛真题-R 格式 【vector容器的使用】 题目描述 输入格式 输出格式 样例输入…...

JavaScript惰性加载优化实例

这是之前的一位朋友的酒桌之谈&#xff0c;他之前负责的一个电商项目&#xff0c;刚刚开发万&#xff0c;首页加载时间特别长&#xff0c;体验很差&#xff0c;所以就开始排查&#xff0c;发现是在首页一次性加载所有js导致的问题&#xff0c;这个问题在自己学习的时候并不明显…...

0_Pytorch中的张量操作

[引言]张量的概念 1.基本概念 张量是一个通用的多维数组&#xff0c;可以表示标量&#xff08;0 维&#xff09;、向量&#xff08;1 维&#xff09;、矩阵&#xff08;2 维&#xff09;以及更高维度的数据。张量是 PyTorch 中的核心数据结构&#xff0c;用于表示和操作数据。…...

Java面试43-常见的限流算法有哪些?

限流算法是一种系统保护策略&#xff0c;主要是避免在流量高峰导致系统被压垮&#xff0c;造成系统不可用的问题。 常见的限流算法有五种&#xff1a; 计数器限流&#xff0c;一般用在单一维度的访问频率限制上&#xff0c;比如短信验证码每隔60s只能发送一次&#xff0c;或者…...

牛客网:树的高度 ← 根节点为 0 号节点

【题目来源】 https://www.nowcoder.com/questionTerminal/4faa2d4849fa4627aa6d32a2e50b5b25 【题目描述】 现在有一棵合法的二叉树&#xff0c;树的节点都是用数字表示&#xff0c;现在给定这棵树上所有的父子关系&#xff0c;求这棵树的高度。 【输入格式】 输入的第一行表…...

Linux:进程程序替换execl

目录 引言 1.单进程版程序替换 2.程序替换原理 3.6种替换函数介绍 3.1 函数返回值 3.2 命名理解 3.3 环境变量参数 引言 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支)&#xff0c;我们所创建的所有的子进程&#xff0c;执行的代码&#x…...

⑩数据中心M-LAG 实战

一、配置指导自己去看今天操作的是M-LAG 基础实验 二、配置代码信息回顾 ### 1、配置 M-LAG 系统 MAC 地址<H3C>system-view[H3C]m-lag system-mac ?H-H-H MAC address2a7a-53ee-0100 Bridge MAC address[H3C]m-lag system-mac### 2、配置 M-LAG 系统编号…...

delphi idtcpserver 搭建tcp ,ssl协议服务端

如果想用indy idtcpserver实现tcp ssl,那么正是你需要的 首先生成证书: 2、windows生成pem证书 - 站着说话不腰疼 - 博客园 有证书后 idtcpserver 用的三个证书, IdServerIOHandlerSSLOpenSSL1.SSLOptions.CertFile = ca.crt IdServerIOHandlerSSLOpenSSL1.SSLOptions.…...

如何实现外观模式?

一、模式理解&#xff08;用快递驿站比喻&#xff09; 想象你网购了5件商品&#xff0c;分别来自不同快递公司。 外观模式就像小区门口的快递驿站&#xff0c;你不需要知道中通怎么分拣、顺丰怎么运输&#xff0c;只要到驿站报取件码就能拿到所有包裹。 在前端开发中&#xf…...

深入解析 Linux 文件系统权限:从基础到高级实践

引言 在 Linux 系统中&#xff0c;文件系统权限是保障数据安全和多用户协作的核心机制。想象这样一个场景&#xff1a; 你的服务器上有多个团队共享项目文件 财务数据必须严格保密&#xff0c;仅允许指定人员访问 开发团队需要共同编辑代码&#xff0c;但禁止随意删除他人文…...

GZ036区块链卷一 EtherStore合约漏洞详解

题目 pragma solidity >0.8.3;contract EtherStore {mapping(address > uint) public balances;function deposit() public payable {balances[msg.sender] msg.value;emit Balance(balances[msg.sender]);}function withdraw() public {uint bal balances[msg.sender…...

医药流通行业批发公司IT运维转型:Prometheus+Grafana监控Spring Boot 3应用实践

一、引言&#xff1a;医药流通行业IT运维挑战与工具换代需求 在医药流通行业批发领域&#xff0c;业务的核心在于供应链的高效运转、订单处理的精准及时以及库存管理的动态平衡。随着互联网医疗的兴起和电商平台的渗透&#xff0c;传统医药批发企业正加速向数字化、智能化转型…...

编程助手fitten code使用说明(超详细)(vscode)

这两年 AI 发展迅猛&#xff0c;作为开发人员&#xff0c;我们总是追求更快、更高效的工作方式&#xff0c;AI 的出现可以说改变了很多人的编程方式。 AI 对我们来说就是一个可靠的编程助手&#xff0c;给我们提供了实时的建议和解决方&#xff0c;无论是快速修复错误、提升代…...

金融大模型

FinGPT 数据集&#xff1a;https://github.com/AI4Finance-Foundation/FinGPT/tree/master/fingpt/FinGPT-v3 FinGPT v3 系列是在新闻和微博情绪分析数据集上使用 LoRA 方法进行微调的LLM&#xff0c;在大多数金融情绪分析数据集上取得了最佳分数。 FinGPT v3.1 使用 chatgl…...

【Pandas】pandas DataFrame infer_objects

Pandas2.2 DataFrame Conversion 方法描述DataFrame.astype(dtype[, copy, errors])用于将 DataFrame 中的数据转换为指定的数据类型DataFrame.convert_dtypes([infer_objects, …])用于将 DataFrame 中的数据类型转换为更合适的类型DataFrame.infer_objects([copy])用于尝试…...

011_异常、泛型和集合框架

异常、泛型和集合框架 异常Java的异常体系异常的作用 自定义异常异常的处理方案异常的两种处理方式 泛型泛型类泛型接口泛型方法、通配符和上下限泛型支持的类型 集合框架集合体系结构Collection Collection集合Collection的遍历方式认识并发修改异常问题解决并发修改异常问题的…...

QTSql全解析:从连接到查询的数据库集成指南

概览 与数据库的有效集成是确保数据管理效率和应用性能的关键&#xff0c;Qt框架就提供了强大的QtSql模块&#xff0c;使得开发者能够轻松地进行数据库操作&#xff0c;包括连接、查询执行以及结果处理等 一、引入QtSql模块 首先&#xff0c;需要在项目中引入QtSql模块&…...

docker快捷打包脚本(ai版)

直接进入主题&#xff1a; 用这个脚本前提是你本地可以拉镜像仓库的镜像&#xff0c;并且在 本地有了&#xff0c;然后将所有的镜像tag写在一个文件中&#xff0c;和下面docker_tags.txt 对应&#xff0c;文件叫什么&#xff0c;脚本里对应改什么&#xff0c;给小白说的 #!/bi…...