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

一文学会easyexcel导入数据,多sheet页、字典转换【附带源码】

文章目录

  • 前言
  • 一、业务流程
  • 二、实现
    • 1、引入easyexcel、fastjson、lombok包
    • 2、创建Json工具类
    • 3、创建自定义字典转换注解
    • 4、创建字典转换实现类
    • 5、创建数据对象类
    • 6、创建多sheet页封装对象
    • 7、创建Excel导入工具类
    • 8、创建测试类
  • 三、接口测试
    • 1、启用项目
    • 2、使用数据导出的文件,作为导入的文件,或者重新编写
  • 四、总结

前言

​上次介绍了使用easyexcel导出数据,本次介绍使用easyexcel导入数据。

一、业务流程

像导出数据一样,导入数据也有对应的业务场景,那就是数据输入;所以通过页面输入数据遇到的问题,导入数据也要处理。下面介绍下数据输入必须要经过业务流程

  1. 输入需要的数据属性
  2. 数据属性和自然语言映射关系,将使用者可以理解的自然语言转为数据对象的属性
  3. 数据字典值和自然语言映射关系,将使用者可以理解的自然语言转为属性的字典值

二、实现

1、引入easyexcel、fastjson、lombok包

<!--easy excel-->
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>4.0.3</version>
</dependency>
<!--fastjson-->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.46</version>
</dependency>
<!--工具-->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.0</version>
</dependency>

2、创建Json工具类

package com.yu.demo.tools;import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.type.TypeReference;import java.lang.reflect.Type;
import java.util.Map;/*** JSON工具类** @author admin*/
public abstract class JsonUtil {private JsonUtil() {}public final static Type MAP_INTEGER_STRING = new TypeReference<Map<Integer, String>>() {}.getType();/*** json串转Map(Map的value类型一致时使用)** @param jsonString json串* @return 对象*/public static <K, V> Map<K, V> json2Map(String jsonString, Type type) {return JSON.parseObject(jsonString, type);}}

3、创建自定义字典转换注解

package com.yu.demo.tools;import java.lang.annotation.*;@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DictSource {/*** 字典类型主键*/String dictTypeId() default "";/*** 字典内容json串*/String dictContentJson() default "";}

4、创建字典转换实现类

package com.yu.demo.web.easyexcel.component;import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.yu.demo.web.easyexcel.util.JsonUtil;
import org.apache.poi.util.StringUtil;import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;public class IntegerDictConverter implements Converter<Integer> {/*** 导入支持的字段类型*/@Overridepublic Class<?> supportJavaTypeKey() {return Integer.class;}/*** 导出支持的字段类型*/@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}/*** 导入转换*/@Overridepublic Integer convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {String stringValue = cellData.getStringValue();if (StringUtil.isBlank(stringValue)) {return null;}//获取添加@ExcelProperty注解且converter = IntegerDictConverter.class的属性Field field = contentProperty.getField();//获取该属性的DictConverter注解信息DictSource dictSource = field.getAnnotation(DictSource.class);//配置了converter = IntegerDictConverter.class的属性,但是没有添加DictSource注解的直接强转if (dictSource == null) {try {//未配置字典时,直接强转return Integer.parseInt(stringValue);} catch (NumberFormatException ignored) {//转化失败时,返回空return null;}}//获取配置的dictTypeIdString dictTypeId = dictSource.dictTypeId();//获取配置的dictContentJsonString dictContentJson = dictSource.dictContentJson();//判断dictTypeId是否为空boolean nullDictType = StringUtil.isBlank(dictTypeId);//判断nullDictContentJson是否为空boolean nullDictContentJson = StringUtil.isBlank(dictContentJson);//字典配置都为空时,直接强转if (nullDictType && nullDictContentJson) {try {return Integer.parseInt(stringValue);} catch (NumberFormatException ignored) {//转化失败时,返回空return null;}}//优先使用dictTypeId处理转换if (!nullDictType) {//通过dictTypeId获取字典内容集合:List<DictContent> dictContents = dictContentService.listByDictTypeId(dictTypeId);//主键是数值的,将dictTypeId转为数值//遍历字典内容,匹配输入值与字典名称:name.equals(dictContent.getName())//匹配成功后获取字典值返回:return dictContent.getValue();//如果没有匹配成功使用dictContentJson处理转换}if (!nullDictContentJson) {Map<Integer, String> dictContentMap = JsonUtil.json2Map(dictContentJson, JsonUtil.MAP_INTEGER_STRING);Set<Map.Entry<Integer, String>> entrySet = dictContentMap.entrySet();for (Map.Entry<Integer, String> entry : entrySet) {if (stringValue.equals(entry.getValue())) {return entry.getKey();}}}//没有转换成功时直接强转try {return Integer.parseInt(stringValue);} catch (NumberFormatException ignored) {//转化失败时,返回空return null;}}/*** 导出转换*/@Overridepublic WriteCellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {//属性值为空时,直接返回if (value == null) {//为空时的处理,与前端展示保持一致即可return new WriteCellData<>("");}//获取添加@ExcelProperty注解且converter = IntegerDictConverter.class的属性Field field = contentProperty.getField();//获取该属性的DictConverter注解信息DictSource dictSource = field.getAnnotation(DictSource.class);//配置了converter = IntegerDictConverter.class的属性,但是没有添加DictSource注解的直接返回if (dictSource == null) {return new WriteCellData<>(String.valueOf(value));}//获取配置的dictTypeIdString dictTypeId = dictSource.dictTypeId();//获取配置的dictContentJsonString dictContentJson = dictSource.dictContentJson();//判断dictTypeId是否为空boolean nullDictType = StringUtil.isBlank(dictTypeId);//判断nullDictContentJson是否为空boolean nullDictContentJson = StringUtil.isBlank(dictContentJson);//字典配置都为空时,将属性值转为字符串直接返回if (nullDictType && nullDictContentJson) {return new WriteCellData<>(String.valueOf(value));}//优先使用dictTypeId处理转换if (!nullDictType) {//通过dictTypeId获取字典内容集合:List<DictContent> dictContents = dictContentService.listByDictTypeId(dictTypeId);//主键是数值的,将dictTypeId转为数值//遍历字典内容,匹配属性值与字典值:value.equals(dictContent.getValue())//匹配成功后获取字典名称返回:return new WriteCellData<>(dictContent.getName());//如果没有匹配成功使用dictContentJson处理转换}if (!nullDictContentJson) {Map<Integer, String> dictContentMap = JsonUtil.json2Map(dictContentJson, JsonUtil.MAP_INTEGER_STRING);String cnName = dictContentMap.get(value);if (StringUtil.isNotBlank(cnName)) {return new WriteCellData<>(cnName);}}//没有转换成功时使用默认属性值return new WriteCellData<>(String.valueOf(value));}
}

5、创建数据对象类

package com.yu.demo.web.easyexcel.entity;import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.converters.date.DateStringConverter;
import com.yu.demo.web.easyexcel.component.DictSource;
import com.yu.demo.web.easyexcel.component.IntegerDictConverter;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;import java.util.Date;@Setter
@Getter
@ToString
//类上添加@ExcelIgnoreUnannotated时,属性没有@ExcelProperty注解时不导出
//类上未添加@ExcelIgnoreUnannotated,属性没有@ExcelProperty注解时也导出
@ExcelIgnoreUnannotated
public class User {/*** 名称*/@ExcelProperty("名称")private String name;/*** 密码* 类添加@ExcelIgnoreUnannotated,属性未添加@ExcelProperty,不导出*/private String password;/*** 生日* 日期样式处理* 1.使用@DateTimeFormat设置导出样式* 2.使用DateStringConverter处理导出*/@DateTimeFormat("yyyy-MM-dd HH:mm:ss")@ExcelProperty(value = "生日", converter = DateStringConverter.class)private Date birthday;/*** 性别* 字典转换处理*/@ColumnWidth(7)//指定列宽度,优先级高于LongestMatchColumnWidthStyleStrategy@ExcelProperty(value = "性别", converter = IntegerDictConverter.class)@DictSource(dictContentJson = "{0:'女',1:'男',2:'保密'}")private Integer sex;}

6、创建多sheet页封装对象

package com.yu.demo.tools;import lombok.Getter;
import lombok.Setter;
import lombok.ToString;import java.util.List;/*** excel导入导出数据对象*/
@Setter
@Getter
@ToString
public class SheetEntity<T> {/*** sheet页名称(导出参数)* 可以为空,为空时,单sheet页没有名称,多sheet页序号为名称*/private String sheetName;/*** 数据类型(导入导出参数)*/private Class<T> head;/*** 数据(导出参数)*/private List<T> data;/*** 读取数据监听器(导入参数)*/private ReadListener<T> readListener;}

7、创建Excel导入工具类

​ 导入数据说明

  • 通过文件或者文件流导入
  • 导入的数据同步方式写入集合,适合小数据量
  • 导入的数据异步方式写入集合,适合大数据量
package com.yu.demo.web.easyexcel.util;import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.yu.demo.web.easyexcel.entity.SheetEntity;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.util.StringUtil;import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;/*** excel导入导出工具类(easyExcel实现)* easyPoi:并发量和数据量都不大时推荐,定制化的导出支持非常的丰富* easyExcel:高并发、大数据量时推荐*/
public abstract class ExcelUtil {// 设置居中对齐的样式private static final WriteCellStyle CONTENT_WRITE_CELL_STYLE;private static final WriteHandler HORIZONTAL_CELL_STYLE_STRATEGY;static {CONTENT_WRITE_CELL_STYLE = new WriteCellStyle();//水平居中CONTENT_WRITE_CELL_STYLE.setHorizontalAlignment(HorizontalAlignment.CENTER);//垂直居中CONTENT_WRITE_CELL_STYLE.setVerticalAlignment(VerticalAlignment.CENTER);HORIZONTAL_CELL_STYLE_STRATEGY = new HorizontalCellStyleStrategy(null, CONTENT_WRITE_CELL_STYLE);}private ExcelUtil() {}/*** 使用EasyExcel导出** @param fullFileName 文件路径+文件名+后缀(文件已存在时覆盖,目录不存在时Windows报错,linux不报错)* @param sheetName    sheet名称(为空时使用默认值0)* @param head         数据类型(为空时没有表头,只有数据)* @param exportData   需要导出的数据(为空时,没有数据)*/public static void exportByEasyExcel(String fullFileName, String sheetName, Class<?> head, List<?> exportData) {File targetFile = new File(fullFileName);// 判断文件父目录是否存在if (!targetFile.getParentFile().exists()) {boolean mkdirResult = targetFile.getParentFile().mkdirs();if (!mkdirResult) {return;}}ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(targetFile, head);if (fullFileName.endsWith(ExcelTypeEnum.XLS.getValue())) {excelWriterBuilder.excelType(ExcelTypeEnum.XLS);} else if (fullFileName.endsWith(ExcelTypeEnum.CSV.getValue())) {excelWriterBuilder.excelType(ExcelTypeEnum.CSV);} else {excelWriterBuilder.excelType(ExcelTypeEnum.XLSX);}excelWriterBuilder//设置列按最大长度调整.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())//设置水平垂直居中.registerWriteHandler(HORIZONTAL_CELL_STYLE_STRATEGY).sheet(sheetName).doWrite(exportData);}/*** 使用EasyExcel导出** @param outputStream 输出流* @param sheetName    sheet名称(为空时使用默认值0)* @param head         数据类型(为空时没有表头,只有数据)* @param exportData   需要导出的数据(为空时,没有数据)*/public static void exportByEasyExcel(OutputStream outputStream, ExcelTypeEnum excelType, String sheetName, Class<?> head, List<?> exportData) {EasyExcel.write(outputStream, head).excelType(excelType)//设置列按最大长度调整,非线程安全,每次都需要new.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())//设置水平垂直居中.registerWriteHandler(HORIZONTAL_CELL_STYLE_STRATEGY).sheet(sheetName).doWrite(exportData);}/*** 使用EasyExcel导出多sheet页数据** @param outputStream  输出流* @param sheetEntities 导出数据对象集合*/public static void exportByEasyExcel(OutputStream outputStream, ExcelTypeEnum excelType, List<SheetEntity<?>> sheetEntities) {ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(outputStream).excelType(excelType);writeSheets(excelWriterBuilder, sheetEntities);}/*** 同步导入,适合小数据量** @param inputStream 数据文件流*/public static <T> List<T> importByEasyExcel(InputStream inputStream, Class<T> head) {return EasyExcel.read(inputStream).head(head).sheet().doReadSync();}/*** 异步导入,解析的数据通过回调函数返回,适合大数据量** @param inputStream  数据文件流* @param head         数据类型* @param readListener 回调监听器*/public static void importByEasyExcel(InputStream inputStream, Class<?> head, ReadListener<?> readListener) {EasyExcel.read(inputStream, head, readListener).sheet().doRead();}/*** 多sheet页导入** @param inputStream   数据文件流* @param sheetEntities 导入数据对象集合*/public static void importByEasyExcel(InputStream inputStream, List<SheetEntity<?>> sheetEntities) {if (inputStream == null || CollectionUtils.isEmpty(sheetEntities)) {return;}ExcelReader excelReader = EasyExcel.read(inputStream).build();readSheets(excelReader, sheetEntities);}/*** 多sheet页导入** @param file          数据文件* @param sheetEntities 导入数据对象集合*/public static void importByEasyExcel(File file, List<SheetEntity<?>> sheetEntities) {if (file == null || CollectionUtils.isEmpty(sheetEntities)) {return;}ExcelReader excelReader = EasyExcel.read(file).build();readSheets(excelReader, sheetEntities);}private static void readSheets(ExcelReader excelReader, List<SheetEntity<?>> sheetEntities) {List<ReadSheet> readSheets = new ArrayList<>(sheetEntities.size());for (int i = 0; i < sheetEntities.size(); i++) {SheetEntity<?> sheetEntity = sheetEntities.get(i);ReadSheet readSheet = EasyExcel.readSheet(i).head(sheetEntity.getHead()).registerReadListener(sheetEntity.getReadListener()).build();readSheets.add(readSheet);}excelReader.read(readSheets);}private static void writeSheets(ExcelWriterBuilder excelWriterBuilder, List<SheetEntity<?>> sheetEntities) {excelWriterBuilder.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).registerWriteHandler(HORIZONTAL_CELL_STYLE_STRATEGY);ExcelWriter excelWriter = excelWriterBuilder.build();for (int i = 0; i < sheetEntities.size(); i++) {SheetEntity<?> sheetEntity = sheetEntities.get(i);Class<?> head = sheetEntity.getHead();List<?> exportData = sheetEntity.getData();String sheetName = StringUtil.isBlank(sheetEntity.getSheetName()) ? String.valueOf(i + 1) : sheetEntity.getSheetName();WriteSheet writeSheet = EasyExcel.writerSheet(i + 1, sheetName).head(head).build();excelWriter.write(exportData, writeSheet);}excelWriter.finish();}}

8、创建测试类

package com.yu.demo.web.easyexcel.web;import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.yu.demo.web.easyexcel.entity.SheetEntity;
import com.yu.demo.web.easyexcel.entity.User;
import com.yu.demo.web.easyexcel.util.ExcelUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;@RestController
@RequestMapping("user")
public class UserController {@Value("${download.path}")private String filePath;private List<User> users;private List<SheetEntity<?>> sheetEntities;@PostConstructpublic void init() {users = new ArrayList<>(5);for (int i = 0; i < 5; i++) {User user = new User();user.setName(i + "号用户");user.setPassword(String.valueOf(i * 1000));user.setBirthday(new Date());user.setSex(i % 3);users.add(user);}sheetEntities = new ArrayList<>(2);for (int i = 0; i < 2; i++) {SheetEntity<User> sheetEntity = new SheetEntity<>();sheetEntity.setSheetName(i + "号sheet");sheetEntity.setHead(User.class);sheetEntity.setData(users);sheetEntities.add(sheetEntity);}}/*** 单sheet页通过全路径文件名导出测试接口(也可以通过文件流导出)* 返回文件名,前端通过web路径+文件名下载文件*/@GetMapping("/filePath")public String filePath() {String fileName = "用户.xlsx";String fullFileName = filePath + fileName;ExcelUtil.exportByEasyExcel(fullFileName, "用户", User.class, users);return fileName;}/*** 多sheet页通过文件流导出(也可以通过全路径文件名导出)*/@GetMapping("/download")public void download(HttpServletResponse response) throws IOException {String fileName = "用户";response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding(StandardCharsets.UTF_8.name());String encodeFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=*=utf-8''" + encodeFileName + ExcelTypeEnum.XLSX.getValue());ExcelUtil.exportByEasyExcel(response.getOutputStream(), ExcelTypeEnum.XLSX, sheetEntities);}/*** 上传数据* 单sheet页,同步导入示例接口*/@PostMapping("/upload")public String upload(MultipartFile file) throws IOException {List<User> list = ExcelUtil.importByEasyExcel(file.getInputStream(), User.class);//根据业务处理数据,这里直接打印数据System.out.println(list);return "success";}/*** 上传数据* 多sheet页,异步导入示例接口*/@PostMapping("/upload2")public String upload2(MultipartFile file) throws IOException {List<SheetEntity<?>> sheetEntities = new ArrayList<>(2);sheetEntities.add(getUserImportEntity());//多sheet页时按照顺序添加SheetEntitysheetEntities.add(getUserImportEntity());ExcelUtil.importByEasyExcel(file.getInputStream(), sheetEntities);return "success";}private SheetEntity<User> getUserImportEntity() {SheetEntity<User> sheetEntity = new SheetEntity<>();sheetEntity.setHead(User.class);//根据业务处理数据,这里直接打印数据ReadListener<User> pageReadListener = new PageReadListener<>(System.out::println);sheetEntity.setReadListener(pageReadListener);return sheetEntity;}
}

三、接口测试

1、启用项目

image-20241025110748439

2、使用数据导出的文件,作为导入的文件,或者重新编写

  • 多sheet页导出接口地址:http://localhost:8080/user/download,获取导入的文件
  • 单sheet页导入接口地址:http://localhost:8080/user/upload
  • 多sheet页导入接口地址:http://localhost:8080/user/upload2
  • postman测试接口(同文件一个,单sheet页时只解析第一个sheet页)

在这里插入图片描述

  • 测试结果

在这里插入图片描述

在这里插入图片描述

四、总结

  1. 使用Entity对象作为关系映射的载体,使用@ExcelProperty注解映射属性名称,并可以指定转换器、序号等信息;使用自定义注解@DictSource注解和指定转换器转换字典值
  2. 数据导入日期类型格式要和Entity中日期属性的注解@DateTimeFormat(“yyyy-MM-dd HH:mm:ss”)中格式保持一致
  3. SpringBoot集成easyexcel数据导入案例下载

相关文章:

一文学会easyexcel导入数据,多sheet页、字典转换【附带源码】

文章目录 前言一、业务流程二、实现1、引入easyexcel、fastjson、lombok包2、创建Json工具类3、创建自定义字典转换注解4、创建字典转换实现类5、创建数据对象类6、创建多sheet页封装对象7、创建Excel导入工具类8、创建测试类 三、接口测试1、启用项目2、使用数据导出的文件&am…...

Spring中的 InitializingBean、BeanPostProcessor、@PostConstruct 等初始化动作的执行时机分析

初始化Bean的时序图如下&#xff1a; 小结说明&#xff1a; 1、相同点&#xff1a;InitializingBean 的(afterPropertiesSet方法)、BeanPostProcessor、PostConstruct 都是在bean的属性注入完毕之后才执行&#xff0c;都可以用来进行bean的初始化动作 2、初始化执行顺序优先级…...

如何利用指纹浏览器爬虫绕过Cloudflare的防护?

网络爬虫能够系统地浏览网页并提取所需的数据&#xff0c;通常被用于市场研究、数据分析或者竞争情报。然而&#xff0c;一些反爬虫机制给网络爬虫的工作带来了不少挑战和风险。 其中&#xff0c;Cloudflare提供了多层次的防护机制&#xff0c;包括IP封锁、速率限制、CAPTCHA验…...

idea 基础简单应用(java)

Java IDE&#xff08;集成开发环境&#xff09;的使用方法因不同的IDE而异&#xff0c;但通常都包含一些基本的操作和功能。以下以IntelliJ IDEA这一流行的Java IDE为例&#xff0c;介绍Java IDE的基本使用方法与指南&#xff1a; 一、下载与安装 请点击观看 idea免费安装步…...

windows环境下vscode下载安装

vscode官网 1.vscode官网&#xff1a;Visual Studio Code - Code Editing. Redefined 进入官网&#xff0c;点击下载 右键文件&#xff0c;以管理员方式运行&#xff0c;开始安装 第一步:同意此协议 第二步&#xff1a;更改安装位置&#xff0c;可以在d盘新建一个文件夹&…...

Obsidian之与Typora图片格式相互兼容

来源 [Obsidian之与Typora图片格式相互兼容 - 简书 (jianshu.com)](https://www.jianshu.com/p/303433fe82b9) 下载插件customer attachment location&#xff0c;并设置...

美半导体巨头正切断中国供应链,给自己“挖坑”?

美国对华半导体“脱钩断链”政策持续升级&#xff0c;近日开始对半导体产业链进行“去中化”。 据外媒《华尔街日报》11月5日报道&#xff0c;受美国政府最新指令指示&#xff0c;美国半导体巨头应用材料公司&#xff08;Applied Materials&#xff09;和泛林集团&#xff08;L…...

RHCE---搭建lnmp云存储

一、恢复快照后&#xff0c;检查安全性&#xff08;查看selinux 以及防火墙&#xff09; 二、搭建LNMP环境 [rootserver ~]# yum -y install nginx mariadb-server php*三、上传软件 1、将nextcloud-25.0.1.zip压缩包传递到根目录下 2、解压缩nextcloud-25.0.1.zip &#xf…...

一些 uniapp相关bug

1.当input聚焦时布局未上移 <scroll-view style"height: calc(100vh - 100rpx - 38rpx)" :scroll-y"true"><wd-form ref"formRef" :model"fbObj">....<wd-inputlabel"联系方式"prop"contact"clear…...

操作系统-4.2文件系统的层次结构虚拟文件系统

文章目录 文件系统的层次结构物理格式化open系统调用打开文件的背后过程图中内容解释文件打开的详细步骤操作总结 虚拟文件系统1. **虚拟文件系统的作用**2. **虚拟文件系统的结构**3. **VFS 工作机制**4. **VFS 的优点** 文件系统的层次结构 用一个例子来辅助记忆文件系统的层…...

【深度学习】DreamClear:提升图片分辨率的模型

基于PixArt-XL-2模型,效果很好。 DreamClear:高容量真实世界图像修复与隐私安全数据集构建 在图像修复领域,处理真实世界中的低质量(Low-Quality, LQ)图像并恢复其高质量(High-Quality, HQ)版本一直是一个具有挑战性的任务。今天,我们将介绍一个最新的开源项目——Dr…...

操作系统进程互斥的四种软件实现和三种硬件实现

进程互斥是操作系统中保证多个进程不会同时访问共享资源的一种机制。 进程互斥的四种软件实现方式&#xff1a; 一、单标志法 核心思想&#xff1a;使用一个布尔变量&#xff08;或称为标志位&#xff09;来表示临界区的访问权限。该变量为true时表示允许某个进程访问临界区&…...

C++虚继承演示

在继承中如果出现&#xff1a; 这种情况&#xff0c;B和C都继承了A&#xff0c;D继承了B、C 在D中访问A的成员会出现&#xff1a; 这样的警告 是因为在继承时A出现两条分支&#xff1a;ABD、ACD 编译器不知道访问的A中的元素是经过B继承还是C继承 所以B、C在继承A时要用到…...

React Native的生命周期

React Native 组件的生命周期分为三个阶段&#xff1a;Mounting&#xff08;挂载&#xff09;、Updating&#xff08;更新&#xff09; 和 Unmounting&#xff08;卸载&#xff09;。每个阶段都会触发不同的生命周期方法。 下面是详细的生命周期解释&#xff0c;并通过一个项目…...

linux系统中涉及到用户管理的命令知识

用户创建与密码设置 Linux中新建用户使用useradd命令&#xff0c;只有root用户才能执行&#xff0c;若useradd命令直接输入不管用&#xff0c;可使用绝对路径/usr/sbin/useradd。设置用户登录密码使用passwd命令。 su命令相关 su代表switch user&#xff0c;用于切换用户。切换…...

LeetCode 0685.冗余连接 II:并查集(和I有何不同分析)——详细题解(附图)

【LetMeFly】685.冗余连接 II&#xff1a;并查集&#xff08;和I有何不同分析&#xff09;——详细题解(附图) 力扣题目链接&#xff1a;https://leetcode.cn/problems/redundant-connection-ii/ 在本问题中&#xff0c;有根树指满足以下条件的 有向 图。该树只有一个根节点&…...

Dubbo负载均衡

负载均衡策略与配置细节 Dubbo 内置了 client-based 负载均衡机制&#xff0c;如下是当前支持的负载均衡算法&#xff0c;结合上文提到的自动服务发现机制&#xff0c;消费端会自动使用 Weighted Random LoadBalance 加权随机负载均衡策略 选址调用。 如果要调整负载均衡算法…...

PymuPDF4llm提取pdf文件文字、表格与图片

一、PymuPDF4llm 的功能特点 &#xff08;一&#xff09;文本提取 简单易用 PymuPDF4llm 的文本提取功能非常简单易用。只需使用pip install pymupdf4llm进行安装&#xff0c;然后通过import pymupdf4llm导入库&#xff0c;就可以使用md_text pymupdf4llm.to_markdown("…...

20241108通过iperf3确认中科创达的高通CM6125的WIFI的网速【失败】

20241108通过iperf3确认中科创达的高通CM6125的WIFI的网速【失败】 2024/11/8 15:43 由于以太网不能用&#xff0c;那就测试一下WIFI&#xff0c;iperf3链接/测试异常。 一般认为可能的原因有&#xff1a; 1、CM6125开发板的WIFI不带天线&#xff0c;影响性能。 2、CM6125的And…...

Stored procedures in PostgreSQL

select 存储过程&#xff0c;在现了解的情况&#xff0c;还是没有mysql,sqlserver等好写好用。 --postgreSQL 11.0 以下版本 create or replace FUNCTION procInsertSchool (pSchoolId Char(5),pSchoolName VarChar(100),pSchoolTelNo VarChar(8) ) RETURNS void language plp…...

新手福音,用快马AI生成2048论坛登录页,轻松理解Web开发基础

今天想和大家分享一个特别适合新手入门的Web开发小项目——用InsCode(快马)平台快速搭建2048论坛的登录页面。作为刚接触编程的小白&#xff0c;我第一次看到这个需求时有点懵&#xff0c;但通过平台提供的AI生成功能&#xff0c;不仅快速实现了页面&#xff0c;还弄懂了每个环…...

ESP32 LVGL8.1 —— 消息框进阶:自定义按钮与事件处理实战

1. ESP32与LVGL8.1消息框基础认知 第一次接触ESP32和LVGL8.1的消息框功能时&#xff0c;我完全被它的灵活性震惊了。想象一下&#xff0c;你正在开发一个智能家居控制面板&#xff0c;当用户操作不当或者系统需要确认时&#xff0c;弹出一个美观的对话框是多么自然的事情。这就…...

AzurLaneAutoScript:碧蓝航线全自动游戏助手,释放您的双手与时间

AzurLaneAutoScript&#xff1a;碧蓝航线全自动游戏助手&#xff0c;释放您的双手与时间 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研&#xff0c;全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAuto…...

【Matlab】MATLAB教程:图形句柄;案例:h=plot(x,y);应用:控制图形属性

MATLAB教程:图形句柄;案例:h=plot(x,y);应用:控制图形属性 在MATLAB数据可视化、实验报告绘图、工程结果展示等场景中,仅仅通过plot函数绘制基础图形远远不够。实际科研与工程应用中,往往需要精准调整图形的线条样式、颜色、标记点、坐标轴、图例等属性,让图形更清晰、…...

让 AI 听懂业务、直接干活:销售易 NeoAgent 2.0 的三大跃迁

当软件行业仍在争论“AI是否会杀死SaaS”时&#xff0c;销售易已经给出了自己的答案。3月27日&#xff0c;在2026腾讯云城市峰会首站上海站&#xff0c;腾讯旗下CRM销售易正式发布新一代营销服全场景AI原生CRM——NeoAgent 2.0。这并非一次简单的产品迭代&#xff0c;而是销售易…...

益象创新与数谷智能,轻量化 AI 定制方案设计谁更优?

在企业数字化转型的下半场&#xff0c;人工智能&#xff08;AI&#xff09;的应用正从“大算力、大模型”的盲目崇拜&#xff0c;转向“轻量化、高适配”的务实落地上。对于中小型企业或大型企业的特定业务部门而言&#xff0c;动辄百万级的算力投入并不现实&#xff0c;一套能…...

提示工程代码审查避坑指南:10个容易犯的低级错误

提示工程代码审查避坑指南&#xff1a;10个容易犯的低级错误 引言&#xff1a;为什么提示工程需要“代码审查”&#xff1f; 在AI时代&#xff0c;提示词&#xff08;Prompt&#xff09;是人类与大语言模型&#xff08;LLM&#xff09;沟通的“桥梁”。就像程序员写代码需要评审…...

理视康新零售系统开发要点

业务模式设计新零售模式需整合线上线下渠道&#xff0c;构建会员体系、分销机制与数据中台。通过小程序、APP或H5实现线上商城&#xff0c;线下门店采用智能硬件&#xff08;如AR试戴、智能货架&#xff09;提升体验。结合LBS技术实现附近门店导流&#xff0c;支持到店自提或同…...

Transformer深度解析四:认知跃迁、交互建模与文明基底重构

【内容定位】未来畅想【文章日期】2026-03-31【场景引入】2026年3月的最后一天&#xff0c;我们站在一个看似稳固的技术高原上回望&#xff1a;Transformer架构已如同信息时代的“牛顿定律”&#xff0c;近乎完美地描述了语言宇宙中“符号”与“关系”的运动规律&#xff0c;并…...

Phi-4-mini-reasoning作品集:自动将推理过程转化为教学级讲解语言

Phi-4-mini-reasoning作品集&#xff1a;自动将推理过程转化为教学级讲解语言 1. 模型简介 Phi-4-mini-reasoning是一个轻量级的开源文本生成模型&#xff0c;专注于将复杂推理过程转化为清晰易懂的教学语言。作为Phi-4模型家族的一员&#xff0c;它特别擅长处理需要逐步解释…...