若依-导出后端解析
针对若依框架微服务版本学习
若依导入导出功能的具体使用详见:后台手册 | RuoYi
1.导出逻辑:
导出文件的逻辑是先创建一个临时文件,等待前端请求下载结束后马上删除这个临时文件。但是有些下载插件,例如迅雷(他们是二次下载),这个时候文件已经删除,会导致异常,找不到文件。可强制把所有的导出都改成流的形式返回给前端,不采用临时文件的方法,具体方法后台手册都有(目前下载的代码为流的形式)
2.代码详解
export 导出的入口函数
1.controller层
调用userService.selectUserList(user)方法查询数据,util.exportExcel()方法以流的形式返回前端文件
@Log(title = "用户管理", businessType = BusinessType.EXPORT)@RequiresPermissions("system:user:export")@PostMapping("/export")public void export(HttpServletResponse response, SysUser user){List<SysUser> list = userService.selectUserList(user);
// 创建 ExcelUtil<SysUser>对象,入参为 SysUser.classExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);util.exportExcel(response, list, "用户数据");}
2.调用ExcelUtil类
/*** 对list数据源将其里面的数据导入到excel表单** @param response 返回数据* @param list 导出数据集合* @param sheetName 工作表的名称* @param title 标题* @return 结果*/public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title){
//告诉浏览器或客户端,响应的内容是一个 Excel 文件(XLSX 格式)通常用于文件下载response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//设置 HTTP 响应的字符编码为 UTF-8response.setCharacterEncoding("utf-8");
//调用init方法对数据处理this.init(list, sheetName, title, Type.EXPORT);
//对list数据源将其里面的数据导入到excel表单exportExcel(response);}
1.init方法
public void init(List<T> list, String sheetName, String title, Type type){
// 需要导出的数据交给listif (list == null){list = new ArrayList<T>();}this.list = list;
// 生成execl的sheet名称this.sheetName = sheetName;
// 类型(0:导出导入;1:仅导出;2:仅导入)this.type = type;
//赋值标题this.title = title;
// 主要完成对 List<Object[]> fields 属性的赋值。createExcelField();
// 创建一个 Workbook 工作簿对象 createWorkbook();
//创建excel第一行标题createTitle();//创建对象的子列表名称createSubHead();}
1.createExcelField();
private void createExcelField(){//获取字段注解信息this.fields = getFields();//通过 Java 的 Stream API 对 fields 进行排序this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());//根据注解获取最大行高this.maxHeight = getRowHeight();}/*** 获取字段注解信息*/public List<Object[]> getFields(){List<Object[]> fields = new ArrayList<Object[]>();List<Field> tempFields = new ArrayList<>();//获得传入实体类的父类的所有声明字段tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));//获得传入实体类所有声明字段tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));//是否需要自定义显示属性列showColumn设置,详见官网文档if (StringUtils.isNotEmpty(includeFields)){//遍历临时字段集合for (Field field : tempFields){//判断字段是否在自定义显示属性列中//判断字段是否有@Excels注解if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class)){// 添加字段信息addField(fields, field);}}}//hideColumn()自定义隐藏Excel中列属性else if (StringUtils.isNotEmpty(excludeFields)){for (Field field : tempFields){if (!ArrayUtils.contains(this.excludeFields, field.getName())){addField(fields, field);}}}else{for (Field field : tempFields){addField(fields, field);}}return fields;}/*** 添加字段信息*/public void addField(List<Object[]> fields, Field field){// 单注解if (field.isAnnotationPresent(Excel.class)){//获得注解实例Excel attr = field.getAnnotation(Excel.class);if (attr != null && (attr.type() == Type.ALL || attr.type() == type)){//创建一个包含两个元素的数组,其中数组的类型是 Object,元素类型会根据它们的实际类型而定fields.add(new Object[] { field, attr });}//判断field的类型是否是collection集合类型if (Collection.class.isAssignableFrom(field.getType())){//获得对象的子列表方法subMethod = getSubMethod(field.getName(), clazz);// getGenericType()方法获取某个字段的泛型类型的方法ParameterizedType pt = (ParameterizedType) field.getGenericType();//getActualTypeArguments()方法从一个泛型类型中获取实际的类型参数,并将其转换为 Class<?> 类型Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];//通过FieldUtils.getFieldsListWithAnnotationf()方法中反射,找到类subClass中所有带有Excel注解的字段,并将它们存储在 subFields 变量this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);}}// 多注解if (field.isAnnotationPresent(Excels.class)){Excels attrs = field.getAnnotation(Excels.class);Excel[] excels = attrs.value();for (Excel attr : excels){if (StringUtils.isNotEmpty(includeFields)){if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr())&& (attr != null && (attr.type() == Type.ALL || attr.type() == type))){fields.add(new Object[] { field, attr });}}else{if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())&& (attr != null && (attr.type() == Type.ALL || attr.type() == type))){fields.add(new Object[] { field, attr });}}}}}/*** 获取对象的子列表方法* * @param name 名称* @param pojoClass 类对象* @return 子列表方法**///通过字段名(name)获取给定类(pojoClass)的 getter 方法。// 这个方法根据字段名生成对应的 getter 方法名称,然后使用反射来查找该方法public Method getSubMethod(String name, Class<?> pojoClass){//将字段名 name 转换为标准的 getter 方法名StringBuffer getMethodName = new StringBuffer("get");//将字段的第一个字母转为大写getMethodName.append(name.substring(0, 1).toUpperCase());//提取 name 字符串从索引位置 1 开始到字符串结束的部分getMethodName.append(name.substring(1));Method method = null;try{//pojoClass.getMethod() 方法通过反射查找指定的方法。// getMethodName.toString() 返回的是动态生成的 getter 方法名//new Class[] {} 表示该方法不接受任何参数(即没有输入参数)method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});}catch (Exception e){log.error("获取对象异常{}", e.getMessage());}return method;}
1.clazz.getSuperclass().getDeclaredFields()
clazz:是一个 Class 类型的对象,它表示一个 Java 类。
getSuperclass():是 Class 类中的方法,返回该类的父类(即继承自哪个类)。如果该类没有父类(例如 Object 类),则返回 null。
getDeclaredFields():是 Class 类中的方法,返回该类所有声明的字段,包括私有字段和保护字段等(不包括继承的字段)。
例如:Dog类继承Animal类
clazz.getSuperclass() 获取的是 Dog 类的父类 Animal 类。
getDeclaredFields() 获取了 Animal 类中声明的字段(name、age 和 species),它们的访问修饰符分别是 private、protected 和 public。
getDeclaredFields() 不会返回父类继承的字段,如果需要获取父类的字段(包括继承的),可以使用 getFields()。
getDeclaredFields() 回的是类中所有声明的字段,包括 private、protected、public 和默认访问权限(包私有)的字段。Java的private字段访问权限是受保护的,即使反射获取到私有字段,也无法直接访问它,需要使用 setAccessible(true) 来允许访问该字段
2.public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
ava 反射 API 中的方法,用于检查某个字段是否被特定的注解所标注。它属于 java.lang.reflect.Field 类。通过该方法,你可以判断某个字段是否使用了某个注解
对于反射操作非常有用,尤其是在需要处理动态注解或者特定配置时
3.public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
field.getAnnotation 是 Java 反射 API 中 java.lang.reflect.Field 类的一个方法,用于获取指定字段上的特定注解实例。与 isAnnotationPresent 方法不同,getAnnotation 返回注解的实例,如果字段上没有该注解,则返回 null。
4.public boolean isAssignableFrom(Class<?> cls)
Java 中 Class 类的一个方法,用于判断某个类或接口的对象是否可以赋值给另一个类或接口的变量。它在反射或类型检查的场景中非常常见。
检查当前类是否可以接受传入类的实例(即目标类的对象能否赋值给当前类的变量)
参数:
cls:要与当前类进行比较的类或接口的 Class 对象。
返回值:
如果当前类可以接受 cls 类型的实例(即 cls 类型的对象可以赋值给当前类的引用变量),则返回 true。
否则,返回 false。用于在运行时进行类型兼容性检查的工具,特别适用于需要动态判断类型关系的情况
类型检查:检查某个类或接口是否可以赋值给另一种类型的变量。
反射:在使用反射时,可能需要验证某个对象是否可以赋给特定类型的变量。
动态类型检查:在运行时检查一个对象能否安全地被强制转换为另一类型,避免出现 ClassCastException报错。
5.ParameterizedType pt = (ParameterizedType) field.getGenericType();
getGenericType() 是用于获取某个字段(Field 对象)的泛型类型的方法。返回一个 Type 对象
常见的返回类型:
原始类型: 如果字段没有泛型,getGenericType() 返回的 Type 是该字段的原始类型(例如 int, String 等)。
ParameterizedType: 如果字段的类型是一个带有泛型的类型(如 List<String>),getGenericType() 返回的是 ParameterizedType,它表示该类型的具体泛型参数。
GenericArrayType: 如果字段是泛型数组类型(如 T[] 或 List<String>[]),则返回 GenericArrayType。ParameterizedType:ParameterizedType 是 Type 接口的一个实现,表示带有类型参数的泛型类型
2.createWorkbook()
/*** 创建一个工作簿*/public void createWorkbook(){// 创建一个SXSSFWorkbook工作簿,最大行数为500this.wb = new SXSSFWorkbook(500);// 在工作簿中创建一个工作表(Sheet)this.sheet = wb.createSheet();// 设置工作表的名称wb.setSheetName(0, sheetName);// 创建样式this.styles = createStyles(wb);}
1.SXSSFWorkbook类
SXSSFWorkbook
是Apache POI
库中的一个类,专门用于处理大型 Excel 文件。它支持在内存中流式写入数据,而不是将整个工作簿保存在内存中,因此可以处理非常大的文件,而不容易导致内存溢出。采用“滚动式写入”技术,将数据按需写入磁盘500
作为构造函数的参数表示在内存中同时保留的最大行数。在这个例子中,它设置每次最多将 500 行加载到内存中,超出 500 行的数据将被写入磁盘。
3.createTitle()
/*** 创建excel第一行标题*/public void createTitle(){if (StringUtils.isNotEmpty(title)){//计算标题行的最后一列的列号,默认是 fields 列表的大小减去 1int titleLastCol = this.fields.size() - 1;//判断是否有对象的子属性列表if (isSubList()){// 如果有子属性列表,标题的最后一列索引要加上子属性的大小titleLastCol = titleLastCol + subFields.size() - 1;}//创建一个新的行,作为标题行Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);// 设置标题行的高度为30磅titleRow.setHeightInPoints(30);//在标题行的第一个单元格(列索引为 0)创建一个单元格对象。这是标题文本所在的单元格Cell titleCell = titleRow.createCell(0);//设置标题单元格的样式titleCell.setCellStyle(styles.get("title"));//设置标题单元格的内容为 titletitleCell.setCellValue(title);//合并单元格:通过 sheet.addMergedRegion() 方法合并标题行的单元格sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol));}}
4.createSubHead()
/*** 创建对象的子列表名称*/public void createSubHead(){if (isSubList()){//创建一个新行,作为子表头。rownum 是当前的行号,表示标题行之后的行Row subRow = sheet.createRow(rownum);int column = 0;//计算子字段的大小int subFieldSize = subFields != null ? subFields.size() : 0;//遍历fields数组。每一项包含一个 Field 对象和一个 Excel 注解对象for (Object[] objects : fields){//获取字段对象Field field = (Field) objects[0];//获取与该字段相关的Excel注解,通常用于指定字段如何映射到Excel表格的列,比如列名、颜色等。Excel attr = (Excel) objects[1];//检查当前字段是否为 Collection 类型(如 List, Set 等)if (Collection.class.isAssignableFrom(field.getType())){//为子表头行的当前列创建一个单元格Cell cell = subRow.createCell(column);//将 Excel 注解中的 name 值设置为单元格的内容cell.setCellValue(attr.name());//设置单元格样式cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));//如果子字段的数量大于 1,意味着该字段需要跨越多个列,因此需要合并单元格if (subFieldSize > 1){//创建一个单元格范围对象CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);//将合并区域添加到表格中sheet.addMergedRegion(cellAddress);}//更新列索引,跳过已合并的子字段列column += subFieldSize;}else{Cell cell = subRow.createCell(column++);cell.setCellValue(attr.name());cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));}}rownum++;}}
2.exportExcel(HttpServletResponse response)
/*** 对list数据源将其里面的数据导入到excel表单* * @return 结果*/public void exportExcel(HttpServletResponse response){try{writeSheet();//将数据写入Excel表单//将工作簿写入HttpServletResponse输出流,以便客户端下载wb.write(response.getOutputStream());}catch (Exception e){log.error("导出Excel异常{}", e.getMessage());}finally{IOUtils.closeQuietly(wb);}}/*** 创建写入数据到Sheet*/public void writeSheet(){// 取出一共有多少个sheet.//Math.ceil() 计算总页数,并确保至少有一个工作表(即 Math.max(1, ...))//list.size() 是数据列表的大小,sheetSize 是每个工作表的最大行数。int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));for (int index = 0; index < sheetNo; index++){// 创建新的工作表createSheet(sheetNo, index);// 产生一行Row row = sheet.createRow(rownum);// 初始化列索引int column = 0;// 写入各个字段的列头名称for (Object[] os : fields){Field field = (Field) os[0]; // 获取字段对象Excel excel = (Excel) os[1]; // 获取Excel注解if (Collection.class.isAssignableFrom(field.getType())){for (Field subField : subFields){// 获取子字段的Excel注解Excel subExcel = subField.getAnnotation(Excel.class);// 创建子字段表头单元格this.createHeadCell(subExcel, row, column++);}}else // 如果字段不是集合类型{// 创建普通字段的表头单元格this.createHeadCell(excel, row, column++);}}//判断type类型是导出if (Type.EXPORT.equals(type)){// 填充数据到Excel行fillExcelData(index, row);// 添加统计行addStatisticsRow();}}}/*** 填充excel数据* * @param index 序号* @param row 单元格行*///@SuppressWarnings 注解用于抑制编译器产生的警告信息//unchecked 消除 "类型不安全" 警告@SuppressWarnings("unchecked")public void fillExcelData(int index, Row row){//根据当前工作表的索引和每个工作表的最大行数,确定当前工作表需要填充的数据范围。int startNo = index * sheetSize;int endNo = Math.min(startNo + sheetSize, list.size());int currentRowNum = rownum + 1; // 从标题行后开始//遍历数据列表并填充 Excel 行for (int i = startNo; i < endNo; i++){row = sheet.createRow(currentRowNum);T vo = (T) list.get(i);int column = 0;//获取子列表最大数int maxSubListSize = getCurrentMaxSubListSize(vo);for (Object[] os : fields){Field field = (Field) os[0];Excel excel = (Excel) os[1];if (Collection.class.isAssignableFrom(field.getType())){try{//如果字段是集合类型(如 List 或 Set),首先通过 getTargetValue() 方法获取该字段的值(即集合对象)Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);//如果集合不为空,遍历集合中的每个元素 subVo(即子对象),并为每个子对象创建一个子行 subRowif (subList != null && !subList.isEmpty()){int subIndex = 0;for (Object subVo : subList){Row subRow = sheet.getRow(currentRowNum + subIndex);if (subRow == null){subRow = sheet.createRow(currentRowNum + subIndex);}//在子行中,遍历子字段 subFields,为每个子字段创建一个单元格。int subColumn = column;for (Field subField : subFields){Excel subExcel = subField.getAnnotation(Excel.class);//调用 addCell() 方法填充每个子字段的值到 Excel 单元格中addCell(subExcel, subRow, (T) subVo, subField, subColumn++);}subIndex++;}//column 变量在处理完一个集合字段后增加,跳到下一个字段的位置column += subFields.size();}}catch (Exception e){log.error("填充集合数据失败", e);}}else{// 创建单元格并设置值addCell(excel, row, vo, field, column);if (maxSubListSize > 1 && excel.needMerge()){//如果该字段需要合并单元格(excel.needMerge() 返回 true),并且该字段有多个子集合项(maxSubListSize > 1),// 则通过 sheet.addMergedRegion() 方法合并相应的单元格。sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column));}column++;}}//更新当前行号currentRowNum += maxSubListSize;}}
总结:以上是若依导出功能的关键代码,理解的可能不太全面,仅供个人参考
相关文章:
若依-导出后端解析
针对若依框架微服务版本学习 若依导入导出功能的具体使用详见:后台手册 | RuoYi 1.导出逻辑: 导出文件的逻辑是先创建一个临时文件,等待前端请求下载结束后马上删除这个临时文件。但是有些下载插件,例如迅雷(他们是二…...
【QT5 Widgets示例】记事本:(二)界面设计
文章目录 记事本:(二)界面设计设置窗口标题和图标创建菜单工具栏创建文本框 记事本:(二)界面设计 设置窗口标题和图标 标题 点击窗口,修改windowTitle项 图标 点击windowIcon 倒三角…...
MPPT与PWM充电原理及区别详解
MPPT(最大功率点跟踪)和PWM(脉宽调制)是太阳能充电控制器中常用的两种技术,它们在原理、效率和适用场景上有显著区别。以下是两者的详细对比: 1. 工作原理 PWM(脉宽调制) 核心机制…...
K8S 集群搭建——cri-dockerd版
目录 一、工作准备 1.配置主机名 2.配置hosts解析 3.配置免密登录(只需要在master上操作) 4.时间同步(每台节点都要做,必做,否则可能会因为时间不同步导致集群初始化失败) 5.关闭系统防火墙 6.配置…...
使用express创建服务器保存数据到mysql
创建数据库和表结构 CREATE DATABASE collect;USE collect;CREATE TABLE info (id int(11) NOT NULL AUTO_INCREMENT,create_date bigint(20) DEFAULT NULL COMMENT 时间,type varchar(20) DEFAULT NULL COMMENT 数据分类,text_value text COMMENT 内容,PRIMARY KEY (id) ) EN…...
ubuntu-学习笔记-nginx+php
nginxphp nginx下载nginx配置nginx.conf php其他 记录一下在ubuntu中nginxphp部署tp项目 nginx nginx就是正常下载 下载nginx sudo apt-get install nginx tp项目版本是3.2,通过设置路由,以域名/api.php/控制器/xxx的格式进行api的调用,文…...
打造智能聊天体验:前端集成 DeepSeek AI 助你快速上手
DeepSeek AI 聊天助手集成指南 先看完整效果: PixPin_2025-02-19_09-15-59 效果图: 目录 项目概述功能特点环境准备项目结构组件详解 ChatContainerChatInputMessageBubbleTypeWriter 核心代码示例使用指南常见问题 项目概述 基于 Vue 3 TypeScrip…...
github生成badges的方法
在Github页面上生成类似下面这样的badge的方法 你可以通过以下步骤在GitHub个人主页的README中创建类似的技术栈徽章: 一、使用 Shields.io 生成徽章 Shields.io 是一个开源徽章生成工具,支持自定义文本、颜色、图标等参数。 1. 基础模板 https://…...
vulnhub靶场渗透之SickOs1.2渗透教程,计划任务提权、chkrootkit提权
vulnhub靶场渗透之SickOs1.2渗透教程,计划任务提权、chkrootkit提权 一、信息收集 1、首先拿到靶场先扫一下ip 2025.3.7 AM 8:36 arp-scan -l 扫描同网段 nmap -sP 192.168.66.24/02、指纹扫描 nmap -sS -sV 192.168.66.130 指纹扫描PORT STATE S…...
Ubuntu系统部署.NET 8网站项目
一、使用XShell连接 Ubuntu系统初次连接时默认的用户名为:ubuntu,使用此用户名与系统登录密码进行连接。 登录成功效果如下图: 二、root用户登录 linux下有超级用户(root)和普通用户,普通用户不能直接操…...
CI/CD—Jenkins配置一次完整的jar自动化发布流程
背景: 实现设想: 要创建自动化发布,需要准备一台测试服务器提前安装好java运行所需的环境,JDK版本最好和Windows开发机器上的版本一致,在Jenkins上配置将构建好的jar上传到测试服务器上,测试服务器自动启动…...
【Academy】Web 缓存欺骗 ------ Web cache deception
Web 缓存欺骗 ------ Web cache deception 1. 概述2. Web 缓存2.1 缓存键2.2 缓存规则 3. 构建 Web 缓存欺骗攻击3.1 使用缓存破坏器3.2 检测缓存的响应 4. 利用静态扩展缓存规则4.1 路径映射差异4.2 利用路径映射差异4.3 分隔符差异4.4 利用分隔符差异4.5 分隔符解码差异4.6 利…...
MATLAB表格Table与时间序列Timetable的高效操作方法
MATLAB中的表格(Table) 和 时间序列(Timetable) 是处理结构化数据和时间相关数据的核心工具。以下从基础操作到高级技巧,分步骤详解其使用方法。 一、创建与基础操作 1. 表格(Table)的创建与访…...
【leetcode hot 100 21】合并两个有序链表
解法一:新建一个链表存放有序的合并链表。当list1和list2至少有一个非空时,返回非空的;否则找出两个链表的最小值作为新链表的头,然后依次比较两链表,每次都先插入小的值。 /*** Definition for singly-linked list.*…...
本地部署 OpenManus 保姆级教程(Windows 版)
一、环境搭建 我的电脑是Windows 10版本,其他的没尝试,如果大家系统和我的不一致,请自行判断,基本上没什么大的出入啊。 openManus的Git地址:https://github.com/mannaandpoem/OpenManus 根据官网的两种安装推荐方式如…...
20250310:OpenCV mat对象与base64互转
代码: https://github.com/ReneNyffenegger/cpp-base64 指南:https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp/ 实操:...
WPS的付费功能,这款软件可完美平替
因为作者有工作上的需求加上WPS使用批量提取图片需要会员,所以自己使用cursor制作了一个从excel中提取图片的工具。 支持提取Excel中的浮动图片和根据图片链接来下载图片。 Excel Image Extractor Excel图片提取工具 软件的功能非常强大,支持提取Excel中…...
L1-088 静静的推荐
L1-088 静静的推荐 - 团体程序设计天梯赛-练习集 (pintia.cn) 题解 这里代码很简单,但是主要是循环里面的内容很难理解,下面是关于循环里面的内容理解: 这里 n 10 表示有 10 个学生,k 2 表示企业接受 2 批次的推荐名单&#…...
NS3学习——运行自定义拥塞控制算法步骤
目录 一、添加优化后的代码文件 二、更改CMakeLists文件中内容 三、重新配置和编译ns-3 四、常见问题 目的:想在tcp拥塞控制算法的基础上进行优化改进,之后在ns3中运行优化后的算法,即自定义拥塞控制算法; 以tcpVegas算法为…...
前端开发中的常见设计模式:全面解析与实践
1. 引言 1.1 设计模式的重要性 设计模式是软件开发中经过验证的解决方案,能够帮助开发者解决常见的设计问题。在前端开发中,合理使用设计模式可以提高代码的可维护性、可扩展性和复用性。 1.2 本文的目标 本文旨在全面解析前端开发中常见的设计模式&…...
VSCode 2025最新 前端开发必备插件推荐汇总(提效指南)
🌟前言: 如果你是一名前端开发工程师,合适的开发工具能大大提高工作效率。Visual Studio Code (VSCode) 凭借其轻量级、高扩展性的特点,已成为众多前端开发者在win系电脑的首选IDE。 名人说:博观而约取,厚积而薄发。—…...
【redis】redis的单线程模型为什么效率高?
文章目录 单线程模型单线程的 Redis 为什么效率高?速度快?IO多路复用epoll 单线程模型 Redis 只使用一个线程,处理所有的命令请求。不是说一个 Redis 服务器进程内部只有一个线程,其实也有多个线程,多个线程是在处理网…...
scala的集合
scala的集合系统的区分了可变( mutable )和不可变(immutable )集合。 mkString(seq:String):方法是将原字符串使用特定的字符串seq分割。 mkString(statrt:String,seq:String,end:String):方法是将原字符…...
Flink状态管理深度探索:从Keyed State到分布式快照
Flink状态管理深度探索:从Keyed State到分布式快照 在大数据实时计算领域,Apache Flink凭借其精准的状态管理能力成为行业标杆。本文将从状态管理的核心机制出发,结合金融行业PB级数据处理实践,深入解析状态后端、容错机制与大规模优化策略。 一、Flink状态管理核心架构 …...
Android 11 DAC和MAC
在 Android 11 中,DAC(Discretionary Access Control,自主访问控制) 和 MAC(Mandatory Access Control,强制访问控制) 是两种不同的访问控制机制,主要用于 权限管理、安全性 以及 进程间访问控制。 1. DAC(自主访问控制) DAC(Discretionary Access Control,自主访…...
平衡二叉树(AVL树)
平衡二叉树是啥我就不多说了,本篇博客只讲原理与方法。 首先引入平衡因子的概念。平衡因子(Balance Factor),以下简称bf。 bf 右子树深度 - 左子树深度。平衡结点的平衡因子可为:-1,0,1。除此…...
SSM架构 +java后台 实现rtsp流转hls流,在前端html上实现视频播放
序言:书接上文,我们继续 SSM架构 NginxFFmpeg实现rtsp流转hls流,在前端html上实现视频播放 步骤一:把rtsp流转化为hls流,用Java代码进行转换 package com.tools;import java.io.BufferedReader; import java.io.IOExc…...
贪心算法--
1.柠檬水找零 link:860. 柠檬水找零 - 力扣(LeetCode) code class Solution { public:bool lemonadeChange(vector<int>& bills) {// 贪心算法, 优先花出大面额bill, 尽可能保护小面额billint five 0, ten 0;// 不…...
【从0到1搞懂大模型】神经网络的实现:数据策略、模型调优与评估体系(3)
一、数据集的划分 (1)按一定比例划分为训练集和测试集 我们通常取8-2、7-3、6-4、5-5比例切分,直接将数据随机划分为训练集和测试集,然后使用训练集来生成模型,再用测试集来测试模型的正确率和误差,以验证…...
CTF工具集合-持续更新
工具地址https://github.com/huan-cdm/ctf_tools工具介绍: 1.ARCHPR:压缩包密码破解工具 2.StegSolve-1.4.jar:隐写图片查看工具 3.ctf_decrypt_tool.rar:随波逐流CTF编码工具 4.010_Editor_All_Versions_For_Windows_CracKed.…...
小方摄像头接入本地服务器的方法
最早众筹时买了几个小方摄像头,后来嫌弃分辨率,就淘汰吃灰好几年,最近想折腾个摄像头识别的小项目,秉着不投入先凑合跑起来的原则,想到了尘封已久的小方,想看看能不能通过网络拉取数据流。 搜索了下&#x…...
取反符号~
取反符号 ~ 用于对整数进行按位取反操作。它会将二进制表示中的每一位取反,即 0 变 1,1 变 0。 示例 a 5 # 二进制表示为 0000 0101 b ~a # 按位取反,结果为 1111 1010(补码表示) print(b) # 输出 -6解释 5 的二…...
Jenkins实现自动化构建与部署:上手攻略
一、持续集成与Jenkins核心价值 1.1 为什么需要自动化构建? 在现代化软件开发中,团队每日面临以下挑战: 高频代码提交:平均每个开发者每天提交5-10次代码。多环境部署:开发、测试、预发布、生产环境需频繁同步。复杂…...
爱普生温补晶振 TG5032CFN高精度稳定时钟的典范
在科技日新月异的当下,众多领域对时钟信号的稳定性与精准度提出了极为严苛的要求。爱普生温补晶振TG5032CFN是一款高稳定性温度补偿晶体振荡器(TCXO)。该器件通过内置温度补偿电路,有效抑制环境温度变化对频率稳定性的影响&#x…...
【Java 面试 八股文】计算机网络篇
操作系统篇 1. 什么是HTTP? HTTP 和 HTTPS 的区别?2. 为什么说HTTPS比HTTP安全? HTTPS是如何保证安全的?3. 如何理解UDP 和 TCP? 区别? 应用场景?3.1 TCP 和 UDP 的特点3.2 适用场景 4. 如何理解TCP/IP协议?5. DNS协议 是什么?说说DNS 完整的查询…...
OpenHarmony5.0分布式系统源码实现分析—软总线
一、引言 OpenHarmony 作为一款面向万物互联的操作系统,其分布式软总线(Distributed SoftBus)是实现设备间高效通信和协同的核心技术之一。分布式软总线通过构建一个虚拟的总线网络,使得不同设备能够无缝连接、通信和协同工作。本…...
Spring Boot/Spring Cloud 整合 ELK(Elasticsearch、Logstash、Kibana)详细避坑指南
我们在开发中经常会写日志,所以需要有个日志可视化界面管理,使用ELK可以实现高效集中化的日志管理与分析,提升性能稳定性,满足安全合规要求,支持开发运维工作。 下述是我在搭建ELK时遇到的许许多多的坑,希望…...
云原生周刊:Istio 1.25.0 正式发布
开源项目推荐 Dstack Dstack 是一个开源的 AI 计算管理平台,旨在简化 AI 任务的部署和管理。它支持本地和云端运行 AI 工作负载,并提供自动化的 GPU 资源调度,使开发者能够更高效地利用计算资源。Dstack 兼容 K8s,可以无缝集成到…...
微前端如何拯救大型项目
前言 在前端开发的世界中,我们经常会遇到这样的问题:一个大型项目往往由多个团队共同开发,每个团队负责一部分功能。然而,随着项目的不断扩大和复杂化,前端代码库变得越来越庞大和难以维护。这时,微前端&a…...
RabbitMQ 高级特性:从 TTL 到消息分发的全面解析 (下)
RabbitMQ高级特性 RabbitMQ 高级特性解析:RabbitMQ 消息可靠性保障 (上)-CSDN博客 RabbitMQ 高级特性:从 TTL 到消息分发的全面解析 (下)-CSDN博客 引言 RabbitMQ 作为一款强大的消息队列中间件ÿ…...
OpenManus-通过源码方式本地运行OpenManus,含踩坑及处理方案
前言:最近 Manus 火得一塌糊涂啊,OpenManus 也一夜之间爆火,那么作为程序员应该来尝尝鲜 1、前期准备 FastGithub:如果有科学上网且能正常访问 github 则不需要下载此软件,此软件是提供国内直接访问 githubGit&#…...
Ubuntu22.04修改root用户并安装cuda
由于本人工作原因,经常会遇到需要给ubuntu打显卡驱动的问题,虽然说不难吧,但是耐不住机器多,重复多次也就烦了,于是抽出了一点时间,并且在deepseek的帮助之下,写了一个自动安装驱动的脚本&#…...
Java LeetCode 热题 100 回顾38
干货分享,感谢您的阅读!LeetCode 热题 100 回顾_力code热题100-CSDN博客 一、哈希部分 1.两数之和 (简单) 题目描述 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两…...
MySQL复习笔记
文章目录 1.MySQL1.1什么是数据库1.2 数据库分类1.3 MySQL简介1.4连接数据库 2. 操作数据库2.1 操作数据库2.2 数据库的列类型2.3 数据库的字段属性(重点)2.4 创建数据库表(重点)2.5 数据表的类型2.6 修改数据表 3. MySQL 数据管理…...
解释 TypeScript 中的类型系统,如何定义和使用类型?
1. 类型系统的核心作用 TypeScript类型系统本质上是JavaScript的静态类型增强方案,提供三个核心价值: 开发阶段类型检查(类似编译时eslint)更清晰的API文档(类型即文档)更好的IDE自动补全支持 代码示例&…...
安裝do時出現log file support is not available
“log file support is not available (press RETURN)” 这个提示信息表明日志文件支持不可用,让你按回车键继续。出现这种情况可能是因为 Odoo 的日志相关配置存在问题或者一些必要的依赖没有正确安装配置。以下是一些可以尝试的解决办法: 1. 检查 Odo…...
[HTTP协议]应用层协议HTTP从入门到深刻理解并落地部署自己的云服务(1)知识基础
[HTTP协议]应用层协议HTTP从入门到深刻理解并落地部署自己的云服务(1)知识基础 水墨不写bug 文章目录 (一)概念梳理1.什么是协议?2.什么是应用层?3. 为什么要进行分层? (二)HTTP协议2.1 初识HTTP协议2.2HTTP协议的URL2.2.1域名2.2.2端口号2…...
机票改签请求
示例代码: tool def update_ticket_to_new_flight(ticket_no: str, new_flight_id: int) -> str:"""Update the users ticket to a new valid flight.Args:ticket_no (str): The ticket number to be updated.new_flight_id (int): The ID of th…...
linux下文件读写操作
Linux下,文件I/O是操作系统与文件系统之间进行数据传输的关键部分。文件I/O操作允许程序读取和写入文件,管理文件的打开、关闭、创建和删除等操作。 1. 文件描述符 在Linux中,每个打开的文件都由一个文件描述符来表示。文件描述符是一个非负…...
命名管道的创建和通信实现
目录 命名管道的创建 使用函数创建命名管道的通信 预备创建 makefile设计 server.hpp设计 clent.hpp设计 comm.hpp设计 server.cc设计 clent.cc设计 测试运行 今天我们来学习命名管道 由于匿名管道(pipe())无法在两个毫不相干的进程之间进行通…...