Excel 解析工具类实现Demo,通过XSSFSheetXMLHandler使用实现

文章目录

  • 一、功能概述
  • 二、BigExcelAnalysisUtil类
  • 三、SheetRuleUtil 类
  • 其他
    • SheetContentsHandler 使用讲解

一、功能概述

  • 可以校验表头
  • 以sheet维度,读取数据
  • 可以根据反射,自动把excel中的数据封装到bean
  • 主要使用了OPCPackage、XSSFReader、XSSFSheetXMLHandler、XMLReader 读取数据
  • 具体的执行demo,下载绑定的代码资源即可

二、BigExcelAnalysisUtil类

  • excel数据的解析过程
package org.example.ljj.util;

import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.SAXHelper;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFComment;
import org.example.ljj.util.model.*;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

public class BigExcelAnalysisUtil {

    private OPCPackage xlsxPackage;

    /**
     * 私有内部类
     */
    private class SimpleSheetContentsHandler implements XSSFSheetXMLHandler.SheetContentsHandler {

        HashMap<String, String> rowData = null;
        List<HashMap<String, String>> datas = null;

        public SimpleSheetContentsHandler(List<HashMap<String, String>> datas) {
            this.datas = datas;
        }

        /**
         * 当数据和行号对不上的时候,补null
         *
         * @param rowNum 当前行号
         */
        @Override
        public void startRow(int rowNum) {
            if (datas.size() < rowNum) {
                for (int i = 0; i < rowNum; i++) {
                    datas.add(null);
                }
            }
            rowData = new HashMap<String, String>(16);
        }

        /**
         * 当前行中的,cellReference列数据处理
         *
         * @param cellReference,列号,A1,B1,C1...
         * @param formattedValue,该单元格的值
         * @param comment
         */
        @Override
        public void cell(String cellReference, String formattedValue, XSSFComment comment) {

            // 读取的列号,cellReference为“A1 A2 A3...”的时候,thisCol为0
            int thisCol = (new CellReference(cellReference)).getCol();
            if (!StringUtils.isEmpty(cellReference)) {
                // formattedValue,为该单元格的值
                formattedValue = formattedValue.trim();
            }
            rowData.put(String.valueOf(thisCol), formattedValue);
        }

        /**
         * 全部列读完之后,做行处理
         *
         * @param rowNum 行号
         */
        @Override
        public void endRow(int rowNum) {
            datas.add(rowData);
        }

        /**
         * 文件表头和表尾处理,这里无需做任何处理
         *
         * @param text
         * @param isHeader
         * @param tagName
         */
        @Override
        public void headerFooter(String text, boolean isHeader, String tagName) {

        }

    }

    /**
     * 解析文件,返回excel的数据
     *
     * @param filePath
     * @param sheetrules
     * @return
     * @throws Exception
     */
    public WorkBookDataResult process(String filePath, List<SheetRule> sheetrules) throws Exception {
        WorkBookDataResult workBookData = new WorkBookDataResult();
        workBookData.setSuccess(true);
        this.xlsxPackage = OPCPackage.open(filePath, PackageAccess.READ);
        // 只读字符表
        ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(this.xlsxPackage);
        // Xssf读取
        XSSFReader xssfReader = new XSSFReader(this.xlsxPackage);
        // 样式表
        StylesTable styles = xssfReader.getStylesTable();
        //读取文件数据,生成List<InputStream>
        XSSFReader.SheetIterator sheets = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
        //xml文件解析器
        XMLReader parser = SAXHelper.newXMLReader();
        int sheetIndex = 0;
        List<SheetDataResult> sheetDatas = new ArrayList<>();
        //一个个sheet分开读取,分开处理
        while (sheets.hasNext()) {
            //获取当前sheet的数据
            InputStream sheet = sheets.next();
            //获取当前sheet的校验规则
            SheetRule sheetRule = this.getSheetRule(sheetrules, sheetIndex);
            //如果不为空才获取数据
            if (sheetRule != null) {
                //获取当前sheet名
                String sheetName = sheets.getSheetName();
                //保存当前sheet的所有数据
                List<HashMap<String, String>> datas = new ArrayList<>();
                //通过把 datas 放入控制器中,通过控制器读取excel的数据,同时把数据放入datas中,这里的datas只是初始化
                XSSFSheetXMLHandler.SheetContentsHandler sheetHandler = new SimpleSheetContentsHandler(datas);
                //解析sheet数据,这里执行结束,datas将有数据
                this.processSheet(parser, styles, strings, sheetHandler, sheet);
                //数据已经读取,释放资源
                sheet.close();
                System.out.println(sheetName + " rows=" + datas.size());
                //验证+组装数据
                String sheetAnalysisResult = this.processData(sheetDatas, sheetName, datas, sheetRule);
                if (!"SUCCESS".equals(sheetAnalysisResult)) {
                    workBookData.setErrMsg(sheetAnalysisResult);
                    workBookData.setSuccess(false);
                    sheetDatas.clear();
                    break;
                }
            }
            sheetIndex++;
        }
        workBookData.setWorkDatas(sheetDatas);
        return workBookData;
    }


    /**
     * 解析文件中sheet数据
     *
     * @param parser
     * @param styles
     * @param strings
     * @param sheetHandler
     * @param sheetInputStream
     * @throws IOException
     * @throws SAXException
     */
    private void processSheet(XMLReader parser, StylesTable styles, ReadOnlySharedStringsTable strings,
                              XSSFSheetXMLHandler.SheetContentsHandler sheetHandler, InputStream sheetInputStream) throws IOException, SAXException {
        ContentHandler handler = new XSSFSheetXMLHandler(styles, strings, sheetHandler, false);
        InputSource sheetSource = new InputSource(sheetInputStream);
        //设置内容格式
        parser.setContentHandler(handler);
        //解析XMl文件数据
        parser.parse(sheetSource);
    }


    /**
     * 验证+组装数据
     *
     * @param sheetDatas
     * @param sheetName
     * @param datas      excel中单个sheet的数据:含表头数据和普通数据
     * @param sheetRule
     * @return
     * @throws Exception
     */
    private String processData(List<SheetDataResult> sheetDatas, String sheetName, List<HashMap<String, String>> datas, SheetRule sheetRule) throws Exception {
        List<CellRule> cellRules = sheetRule.getCellRules();

        //解析校验表头
        if (!checkSheetTitles(sheetRule, datas)) {
            return "导入文件的表头和模板的表头不一致!";
        }
        //校验数据
        int startRow = sheetRule.getStartRow();
        String mapBeanName = sheetRule.getMapBean();
        boolean mapBean = StringUtils.isEmpty(mapBeanName) ? false : true;
        //获取数据转换字典
        HashMap<String, HashMap<String, String>> dictionary = sheetRule.getDictionary();
        List<Map<String, Object>> sheetMapDatas = new ArrayList<Map<String, Object>>();
        List<Object> sheetBeanDatas = new ArrayList<Object>();
        //解析行数据
        for (int rowIndex = 0 + startRow; rowIndex < datas.size(); rowIndex++) {
            // 过滤空行
            if (datas.get(rowIndex) == null || datas.get(rowIndex).isEmpty()) {
                continue;
            }
            HashMap<String, Object> mapData = null;
            Object beanData = null;
            Class beanClass = null;
            if (!mapBean) {
                mapData = new HashMap<>(16);
            } else {
                //根据 mapBeanName 创建对应的对象
                beanClass = Class.forName(mapBeanName);
                beanData = beanClass.newInstance();
            }
            //获取单元格数据,按照模板的顺序遍历,cellRule对象里面的columnIndex存储了数据在文件的具体位置(列)
            for (int ls = 0; ls < cellRules.size(); ls++) {
                CellRule cellRule = cellRules.get(ls);
                //获取单个单元格的值
                String cellData = datas.get(rowIndex).get(String.valueOf(cellRule.getColumnIndex()));
                //校验该单元格的数据是否合法
                CheckCellInfo checkCellInfo = checkCelldata(cellRule, cellData);
                if (!checkCellInfo.isSuccess()) {
                    return sheetName + "第" + (rowIndex + 1) + "行" + checkCellInfo.getMeg();
                } else {
                    //查询是否有字典名
                    String transformDicName = cellRule.getTransformDicName();
                    //如果有字典,做转换
                    if (!StringUtils.isEmpty(transformDicName)) {
                        cellData = dictionary.get(transformDicName).get(cellData);
                    }
                    if (!mapBean && mapData != null) {
                        String key = cellRule.getMapColumn();
                        mapData.put(key, cellData);
                    } else if (beanClass != null) {
                        String beanField = cellRule.getBeanFiled();
                        Field field = beanClass.getDeclaredField(beanField);
                        //设置访问权限为可访问(如果需要访问私有字段)
                        field.setAccessible(true);
                        //通过字段反射类field,给beanData对象赋值
                        field.set(beanData, transFiledData(field, cellData));
                    }
                }
            }
            //把一行的数据存储起来
            if (!mapBean) {
                sheetMapDatas.add(mapData);
            } else {
                sheetBeanDatas.add(beanData);
            }
        }
        //把sheet的数据封装到sheetDataResult中
        SheetDataResult sheetDataResult = new SheetDataResult();
        sheetDataResult.setSheetIndex(sheetRule.getSheetIndex());
        sheetDataResult.setSheetName(sheetName);
        //把sheet的数据放入sheetDataResult中
        if (!mapBean) {
            sheetDataResult.setSheetDatas(sheetMapDatas);
            sheetDataResult.setRowNum(sheetMapDatas.size());
        } else {
            sheetDataResult.setSheetBeanDatas(sheetBeanDatas);
            sheetDataResult.setRowNum(sheetBeanDatas.size());
        }
        sheetDatas.add(sheetDataResult);
        return "SUCCESS";
    }


    /**
     * 解析校验表头
     *
     * @param sheetRule 当前sheet的表头规则
     * @param datas     文件数据
     * @return
     */
    private boolean checkSheetTitles(SheetRule sheetRule, List<HashMap<String, String>> datas) {
        List<List<SheetTitle>> sheetTitles = sheetRule.getSheetTitles();
        List<CellRule> cellRules = sheetRule.getCellRules();
        if (!CollectionUtils.isEmpty(sheetTitles)) {
            //根据文件的表头更新,数据所在列,用于后续的数据组装
            List<CellRule> dynamicCellRule = new ArrayList<>();
            //遍历模板表头的第一行
            for (int cl = 0; cl < sheetTitles.get(0).size(); cl++) {
                //单个空格的title值
                SheetTitle sheetTitle = sheetTitles.get(0).get(cl);
                //文件中的数据
                HashMap<String, String> titleRow = datas.get(0);
                boolean findTitle = false;
                int columnIndex = 0;
                if (titleRow != null) {
                    //文件中的数据
                    Iterator<String> titleKye = titleRow.keySet().iterator();
                    //通过遍历文件中的表头寻找title的值
                    while (titleKye.hasNext()) {
                        String titleColumn = titleKye.next();
                        String titleValue = titleRow.get(titleColumn);
                        //找到文件中第一行中的表头
                        if (sheetTitle.getTitleValue().equals(titleValue)) {
                            sheetTitle.setColumnIndex(Integer.parseInt(titleColumn));
                            findTitle = true;
                            columnIndex = Integer.parseInt(titleColumn);
                            //循环比较同一列的所有表头(其它行)
                            for (int i = 1; i < sheetTitles.size(); i++) {
                                if (!sheetTitles.get(i).get(cl).getTitleValue().equals(datas.get(i).get(titleColumn))) {
                                    return false;
                                }
                            }
                            break;
                        }
                    }
                }
                //当这个表头是必须的,同时不存在,则返回表头检验不合格
                if (sheetTitle.isRequire() && !findTitle) {
                    return false;
                }
                //从文件中找到表头,做标记处理
                if (findTitle) {
                    //获取和标题对应的解析列规则,重新修改列坐标,加个判定防止数组越界错误
                    if (cl < cellRules.size()) {
                        CellRule cellRule = cellRules.get(cl);
                        cellRule.setColumnIndex(columnIndex);
                        dynamicCellRule.add(cellRule);
                    }
                }
            }
            //把dynamicCellRule中的值赋给cellRules,用于后续的数据组装
            cellRules.clear();
            cellRules.addAll(dynamicCellRule);
        }
        return true;
    }

    /**
     * 校验该单元格的数据是否合法
     *
     * @param cellRule 校验规则
     * @param value    值
     * @return
     */
    private static CheckCellInfo checkCelldata(CellRule cellRule, String value) {
        CheckCellInfo checkCellInfo = null;
        if (cellRule != null) {
            checkCellInfo = cellRule.checkData(value);
        } else {
            checkCellInfo = new CheckCellInfo();
            checkCellInfo.setSuccess(true);
        }
        return checkCellInfo;
    }

    /**
     * 把数据转化为bean中的字段的数据类型
     *
     * @param field bean中的字段
     * @param data  数据
     * @return
     */
    private static Object transFiledData(Field field, Object data) {
        Object value = null;
        String fileType = field.getType().getName();
        fileType = fileType.substring(fileType.lastIndexOf(".") + 1);
        if (data != null && !StringUtils.isEmpty(String.valueOf(data))) {
            try {
                switch (fileType) {
                    case "String":
                        value = String.valueOf(data);
                        break;
                    case "int":
                        value = Integer.parseInt(String.valueOf(data));
                        break;
                    case "Short":
                        value = Short.parseShort(String.valueOf(data));
                        break;
                    case "Integer":
                        value = Integer.parseInt(String.valueOf(data));
                        break;
                    case "double":
                        value = Double.parseDouble(String.valueOf(data));
                        break;
                    case "float":
                        value = Float.parseFloat(String.valueOf(data));
                        break;
                    case "Date":
                        String format = "yyyy-MM-dd HH:mm:ss";
                        if (!String.valueOf(data).contains(":")) {
                            if (String.valueOf(data).contains("/")) {
                                format = "yyyy/MM/dd";
                            } else {
                                format = "yyyy-MM-dd";
                            }
                        } else {
                            if (String.valueOf(data).contains("/")) {
                                format = "yyyy/MM/dd HH:mm:ss";
                            }
                        }
                        SimpleDateFormat sdf = new SimpleDateFormat(format);
                        ;
                        value = sdf.parse(String.valueOf(data));
                        break;
                    case "boolean":
                        value = Boolean.parseBoolean(String.valueOf(data));
                        break;
                    case "char":
                        value = String.valueOf(data).charAt(0);
                        break;
                    case "long":
                        value = Long.parseLong(String.valueOf(data));
                        break;
                    case "Long":
                        value = Long.parseLong(String.valueOf(data));
                        break;
                    default:
                        value = data;
                        break;
                }
            } catch (Exception e) {
                System.out.println("数据转换异常!");
                e.printStackTrace();
            }
        }
        return value;
    }

    /**
     * 获取当前sheet的校验规则
     *
     * @param sheetrules
     * @param sheetIndex
     * @return
     */
    private SheetRule getSheetRule(List<SheetRule> sheetrules, int sheetIndex) {
        if (sheetrules != null && sheetrules.size() > 0) {
            for (SheetRule sheetRule : sheetrules) {
                if (sheetRule.getSheetIndex() == sheetIndex) {
                    return sheetRule;
                }
            }
        }
        return null;
    }

}

三、SheetRuleUtil 类

  • 解析xml配置文件,获取Excel的解析规则
package org.example.ljj.util;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.example.ljj.util.model.*;
import org.example.ljj.util.enums.DataType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.*;

/**
 * @ClassName: AnaylisisXml
 * @Description: 解析xml配置文件
 * @author: ljj
 * @date: 2018-9-5 上午8:50:07
 */

public class SheetRuleUtil {
    private static final Logger logger = LoggerFactory.getLogger(SheetRuleUtil.class);

    /**
     * 读取xml文件得到配置规则
     * @param in 文件输入流
     * @return
     */
    public static List<SheetRule> analysiXml(InputStream in) {
        // 解析xml生成对应的bean
        SAXReader saxReader = new SAXReader();
        List<SheetRule> sheetRules = new ArrayList<SheetRule>();
        try {
            if (in != null) {
                Document document = saxReader.read(in);
                Element rootElement = document.getRootElement();
                Iterator<Element> sheets = rootElement.element("sheets").elements().iterator();
                while (sheets.hasNext()) {
                    Element sheet = sheets.next();
                    //解析sheet规则
                    SheetRule sheetRule = analysisSheetRule(sheet);
                    int startColumn = sheetRule.getStartColumn();
                    //解析sheet数据规则
                    List<CellRule> cellRules = analysisCellRules(sheet, startColumn);
                    sheetRule.setCellRules(cellRules);
                    //解析字典表
                    HashMap<String, HashMap<String, String>> dictionary = analysisDictionary(sheet);
                    sheetRule.setDictionary(dictionary);
                    //解析表头标题数据
                    List<List<SheetTitle>> sheetTitles = analysisSheetTitle(sheet);
                    sheetRule.setSheetTitles(sheetTitles);
                    sheetRules.add(sheetRule);
                }
            }
        } catch (Exception e) {
            logger.error("解析xml配置异常", e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sheetRules;
    }

    /**
     * @param sheet
     * @return
     * @return SheetRule
     * @Title: analysisSheetRule
     * @Description: 解析sheet规则
     */
    private static SheetRule analysisSheetRule(Element sheet) {
        Boolean isCommon = Boolean.valueOf(sheet.attributeValue("isCommon"));
        int sheetIndex = Integer.parseInt(sheet.attributeValue("sheetIndex"));
        int startRow = Integer.parseInt(sheet.attributeValue("startRow"));
        int startColumn = Integer.parseInt(sheet.attributeValue("startColumn"));
        int columnSize = Integer.parseInt(sheet.attributeValue("columnSize"));
        String sheetName = sheet.attributeValue("sheetName");
        String mapBean = sheet.attributeValue("mapBean");
        SheetRule sheetRule = new SheetRule(sheetIndex, startRow, startColumn, columnSize, null, isCommon);
        sheetRule.setSheetName(sheetName);
        sheetRule.setMapBean(mapBean);
        return sheetRule;
    }

    /**
     * @param sheet
     * @return
     * @return SheetRule
     * @Title: analysisSheetRule
     * @Description: 解析sheet数据规则
     */
    private static List<CellRule> analysisCellRules(Element sheet, int startColumn) {
        Iterator<Element> cells = sheet.element("cells").elements().iterator();
        List<CellRule> cellRules = new ArrayList<CellRule>();
        int colIndex = 0;
        while (cells.hasNext()) {
            Element cell = cells.next();
            String cellName = cell.attributeValue("cellName");
            boolean notNull = "true".equals(cell.attributeValue("notNull")) ? true : false;
            String mapColumn = cell.attributeValue("mapColumn");
            String beanFiled = cell.attributeValue("beanFiled");
            String dataType = cell.attributeValue("dataType");
            String transformDicName = cell.attributeValue("transformDicName");
            boolean isMulti = "true".equals(cell.attributeValue("isMulti")) ? true : false;
            String multiSplit = cell.attributeValue("multiSplit");
            String reJoinSplit = cell.attributeValue("reJoinSplit");
            String labelTypeCode = cell.attributeValue("labelTypeCode");
            CellRule cellRule = null;
            switch (DataType.getCodeValue(dataType)) {
                case 1:
                    try {
                        int sLeg = Integer.parseInt(cell.attributeValue("maxLength"));
                        boolean checkIllegalChar = "false".equals(cell.attributeValue("checkIllegalChar")) ? false : true;
                        cellRule = new StringCellRule(cellName, notNull, mapColumn, beanFiled, sLeg, checkIllegalChar);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case 2:
                    int maxLength = Integer.parseInt(cell.attributeValue("maxLength"));
                    cellRule = new IntegerCellRule(cellName, notNull, mapColumn, beanFiled, maxLength);
                    break;
                case 3:
                    int maxLg = Integer.parseInt(cell.attributeValue("maxLength"));
                    int decimalLength = Integer.parseInt(cell.attributeValue("decimalLength"));
                    cellRule = new DoubleCellRule(cellName, notNull, mapColumn, beanFiled, maxLg, decimalLength);
                    break;
                case 4:
                    cellRule = new DateCellRule(cellName, notNull, mapColumn, beanFiled);
                    break;
                case 5:
                    cellRule = new DateTimeCellRule(cellName, notNull, mapColumn, beanFiled);
                    break;
                case 6:
                    String expression = cell.attributeValue("expression");
                    cellRule = new RegularCellRule(cellName, notNull, mapColumn, beanFiled, expression);
                    cellRule.setIsMulti(isMulti);
                    cellRule.setMultiSplit(multiSplit);
                    cellRule.setLabelTypeCode(labelTypeCode);
                    cellRule.setReJoinSplit(reJoinSplit);
                    break;
            }
            ;
            if (cell != null) {
                cellRule.setTransformDicName(transformDicName);
            }
            cellRule.setColumnIndex(startColumn + colIndex);
            cellRules.add(cellRule);
            colIndex++;
        }
        return cellRules;
    }

    /**
     * @param sheet
     * @return
     * @return HashMap<String, HashMap < String, Object>> (这里用一句话描述返回结果说明)
     * @Title: analysisDictionary
     * @Description: 解析字典表
     */
    private static HashMap<String, HashMap<String, String>> analysisDictionary(Element sheet) {
        HashMap<String, HashMap<String, String>> dicsMap = new HashMap<String, HashMap<String, String>>();
        Element dicsElement = sheet.element("dics");
        if (dicsElement != null) {
            Iterator<Element> dics = dicsElement.elements().iterator();
            while (dics.hasNext()) {
                Element dic = dics.next();
                String dicName = dic.attributeValue("name");
                Iterator<Element> kv = dic.elements().iterator();
                HashMap<String, String> dicMap = new HashMap<String, String>();
                while (kv.hasNext()) {
                    Element dicElementData = kv.next();
                    String key = dicElementData.attributeValue("key");
                    String value = dicElementData.getTextTrim();
                    dicMap.put(key, value);
                }
                dicsMap.put(dicName, dicMap);
            }
        }
        return dicsMap;
    }

    /**
     * @param sheet
     * @return
     * @return List<SheetTitle>
     * @Title: analysisSheetTitle
     * @Description: 解析表头标题数据
     */
    private static List<List<SheetTitle>> analysisSheetTitle(Element sheet) {
        //存储多行表头
        List<List<SheetTitle>> sheetTitles = new LinkedList<>();
        Element titlesElements = sheet.element("titles");
        if (titlesElements != null) {
            Iterator<Element> titles = titlesElements.elements().iterator();
            while (titles.hasNext()) {
                //存储单行表头
                List<SheetTitle> list = new LinkedList<>();
                Element title = titles.next();
                //获取行号,从0开始
                int rowIndex = Integer.parseInt(title.attributeValue("rowIndex"));
                Iterator<Element> texts = title.elements().iterator();
                while (texts.hasNext()) {
                    Element value = texts.next();
                    int colIndex = Integer.parseInt(value.attributeValue("columnIndex"));
                    String titleValue = value.getTextTrim();
                    SheetTitle sheetTitle = new SheetTitle(rowIndex, colIndex, titleValue);
                    //默认为true,如果不写require属性
                    boolean require = "false".equals(value.attributeValue("require")) ? false : true;
                    sheetTitle.setRequire(require);
                    list.add(sheetTitle);
                }
                sheetTitles.add(list);
            }
        }
        return sheetTitles;
    }

}

其他

SheetContentsHandler 使用讲解

  • SheetContentsHandler 使用讲解,Excel表格文件处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/556913.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot多数据源(五)

SpringBoot多数据源-集成多个mybatis框架 1.基本框架2.使用2.1项目结构2.2 依赖导入2.3 application.yml配置2.4 创建读与写的SqlSessionFactoryBean 3.总结 1.基本框架 通过启动多个SqlSessionFactoryBean&#xff0c;每个SqlSessionFactoryBean对应一个datasource和指定位置的…

【计算机毕业设计】点餐平台网站——后附源码

&#x1f389;**欢迎来到琛哥的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 琛哥&#xff0c;一名来自世界500强的资深程序猿&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 琛哥在深度学习任务中展现出卓越的能力&a…

吴恩达2022机器学习专项课程(一) 6.1 动机第三周课后实验:Lab1使用逻辑回归进行分类

问题预览/关键词 回归和分类的区别&#xff1f;逻辑回归的作用是&#xff1f;什么是二分类问题&#xff1f;二分类问题案例如何表达二分类的结果&#xff1f;逻辑回归通常用哪种表达形式&#xff1f;什么是正样本和负样本&#xff1f;什么是阈值&#xff1f;可视化线性回归解决…

什么台灯对眼睛好?揭秘央视315推荐的护眼灯

目前很多家长都纠结这个问题&#xff0c;那就是孩子上学以后要怎么保护眼睛&#xff0c;晚上写作业用什么台灯对比较好一点&#xff1f;我建议最好选择一款合格、专业的护眼台灯&#xff0c;因为市面上大多数台灯都是没有专业光源技术&#xff0c;甚至部分廉价台灯还会使用低成…

Linux 网络基本命令

一、查看网络信息 ifconfig 二、关闭网络 ifdown ens33 (有的电脑不一定是ens33&#xff0c;具体看上图画线的地方) 三、开启网络 ifup ens33

【Canvas与艺术】绘制绿圈三红五星Premium Quality标志

【说明】 构图简约但美观。 【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>使用HTML5/Canvas绘制绿圈三红五星Prem…

JavaWeb--前端工程化

目录 1. 前端工程化 1.1. 概述 1.2. 前端工程化实现技术栈 2. ECMA6Script 2.1. es6的介绍 2.2. es6 变量 / 模版字符串 2.2.1. let 与 var 的差别 2.2.2. const 与 var 的差异 2.2.3. 模板字符串 2.3. 解构表达式 / 赋值 2.3.1. 数组解构赋值 2.3.2. 对象解构赋值 …

2024年分享酷我音乐如何下载mp3的方法

这里教大家用酷我音乐小程序的下载方法,小程序下载资源的方法有3种 1.利用专业的抓包工具(Fiddler/Charles)进行获取,然后分析数据包,最后直接用下载器下载分析出来的链接。强烈不推荐,因为大部分人并非程序员出身 2.录屏,录屏效率太慢,所以也不推荐 3. 利用专门的下载资源的…

微纤维眼镜清洁布的革命性进化

在日常生活中&#xff0c;眼镜是许多人不可或缺的日常用品&#xff0c;无论是视力矫正还是防护眼睛免受阳光的伤害。然而&#xff0c;眼镜的清洁常常是一个令人头疼的问题&#xff0c;特别是在面对指纹、灰尘和其他污垢时。传统的清洁方法往往需要化学清洁剂&#xff0c;不仅繁…

【css】select实现placeholder效果

场景&#xff1a;使用select下拉选择框的时候&#xff0c;需要像其他控件一样提示默认信息。 问题&#xff1a;表单控件select没有placeholder属性。 解决方案&#xff1a;通过css实现&#xff0c;不需要js <style>select > option[disabled]{ color:#999;cursor: n…

如何用Python构建一个生产级别的电影推荐系统 - 机器学习手册

构建项目是彻底学习概念并发展必要技能的最有效方式之一。 项目使您沉浸在现实世界的问题解决中&#xff0c;巩固您的知识&#xff0c;并培养批判性思维、适应能力和项目管理专业知识。 本指南将带您逐步构建一个根据用户喜好量身定制的电影推荐系统。我们将利用一个庞大的包…

Homebrew安装与卸载

卸载 /bin/bash -c "$(curl -fsSL https://gitee.com/ineo6/homebrew-install/raw/master/uninstall.sh)"安装 /bin/bash -c "$(curl -fsSL https://gitee.com/ineo6/homebrew-install/raw/master/install.sh)"1、复制命令到命令行执行&#xff0c;输入1…

多模态中的视觉编码器clip以及输入分辨率

在多模态的视觉编码主干中&#xff0c;若采用分类的backbone效果很差&#xff0c;经过语义对齐的backbone&#xff0c;比如clip的vit&#xff0c;效果则好很多。 1.Cogvlm中的EVA2-CLIP-E&#xff0c;VIT中最后一层被移除&#xff0c;4.4B&#xff0c;支持分辨率为334/490. 2.…

[源码分享]基于Unity的Live2D虚拟人物——结合了GPT、Azure、情绪识别和口型同步,也可以集合苹果Vision Pro做成3D的形象

# 技术文档 ## 1 项目简介 ### 项目目录 ``` Assets ├─ Animator // 动画 ├─ Code // 代码 │ ├─ AI // AI 模块 │ │ ├─ LM // 语言模型模块 │…

Python爬虫数据可视化分析

Python爬虫用于从网络上获取数据&#xff0c;数据可视化分析则是将获取的数据进行可视化展示和分析&#xff0c;帮助我们更好地理解数据、发现规律、做出决策。下面是一个基本的Python爬虫数据可视化分析的流程&#xff1a; 步骤一&#xff1a;数据爬取 1.选择合适的爬虫工具&a…

使用PL\SQL将Excel表格导入到oracle数据库中

因为要测试生产问题&#xff0c;需要把生产上oracle导出数据导入到测试环境oracle数据库中&#xff0c;尝试了N种方法&#xff0c;发现使用PL\SQL 的ODBC 方法比较好用 1、开始 首先使用plsqldev里面的&#xff0c;工具--》下面的odbc导入器 2、配置 点击之后&#xff0c;会…

LUA脚本判断是否为空

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Lua是一个小巧的脚…

MOS产品在储能上的应用分析与推荐

电化学储能可与光伏、风电等新能源发电相结合&#xff0c;缓解可再生能源稳定性差的问题。同时&#xff0c;电化学储能可提供调峰、调频、AGC、黑启动等辅助服务&#xff0c;保障电网安全。此外&#xff0c;电化学储能可以起到削峰填谷的作用&#xff0c;为住宅、工业和商业用户…

阻塞队列(模拟+生产者消费者)

阻塞队列 字面意思&#xff0c;带有阻塞功能的队列&#xff0c;满足队列先进先出的性质 作用&#xff1a; 1.如果队列为空&#xff0c;此时执行出队列操作&#xff0c;就会阻塞&#xff0c;直到往此队列里添加元素为止&#xff08;队列不为空&#xff09; 2.如果队列为满&#…

GIS地理信息平台+智慧巡检技术解决方案(Word原件)

1.系统概述 1.1.需求描述 1.2.需求分析 1.3.重难点分析 1.4.重难点解决措施 2.系统架构设计 2.1.系统架构图 2.2.关键技术 3.系统功能设计 3.1.功能清单列表软件全套精华资料包清单部分文件列表&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项…