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

EasyExcel多线程批量导出数据,动态表头,静态资源访问

1.导入依赖

        <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version></dependency>

2.建立实体

@Data
public class ActResultLogVO implements Serializable {private static final long serialVersionUID = 1L;@ExcelProperty(value = "onlineseqid",index = 0)private String onlineseqid;@ExcelProperty(value = "businessid",index = 1)private String businessid;@ExcelProperty(value = "becifno",index = 2)private String becifno;@ExcelProperty(value = "ivisresult",index = 3)private String ivisresult;@ExcelProperty(value = "createdby",index = 4)private String createdby;@ExcelProperty(value = "createddate",index = 5)private LocalDate createddate;@ExcelProperty(value = "updateby",index = 6)private String updateby;@ExcelProperty(value = "updateddate",index = 7)private LocalDate updateddate;@ExcelProperty(value = "risklevel",index = 8)private String risklevel;/*** 分页开始数量*/private Integer start;/***  分页 size*/private Integer size;
}

3.多线程异步导出

	@Async@Transactionalpublic  void exportExcel(String filePath) {//filePath 文件路径ExcelWriter writer = EasyExcel.write(filePath, ActResultLogVO.class).build();// 根据数据读写速度来调整,一般来说读的逻辑复杂,比较慢,如果读比写快,这里设为1int N = 2;// 大小设置为2就可以,作为缓冲BlockingQueue<List<ActResultLogVO>> queue = new ArrayBlockingQueue<>(2);AtomicInteger start = new AtomicInteger(0);AtomicInteger num = new AtomicInteger(0);AtomicInteger sheet = new AtomicInteger(1);// 分页大小可以适当调整int pageSize = 100000;//开启多个线程分页查数据for (int i = 0; i < N; i++) {executorService.submit(() -> {while (true) {//自增int startNum= start.getAndAdd(pageSize);try {long l = System.currentTimeMillis();logger.info("[多线程,分页查询] 线程:{},开始执行查询:startNum :{},时间:{}",Thread.currentThread().getName(),startNum,l);List<ActResultLogVO> list = selectActResultLogVOPage(startNum, pageSize);logger.info("[多线程,分页查询] 线程:{},执行查询完成 startNum :{} 用时:{}",Thread.currentThread().getName(),startNum,System.currentTimeMillis()-l);if (CollectionUtils.isEmpty(list)) {//读到没数据也要放入空集合queue.put(Collections.EMPTY_LIST);break;}queue.put(list);} catch (Exception e) {//异常情况也要放入空集合,防止写线程无法退出循环try {queue.put(Collections.EMPTY_LIST);} catch (InterruptedException ex) {throw new RuntimeException(ex);}throw new RuntimeException(e);}}});}Future<?> submit = executorService.submit(() -> {int count = 0;while (true) {List<ActResultLogVO> list = null;try {list = queue.take();} catch (InterruptedException e) {Thread.interrupted();}if (CollectionUtils.isEmpty(list)) {count++;// 当获取到两次空集合时,说明已经读完if (count == N) {break;}continue;}if(num.get()>=500000){sheet.getAndAdd(1);num.getAndSet(0);}num.getAndAdd(list.size());long l = System.currentTimeMillis();logger.info("[多线程,写入Excel] 线程:{},开始执行写入:sheet :{},num:{}时间:{}",Thread.currentThread().getName(),sheet.get(),num.get(),l);writer.write(list, EasyExcel.writerSheet("Sheet"+sheet).build());logger.info("[多线程,写入Excel] 线程:{},开始执行写入结束:sheet :{},num:{},时间:{}",Thread.currentThread().getName(),sheet.get(),num.get(),System.currentTimeMillis()-l);}writer.finish();});try {// 阻塞等待完成,异步处理也可以去掉这段代码submit.get();} catch (Exception e) {}}

4.动态表头

 	 @Autowired@Qualifier("excelThreadPool")private ExecutorService executorService;@Async@Transactionalpublic void exportExcel(String filePath,LinkedHashMap<String, DynamicExcelData> nameMap) {// 指定写入的文件ExcelWriter writer = EasyExcel.write(filePath).head(ExcelUtils.getHead(nameMap)).build();// 根据数据读写速度来调整,一般来说读的逻辑复杂,比较慢,如果读比写快,这里设为1int N = 2;// 大小设置为2就可以,作为缓冲BlockingQueue<List<Map<String,Object>>> queue = new ArrayBlockingQueue<>(2);AtomicInteger num = new AtomicInteger(0);AtomicInteger sheet = new AtomicInteger(1);// 分页大小可以适当调整int pageSize = ExcelConstants.SELECT_TO_DB_ROWS_MYBATIS;//开启多个线程分页查数据getData(lvnengAllCardBillVo,queue,pageSize);Future<?> submit = executorService.submit(() -> {int count = 0;while (true) {List<Map<String,Object>> list = null;try {list = queue.take();} catch (InterruptedException e) {Thread.interrupted();}if (CollectionUtils.isEmpty(list)) {count++;// 当获取到两次空集合时,说明已经读完if (count == N) {break;}continue;}if(num.get()>=600000){sheet.getAndAdd(1);num.getAndSet(0);}num.getAndAdd(list.size());List<List<String>> dataList = ExcelUtils.getDataList(nameMap, list);writer.write(dataList, EasyExcel.writerSheet("Sheet"+sheet).build());}writer.finish();});try {// 阻塞等待完成,异步处理也可以去掉这段代码submit.get();} catch (Exception e) {}}
public void getData(ActResultLogVO actResultLogVO,BlockingQueue<List<Map<String,Object>>> queue,int pageSize) {// 根据数据读写速度来调整,一般来说读的逻辑复杂,比较慢,如果读比写快,这里设为1int N = 2;AtomicInteger start = new AtomicInteger(0);for (int i = 0; i < N; i++) {executorService.submit(() -> {while (true) {//自增int startNum = start.getAndAdd(pageSize);List<Map<String, Object>> list = new ArrayList<>();try {ActResultLogVO actResultLogVO1 = DeepCopyUtil.deepCopy(actResultLogVO);actResultLogVO1.setStart(startNum);List<Map<String, Object>> list = selectactResultLogVOPage(actResultLogVO1);if (CollectionUtils.isEmpty(list)) {//读到没数据也要放入空集合queue.put(Collections.EMPTY_LIST);break;}queue.put(list);} catch (Exception e) {//异常情况也要放入空集合,防止写线程无法退出循环try {queue.put(Collections.EMPTY_LIST);} catch (InterruptedException ex) {throw new RuntimeException(ex);}throw new RuntimeException(e);}}});}logger.info("查询数据完成");}
@Configuration
public class ThreadPoolConfig {@Bean("excelThreadPool")public  ExecutorService buildExcelThreadPool() {int cpuNum = Runtime.getRuntime().availableProcessors();BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(1000);ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("excel-pool-%d").build();return new ThreadPoolExecutor(10 * cpuNum, 30 * cpuNum,1, TimeUnit.MINUTES, workQueue, threadFactory);}
}
public class ExcelConstants {public static final Integer PER_SHEET_ROW_COUNT = 100*10000;public static final Integer PER_WRITE_ROW_COUNT = 20*10000;public static final Integer SHEET_WRITE_ROW_COUNT = 50*10000;public static final Integer SELECT_TO_DB_ROWS = 10*10000;public static final Integer SELECT_TO_DB_ROWS_MYBATIS = 5*10000;
}
@Data
public class DynamicExcelData {//列名private String name;//默认值private String defaultValue;public DynamicExcelData(String name, String defaultValue) {this.name = name;this.defaultValue = defaultValue;}
}

5,用到的util

5.1 EasyUtils

public class ExcelUtils {public static void dynamicExportByURL(String filePath,LinkedHashMap<String, DynamicExcelData> nameMap,List<Map<String, Object>> list,String sheetName) throws IOException {//首先判断是否有数据,没有就返回if(CollUtil.isEmpty(list)){return;}//这里的map使用LinkedHashMap,实现字段的顺序功能if(nameMap==null){throw new RuntimeException("请填写好映射表数据");}File file = getFile(filePath);dynamicExportByURL(file,nameMap,list,sheetName);}public static void dynamicExport(HttpServletResponse response,LinkedHashMap<String, DynamicExcelData> nameMap,List<Map<String, Object>> list,String sheetName) throws IOException {//首先判断是否有数据,没有就返回if(CollUtil.isEmpty(list)){return;}//这里的map使用LinkedHashMap,实现字段的顺序功能if(nameMap==null){throw new RuntimeException("请填写好映射表数据");}response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");//使用EasyExcel write进行写出EasyExcel.write(response.getOutputStream()).head(getHead(nameMap)).sheet(sheetName).doWrite(getDataList(nameMap,list));}public static ArrayList<List<String>> getHead(LinkedHashMap<String, DynamicExcelData> nameMap) {//获取表头ArrayList<List<String>> head = new ArrayList<>();for (Map.Entry<String, DynamicExcelData> titleMap : nameMap.entrySet()) {DynamicExcelData data = titleMap.getValue();head.add(Collections.singletonList(data.getName()));}return head;}public static List<List<String>> getDataList(LinkedHashMap<String, DynamicExcelData> nameMap, List<Map<String, Object>> list) {//先初始化一下传入int size = list.size();List<List<String>> dataList = new ArrayList<>();for (int i = 0; i < size; i++) {dataList.add(new ArrayList<>());}//数据重组for (int i = 0; i < list.size(); i++) {Map<String, Object> map = list.get(i);List<String> columns = dataList.get(i);for (Map.Entry<String, DynamicExcelData> sortNameEntry : nameMap.entrySet()) {String key = sortNameEntry.getKey();Object value = map.get(key);columns.add(value != null ? String.valueOf(value) : sortNameEntry.getValue().getDefaultValue());}}return dataList;}public static File getFile(String filePath) throws IOException {File file = new File(filePath);if (!file.exists()) {file.createNewFile();}return file;}public static void dynamicExportByURL(File file,LinkedHashMap<String, DynamicExcelData> nameMap,  List date,String sheetName) {long startTime = 0;ExcelWriter excelWriter = null;try {startTime = System.currentTimeMillis();// 获取 sheet 的个数int sheetNum = getSheetNum(date.size());// 获取每个sheet 写入的次数int writeNumPerSheet = getWriteNumPerSheet();// 最后一个 sheet 写入的数量int writeNumLastSheet = date.size() - (sheetNum - 1) * ExcelConstants.PER_SHEET_ROW_COUNT;// 最后一个 sheet 写入的次数int writeNumPerLastSheet = writeNumLastSheet % ExcelConstants.PER_WRITE_ROW_COUNT == 0 ? writeNumLastSheet / ExcelConstants.PER_WRITE_ROW_COUNT : writeNumLastSheet / ExcelConstants.PER_WRITE_ROW_COUNT + 1;// 指定写入的文件excelWriter = EasyExcel.write(file).head(getHead(nameMap)).build();for (int i = 0; i < sheetNum; i++) {String sheet = sheetName + i;WriteSheet writeSheet = EasyExcel.writerSheet(i, sheet).build();int writeNum = i == sheetNum - 1 ? writeNumPerLastSheet : writeNumPerSheet; // 每个sheet 写入的次数int endEndNum = i == sheetNum - 1 ? date.size() : (i + 1) * ExcelConstants.PER_SHEET_ROW_COUNT; // 每个sheet 最后一次写入的最后行数for (int j = 0; j < writeNum; j++) {long l = System.currentTimeMillis();int startNum = i * ExcelConstants.PER_SHEET_ROW_COUNT + j * ExcelConstants.PER_WRITE_ROW_COUNT;int endNum = j == writeNum - 1 ? endEndNum : i * ExcelConstants.PER_SHEET_ROW_COUNT + (j + 1) * ExcelConstants.PER_WRITE_ROW_COUNT;excelWriter.write(getDataList(nameMap,date.subList(startNum, endNum)), writeSheet);}}} catch (Exception e) {} finally {// 需要放入 finally 中if (excelWriter != null) {excelWriter.finish();}}}public static void writeExcel(String filePath, Class clazz, List date,String sheetName) throws Exception{File file = getFile(filePath);long startTime = System.currentTimeMillis();// 获取 sheet 的个数int sheetNum = getSheetNum(date.size());// 获取每个sheet 写入的次数int writeNumPerSheet = getWriteNumPerSheet();// 最后一个 sheet 写入的数量int writeNumLastSheet = date.size() - (sheetNum - 1) * ExcelConstants.PER_SHEET_ROW_COUNT;// 最后一个 sheet 写入的次数int writeNumPerLastSheet = writeNumLastSheet % ExcelConstants.PER_WRITE_ROW_COUNT == 0 ? writeNumLastSheet / ExcelConstants.PER_WRITE_ROW_COUNT : writeNumLastSheet / ExcelConstants.PER_WRITE_ROW_COUNT + 1;// 指定写入的文件ExcelWriter excelWriter = EasyExcel.write(file, clazz).build();for (int i = 0; i < sheetNum; i++) {String sheet = sheetName + i;WriteSheet writeSheet = EasyExcel.writerSheet(i, sheet).build();int writeNum = i == sheetNum - 1 ? writeNumPerLastSheet : writeNumPerSheet; // 每个sheet 写入的次数int endEndNum = i == sheetNum - 1 ? date.size() : (i + 1) * ExcelConstants.PER_SHEET_ROW_COUNT; // 每个sheet 最后一次写入的最后行数for (int j = 0; j < writeNum; j++) {long l = System.currentTimeMillis();int startNum = i * ExcelConstants.PER_SHEET_ROW_COUNT + j * ExcelConstants.PER_WRITE_ROW_COUNT;int endNum = j == writeNum - 1 ? endEndNum : i * ExcelConstants.PER_SHEET_ROW_COUNT + (j + 1) * ExcelConstants.PER_WRITE_ROW_COUNT;excelWriter.write(date.subList(startNum, endNum), writeSheet);}}// 需要放入 finally 中if (excelWriter != null) {excelWriter.finish();}}public static int getSheetNum(int dateSize){return dateSize % ExcelConstants.PER_SHEET_ROW_COUNT == 0 ? (dateSize / ExcelConstants.PER_SHEET_ROW_COUNT) : (dateSize / ExcelConstants.PER_SHEET_ROW_COUNT + 1);}public static int getWriteNumPerSheet(){return ExcelConstants.PER_SHEET_ROW_COUNT % ExcelConstants.PER_WRITE_ROW_COUNT == 0 ? (ExcelConstants.PER_SHEET_ROW_COUNT / ExcelConstants.PER_WRITE_ROW_COUNT) : (ExcelConstants.PER_SHEET_ROW_COUNT / ExcelConstants.PER_WRITE_ROW_COUNT + 1);}public static  List<String> objectToList(Object obj){ArrayList<String> list = new ArrayList<>();//获取obj类中的所有字段Field[] fields = obj.getClass().getDeclaredFields();//遍历所有属性for (Field field : fields) {try {field.setAccessible(true);list.add(field.get(obj).toString());} catch (IllegalAccessException e) {throw new RuntimeException(e);}}return list;}public static Map<String,Object> objectToMap(Object obj){HashMap<String, Object> map = new HashMap<>();//获取obj类中的所有字段Field[] fields = obj.getClass().getDeclaredFields();//遍历所有属性for (Field field : fields) {try {field.setAccessible(true);map.put(field.getName(),field.get(obj));} catch (IllegalAccessException e) {throw new RuntimeException(e);}}return map;}/*** 通过反射方式将头部作为公共部分进行设置*/public static List<List<String>> setTitles(Class clazz) {List<List<String>> titles = new ArrayList<List<String>>();for (Field declaredField : clazz.getDeclaredFields()) {ExcelProperty annotation = declaredField.getAnnotation(ExcelProperty.class);if (null != annotation) {titles.add(Arrays.asList(annotation.value()));}}return titles;}
}

5.2 深拷贝

public class DeepCopyUtil {public static <T extends Serializable> T deepCopy(T object) {try {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);objectOutputStream.writeObject(object);ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);return (T) objectInputStream.readObject();} catch (IOException | ClassNotFoundException e) {throw new RuntimeException(e);}}
}

配置静态资源访问

@Configuration
public class MyStaticConfig extends WebMvcConfigurationSupport {@Value("${download.url}")private String fileDir;@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/uploads/**").addResourceLocations("classpath:/META-INF/resources/", "classpath:/resources/","classpath:/static/", "classpath:/public/","file:"+fileDir);}
}

相关文章:

EasyExcel多线程批量导出数据,动态表头,静态资源访问

1.导入依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version></dependency>2.建立实体 Data public class ActResultLogVO implements Serializable {private static…...

树莓派界面改成中文

安装完树莓派系统(Raspberry Pi OS with Desktop)&#xff0c;第一次启动时&#xff0c;时会有如下面二个图所示&#xff0c;让你选择区域时区和语言。 树莓派默认的语言为英文&#xff0c;如果你在安装时没有选择的话&#xff0c;默认的区域为英国&#xff0c;语言为英国英文&…...

软件工程期末复习

● 用例&#xff1a;借书 ●参与者&#xff1a;管理员,借阅者 ●操作流&#xff1a; ① 管理员进入图书借阅界面&#xff0c;用例开始。 ② 系统要求输入借阅者的借书证编码。 ③系统检验借书证编码,如果正确,则显示借阅者的信息。 A1&#xff1a;借书证编码有错。 A2: 如果该借…...

【linux】select实现定时器

/*秒级定时器*/ void seconds_sleep(unsigned long seconds) {if(seconds 0) return;struct timeval tv;tv.tv_secseconds;tv.tv_usec0;int err;do{errselect(0,NULL,NULL,NULL,&tv);}while(err<0 && errnoEINTR); }/*毫秒定时器*/void milliseconds_slee…...

Android 13 - Media框架(28)- MediaCodec(三)

上一节我们了解到 ACodec 执行完 start 流程后&#xff0c;会把所有的 input buffer 都提交给 MediaCodec 层&#xff0c;MediaCodec 是如何处理传上来的 buffer 呢&#xff1f;这一节我们就来了解一下这部分内容。 1、ACodecBufferChannel::fillThisBuffer ACodec 通过调用 A…...

Azure 学习总结

文章目录 1. Azure Function1.1 Azure Function 概念1.2 Azure Function 实现原理1.3 Azure Function 本地调试1.4 Azure Function 云部署 2. Azure API Managment 概念 以及使用2.1 Azure API 概念2.2 Azure API 基本使用 3. Service Bus 应用场景及相关特性3.1 Service Bus 基…...

数据库是否可以直接作为数据仓库的数据源

在数据仓库使用数据时&#xff0c;我们是否可以直接将数据库作为数据源&#xff1f;如果使用了&#xff0c;会存在哪些问题&#xff1f; 数据库中存储的是业务数据&#xff0c;存储方式是行式存储&#xff1b;而数据仓库中数据是以列式存储的&#xff1b;如果数据仓库要想使用…...

IntelliJ IDE 插件开发 | (四)开发一个时间管理大师插件

系列文章 IntelliJ IDE 插件开发 |&#xff08;一&#xff09;快速入门IntelliJ IDE 插件开发 |&#xff08;二&#xff09;UI 界面与数据持久化IntelliJ IDE 插件开发 |&#xff08;三&#xff09;消息通知与事件监听IntelliJ IDE 插件开发 |&#xff08;四&#xff09;开发一…...

【ChatGPT 默认强化学习策略】PPO 近端策略优化算法

PPO 近端策略优化算法 PPO 概率比率裁剪 演员-评论家算法演员-评论家算法&#xff1a;多智能体强化学习核心框架概率比率裁剪&#xff1a;逐步进行变化的方法PPO 目标函数的设计重要性采样KL散度 PPO 概率比率裁剪 演员-评论家算法 论文链接&#xff1a;https://arxiv.org…...

【银行测试】金融银行-理财项目面试/分析总结(二)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 银行理财相关的项…...

张江智荟毁约offer

毕业8年后&#xff0c;找工作被国企歧视学历&#xff01;已经收到了offer&#xff0c;在入职前一周被通知要撤回offer&#xff0c;拒绝录用&#xff0c;理由居然是他们只要本科211以上的人 这是我今天&#xff08;2023-12-26&#xff09;亲身经历的事&#xff0c;听说过面试前…...

ubuntu 系统终端颜色设置

1 开启终端颜色 # 第一步&#xff1a; 在 ~/.bashrc 中设置 force_color_promptyes# 第二步&#xff1a; 执行 source ~/.bashrc2 对于精减的 .bashrc 在 ~/.bashrc 中添加以下内容&#xff0c;再执行 source ~/.bashrc &#xff1a; # uncomment for a colored prompt, if…...

【Vue】class与style绑定

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…...

大厂前端面试题总结(百度、字节跳动、腾讯、小米.....),附上热乎面试经验!

先简单介绍下自己&#xff0c;我“平平无奇小天才”一枚&#xff0c;毕业于南方普通985普通学生&#xff0c;有幸去百度、字节面试&#xff0c;感觉大公司就是不一样&#xff0c;印象最深的是字节&#xff0c;所以有必要总结一下面试经验&#xff0c;以及面试中遇到的一些问题&…...

EXPLORING DIFFUSION MODELS FOR UNSUPERVISED VIDEO ANOMALY DETECTION 论文阅读

EXPLORING DIFFUSION MODELS FOR UNSUPERVISED VIDEO ANOMALY DETECTION 论文阅读 ABSTRACT1. INTRODUCTION2. RELATEDWORK3. METHOD4. EXPERIMENTAL ANALYSIS AND RESULTS4.1. Comparisons with State-Of-The-Art (SOTA)4.2. Diffusion Model Analysis4.3. Qualitative Result…...

当 ML 遇到 DevOps:如何理解 MLOps

近年来&#xff0c;人工智能 &#xff08;AI&#xff09; 和机器学习 &#xff08;ML&#xff09; 已经席卷全球&#xff0c;几乎成为任何行业的重要组成部分&#xff0c;从零售和娱乐到医疗保健和银行业。这些技术能够通过分析大量数据实现运营自动化、降低成本和促进决策&…...

vue+element+springboot实现多张图片上传

1.需求说明 2.实现思路 3.el-upload组件主要属性说明 4.前端传递MultipartFile数组与服务端接收说明 5.完整代码 1.需求说明 动态模块新增添加动态功能,支持多张图片上传.实现过程中对el-upload组件不是很熟悉,踩了很多坑,当然也参考过别的文章,发现处理很…...

react使用useState更新数组失败

失败案例&#xff1a; const [addBox, setAddBox] useState([])const itemAdd (item) >{addBox.push(item);setAddBox(addBox)console.log(addBox,点击添加按钮)} 原因&#xff1a;react的useState hook监听的是浅监听 在 React 中&#xff0c;使用 useState Hook 来更新…...

《LIO-SAM阅读笔记》3.后端优化

前言&#xff1a; LIO-SAM后端优化部分写在了mapOptimization.cpp文件中&#xff0c;本部分主要进行了激光帧的scan-to-map匹配&#xff0c;回环检测以及关键帧的因子图优化。本部分主要有两个环节同步进行&#xff0c;一个单独开辟了回环检测线程&#xff0c;另外一个是lidar…...

mac下jd-gui提示没有找到合适的jdk版本

mac下jd-gui提示jdk有问题 背景解决看一下是不是真有问题了方法一&#xff1a;修改启动脚本方法二&#xff1a;设置launchd环境变量 扩展动态切jdk脚本(.bash_profile) 背景 配置了动态jdk后&#xff0c;再次使用JD-GUI提示没有找到合适的jdk版本。 解决 看一下是不是真有问题…...

PS4游戏存档管理终极指南:如何使用Apollo工具轻松备份和修改游戏进度

PS4游戏存档管理终极指南&#xff1a;如何使用Apollo工具轻松备份和修改游戏进度 【免费下载链接】apollo-ps4 Apollo Save Tool (PS4) 项目地址: https://gitcode.com/gh_mirrors/ap/apollo-ps4 在PlayStation 4游戏体验中&#xff0c;游戏存档管理一直是个让玩家头疼的…...

OpenClaw 2.6.4 一键部署教程|零代码零基础无需命令快速上手

OpenClaw 是一款可以在本地运行的智能操作工具&#xff0c;能够通过自然语言指令完成电脑自动化操作&#xff0c;无需复杂配置即可快速使用。本文为 Windows 10/11 64 位系统提供完整的一键部署流程&#xff0c;帮助用户快速搭建属于自己的本地智能工具。 适配系统&#xff1a…...

3PEAK思瑞浦 TPA2772-VS1R MSOP8 运算放大器

特性 供电电压:3V至36V 偏移电压:在25C时最大3.5mV 轨到轨输入和输出 带宽:4.6 MHz 噪声容限:-良好&#xff0c;THD0.0008% 低噪声:1kHz时53nV/vHz 零交叉输入: -优异的总谐波失真加噪声:0.0008%...

VS Code图表神器:零配置用代码画UML、流程图与架构图

1. 项目概述&#xff1a;在VS Code里优雅地“画”图作为一名长期在技术文档、架构设计和日常笔记中与图表打交道的老兵&#xff0c;我深知一个痛点&#xff1a;从想法到一张清晰可用的图表&#xff0c;中间往往隔着“安装Java环境”、“配置GraphViz路径”、“折腾渲染引擎”等…...

从手忙脚乱到智能掌控:League-Toolkit如何解决你的英雄联盟痛点

从手忙脚乱到智能掌控&#xff1a;League-Toolkit如何解决你的英雄联盟痛点 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power &#x1f680;. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 你是否曾经在极地大…...

uni-app iOS后台运行 uni-app App如何实现后台定位或音乐播放

iOS上uni.startBackgroundTask基本无效&#xff0c;仅音频播放、定位更新、后台数据刷新三类能力合规&#xff1b;后台定位需manifest声明原生权限地理围栏事件&#xff1b;无声音频保活须onLaunch配置AudioSession并延迟播放。uni.startBackgroundTask 在 iOS 上基本无效&…...

从STM32到华大HC32F460:手把手移植USB HOST MSC + FatFs R0.13c(含源码对比与避坑指南)

从STM32到华大HC32F460&#xff1a;USB HOST MSC与FatFs移植实战全解析 1. 迁移背景与核心挑战 对于长期使用STM32的嵌入式开发者而言&#xff0c;切换到华大半导体HC32F460系列MCU既是一次技术升级&#xff0c;也面临实际移植的挑战。USB HOST MSC&#xff08;Mass Storage Cl…...

从荧光灯到充电器:剖析MJE13001高压小功率三极管的实战选型与参数验证

1. MJE13001三极管的前世今生 第一次见到MJE13001这颗三极管是在修理一台老式荧光灯电子镇流器时。当时电路板上那颗黑乎乎的小元件已经烧得发黄&#xff0c;但依稀能看到"13001"的标识。拆下来用万用表测量发现CE结已经击穿&#xff0c;换上新的MJE13001后&#xf…...

Linux桌面便签终极方案:Sticky让你的灵感永不丢失

Linux桌面便签终极方案&#xff1a;Sticky让你的灵感永不丢失 【免费下载链接】sticky A sticky notes app for the linux desktop 项目地址: https://gitcode.com/gh_mirrors/stic/sticky 在Linux桌面上高效管理零散信息一直是许多用户的痛点。Sticky作为一款专为Linux…...

蓝叠模拟器抓包难题?用Proxifier+ Fiddler搞定HTTPS请求(保姆级图文教程)

蓝叠模拟器HTTPS抓包实战&#xff1a;Proxifier与Fiddler深度配置指南 在移动应用开发与安全测试领域&#xff0c;抓包分析是必不可少的技能。然而当遇到蓝叠模拟器这类特殊环境时&#xff0c;许多开发者发现常规的代理设置方法完全失效——因为蓝叠根本没有提供网络配置界面。…...