如何使用Java 实现excel模板导出---多sheet导出?

news2024/11/25 3:01:41

实现多个sheet的excel导出功能

效果展示:
在这里插入图片描述

maven依赖

<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.17</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.17</version>
		</dependency>

相关工具类
**此处省略异常处理类

ExcelReportUtil 类


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

import java.math.BigDecimal;
import java.util.*;

/**
 * 
* @ClassName: ExcelReportUtil 
* @Description: excel导出工具类 
* @version v1.0
 */
public class ExcelReportUtil {
	
	private static Log logger = LogFactory.getLog(ExcelReportUtil.class);
	
	/**
	 * clone the height, cells and cellRangeAddress to destRow from srcRow
	 * @param sheet
	 * @param srcRow
	 * @param destRow
	 */
	public static void cloneRow(Sheet sheet, Row srcRow, Row destRow) {
		if (sheet == null || srcRow == null || destRow == null)
			return;
		Set mergedRegions = new HashSet();
		destRow.setHeight(srcRow.getHeight());
		if (srcRow.getFirstCellNum() >= 0 && srcRow.getLastCellNum() >= 0) {
            for (int i = srcRow.getFirstCellNum(), j = srcRow.getLastCellNum(); i <= j; i++) {
				Cell srcCell = srcRow.getCell(i);
				Cell destCell = destRow.getCell(i);
                if (srcCell != null) {
                	logger.debug("cell is found at col[" + i + 
                			"], will be cloned to the destRow");
                    if (destCell == null) {
                        destCell = destRow.createCell(i);
                    }
                    cloneCell(srcCell, destCell);
                    CellRangeAddress mergedRegion = getMergedRegion(sheet, srcRow.getRowNum(),
                    		srcCell.getColumnIndex());
                    if (mergedRegion != null) {
                    	CellRangeAddress newMergedRegion = new CellRangeAddress(
                    			destRow.getRowNum(), 
                    			destRow.getRowNum() + mergedRegion.getLastRow() - mergedRegion.getFirstRow(), 
                    			mergedRegion.getFirstColumn(), 
                    			mergedRegion.getLastColumn());
                        if (isNewMergedRegion(newMergedRegion, mergedRegions)) {
                        	logger.debug("CellRangeAddress is found at col[" + i + 
                        			"], will be cloned to the destRow");
                            mergedRegions.add(newMergedRegion);
                            sheet.addMergedRegion(newMergedRegion);
                        }
                    }
                }
            }
		}
	}
	
	/**
	 * get the CellRangeAddress of sheet at [rowNum, colNum] if exists
	 * @param sheet
	 * @param rowNum
	 * @param colNum
	 * @return null if not exists
	 */
	public static CellRangeAddress getMergedRegion(Sheet sheet, int rowNum, int colNum) {
        for (int i = 0, c = sheet.getNumMergedRegions(); i < c; i++) {
            CellRangeAddress merged = sheet.getMergedRegion(i);
            if (isRangeContainsCell(merged, rowNum, colNum)) {
                return merged;
            }
        }
        return null;
    }
	
	/**
	 * to judge whether the CellRangeAddress includes the cell at [row, col]
	 * @param range
	 * @param row
	 * @param col
	 * @return 
	 * 	true if the CellRangeAddress includes the cell at [row, col]
	 */
    public static boolean isRangeContainsCell(CellRangeAddress range, int row, int col) {
        if ((range.getFirstRow() <= row) && (range.getLastRow() >= row)
                && (range.getFirstColumn() <= col)
                && (range.getLastColumn() >= col)) {
            return true;
        }
        return false;
    }
    
    /**
     * to judge if the CellRangeAddress is not included in mergedRegions,
     * using {@link #areRegionsEqual(CellRangeAddress, CellRangeAddress)} to compare
     * @param region
     * @param mergedRegions
     * @return 
     * 	true if the CellRangeAddress is not included in mergedRegions
     */
    private static boolean isNewMergedRegion(CellRangeAddress region,
            Collection mergedRegions) {
        for (Iterator iterator = mergedRegions.iterator(); iterator.hasNext();) {
            CellRangeAddress cellRangeAddress = (CellRangeAddress) iterator.next();
            if (areRegionsEqual(cellRangeAddress, region)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * compares region1 with region2
     * @param region1
     * @param region2
     * @return 
     * 	true if both of them are null or 
     * 	their firstColumn, lastColumn, firstRow and lastRow are all the same
     */
    public static boolean areRegionsEqual(CellRangeAddress region1,
            CellRangeAddress region2) {
        if ((region1 == null && region2 != null)
                || (region1 != null && region2 == null)) {
            return false;
        }
        if (region1 == null) {
            return true;
        }
        return (region1.getFirstColumn() == region2.getFirstColumn()
                && region1.getLastColumn() == region2.getLastColumn()
                && region1.getFirstRow() == region2.getFirstRow() 
                && region2.getLastRow() == region2.getLastRow());
    }
    
    /**
     * clone the style and value to destCell from srcCell
     * @param srcCell
     * @param destCell
     */
    public static void cloneCell(Cell srcCell, Cell destCell) {
		if (srcCell == null || destCell == null)
			return;
		destCell.setCellStyle(srcCell.getCellStyle());
		switch (srcCell.getCellTypeEnum()) {
			case NUMERIC :
				destCell.setCellValue(srcCell.getNumericCellValue());
				break;
			case STRING :
				destCell.setCellValue(srcCell.getRichStringCellValue());
				break;
			case FORMULA :
				destCell.setCellFormula(srcCell.getCellFormula());
				break;
			case ERROR:
				destCell.setCellErrorValue(srcCell.getErrorCellValue());
				break;
			case BOOLEAN:
				destCell.setCellValue(srcCell.getBooleanCellValue());
				break;
			default :
				destCell.setCellType(CellType.BLANK);
				break;
		}
	}
    
    /**
     * Set a value for the cell.
     * Value whose type is {@link Calendar}, {@link Date}, {@link Number}, {@link String}
     * is supported directly, otherwise will be processed as string.
     * @param cell
     * @param value
     */
    public static void setCellValue(Cell cell, Object value) {
    	if (cell == null)
    		return;
    	if (value == null) {
    		cell.setCellType(CellType.BLANK);
    	} else if (value instanceof Calendar) {
    		cell.setCellValue((Calendar) value);
    	//Date格式化日期输出
		} else if (value instanceof Date) {
			//cell.setCellValue((Date) value);
			//cell.setCellValue(BaseUtils.Date2String((Date)value, CommonConstants.FORMAT_Date));
			cell.setCellValue(BaseUtils.Date2String((Date)value, "yyyy-MM-dd HH:mm:ss"));
		} else if (value instanceof Number) {
			setCellValue(cell, (Number) value);
		} else if (value instanceof String) {
			cell.setCellValue((String) value);
		} else {
			logger.warn("value type [" + value.getClass().getName() + 
					"] is not directly supported, will be processed as String");
			cell.setCellValue((String) value.toString());
		}
    }
	
    /**
     * set a number value for the cell
     * @param cell
     * @param value
     * @throws XLSReportException
     * 	if the Number can not be unwrapped
     */
	private static void setCellValue(Cell cell, Number value) {
		double doubleContent = 0.0;
		if (value instanceof Byte) {
			doubleContent = (Byte) value;
		} else if (value instanceof Double) {
			doubleContent = (Double) value;
		} else if (value instanceof Float) {
			doubleContent = (Float) value;
		//BigDecimal转换为Double
		}else if (value instanceof BigDecimal) {
			doubleContent = TypeCaseHelper.convert2Double(value);
		} else if (value instanceof Integer) {
			float tmp = (Integer) value;
			doubleContent = tmp;
		} else if (value instanceof Long) {
			float tmp = (Long) value;
			doubleContent = tmp;
		} else if (value instanceof Short) {
			short tmp = (Short) value;
			doubleContent = tmp;
		} else {
			throw new XLSReportException("value type [" + value.getClass().getName() + 
					"] can not be processed as double");
		}
		cell.setCellValue(doubleContent);
	}
	
	/**
	 * get the string value of a cell
	 * @param cell
	 * @return "" if type of the cell is not in 
	 * 	{CELL_TYPE_NUMERIC, CELL_TYPE_STRING and CELL_TYPE_BOOLEAN}
	 * @see Cell#CELL_TYPE_BLANK
     * @see Cell#CELL_TYPE_NUMERIC
     * @see Cell#CELL_TYPE_STRING
     * @see Cell#CELL_TYPE_FORMULA
     * @see Cell#CELL_TYPE_BOOLEAN
     * @see Cell#CELL_TYPE_ERROR
	 */
	public static String getCellStringValue(Cell cell) {
		String cellStringValue = null;
		switch (cell.getCellTypeEnum()) {
			case NUMERIC:
				cellStringValue = cell.getNumericCellValue() + "";
				break;
			case STRING:
				cellStringValue = cell.getStringCellValue();
				break;
			case BOOLEAN:
				cellStringValue = cell.getBooleanCellValue() + "";
				break;
			default :
				logger.warn("can not get the string value of a cell whose type is " + cell.getCellTypeEnum());
				cellStringValue = "";
				break;
		}
		return cellStringValue;
	}
	
	/**
	 * remove a comment from sheet
	 * @param sheet
	 * @param comment
	 */
	public static void removeComment(Sheet sheet, Comment comment) {
		if (sheet != null && comment != null) {
			sheet.getRow(comment.getRow())
				.getCell(comment.getColumn())
				.removeCellComment();
		}
	}
	
}

excel 接口


import org.apache.poi.ss.usermodel.Sheet;
import java.util.Map;

/**
 * 
* @ClassName: ExcelProcessor 
* @Description: 自定义的excel接口
* @author huali
* @version v1.0
 */
public interface ExcelProcessor{
	
	/**
	 * initialize the CommentProcessor
	 */
	void init();
	

	boolean isInited();
	
	/**
	 * 
	* @Title: process 
	* @Description: fill the XLS sheet by data 
	* @param @param sheet
	* @param @param dataSource
	* @return void
	 */
	void process(Sheet sheet, Map dataSource);
}

实现类

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.ognl.Ognl;
import org.apache.ibatis.ognl.OgnlException;
import org.apache.poi.ss.usermodel.*;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Implementation of {@link ExcelProcessor},
 * it fills a list in the XLS horizontally.
 * Besides 'type', 'expression', 'firstIndex' and 'dataMapping' are added to finish that,
 * 1) expression, mandatory, a OGNL expression, is used to get the list from XLS data
 * 2) firstIndex, mandatory, the beginning row index of filling list
 * 3) dataMapping, mandatory, a Map<Integer, String> value,
 * 		whose key is the cell column index and value is a OGNL expression to
 * 		get the cell value from list element.
 * In filling, the list element is transfered by {@link ExcelDataSource},
 * and the index of element is put in the transfered data as key 'index'.
 * A typical configuration is like this,
 * { type : 'I', expression : 'students', dataMapping : { 1 : 'index', 2 : 'name'...} }
 *
 */
public class ExcelIteratorNoLastRowProcessor implements ExcelProcessor {
//填充类型
	public static String TYPE_ID = "I";

	private static Log logger = LogFactory.getLog(ExcelIteratorNoLastRowProcessor.class);

	private boolean inited;
//批注
	private final Comment comment;
//填充数据的名称
	private String expression;
//从第几行开始填充
	private int firstIndex;
//填充的数据
	private Map<Integer, String> dataMapping;

	public ExcelIteratorNoLastRowProcessor(Comment comment) {
		this.comment = comment;
	}

	public String getExpression() {
		return expression;
	}

	public void setExpression(String expression) {
		this.expression = expression;
	}

	public int getFirstIndex() {
		return firstIndex;
	}

	public void setFirstIndex(int firstIndex) {
		this.firstIndex = firstIndex;
	}

	public Map<Integer, String> getDataMapping() {
		return dataMapping;
	}

	public void setDataMapping(Map<Integer, String> dataMapping) {
		this.dataMapping = dataMapping;
	}

	@Override
	public void init() {
		try {
			Map<String, Object> classMap = new HashMap<String, Object>();
			classMap.put("dataMapping", Map.class);
			Map<String, Object> cfg = JSON.parseObject(this.comment.getString().toString(),Map.class);
			Object expresionCfg = cfg.get("expression");
			Object firstIndexCfg = cfg.get("firstIndex");
			Object dataMappingCfg = cfg.get("dataMapping");
			if (expresionCfg == null || !(expresionCfg instanceof String)) {
				throw new XLSReportCfgException("expresion must be configured and its type must be String");
			}
			this.expression = (String) expresionCfg;
			if (firstIndexCfg == null || !(firstIndexCfg instanceof Integer)) {
				throw new XLSReportCfgException("firstIndex must be configured and its type must be Integer");
			}
			this.firstIndex = (Integer) firstIndexCfg;
			if (dataMappingCfg == null || !(dataMappingCfg instanceof Map)) {
				throw new XLSReportCfgException("dataMapping must be configured and its type must be Map");
			}
			this.dataMapping = (Map<Integer, String>) dataMappingCfg;
			this.inited = true;
		} catch (JSONException e) {
			throw new XLSReportCfgException("the comment configuration at [" +
					comment.getRow() + "," + comment.getColumn() + "] " + comment.getString().toString() +
					" is error", e);
		}
	}

	@Override
	public boolean isInited() {
		return this.inited;
	}

	@Override
	public void process(Sheet sheet, Map dataSource) {
		try {
			if (!isInited())
				throw new XLSReportException("the CommentProcessor has not inited yet");
				//从dataSource中找到填充目标名称
			Object content = Ognl.getValue(this.expression, dataSource);
			if (content == null) {
				content = Collections.EMPTY_LIST;
			}
			if (!(content instanceof Iterable)) {
				content = Arrays.asList(content);
			}
			int index = 0;
			boolean isAddRow = false;
			for (Object element : (Iterable) content) {
				//clone row
				logger.debug("clone the row at index[" + (this.firstIndex + index + 1) + "] to the new row at index[" + (this.firstIndex + index) + "]");
				ExcelReportUtil.cloneRow(sheet, sheet.getRow(this.firstIndex + index + 1), sheet.createRow(this.firstIndex + index));
				//获取填充行
				Row aimedRow = sheet.getRow(this.firstIndex + index);
				//fill data
				for (Integer key : this.dataMapping.keySet()) {
					int cellIndex = key;
					//获取第一行的数据
					Map rowDS = new ExcelDataSource(element).getData();
					rowDS.put("index", index);
					Cell aimedCell = aimedRow.getCell(cellIndex);
					if (aimedCell == null)
						aimedCell = aimedRow.createCell(cellIndex);
						//找到列对应的数据
					Object value = Ognl.getValue(this.dataMapping.get(key), rowDS);
					//样式
					if(Boolean.parseBoolean(rowDS.get("isBolded") == null ? "":rowDS.get("isBolded").toString())){
						Workbook workbook = sheet.getWorkbook();
						CellStyle cellStyle = workbook.createCellStyle();
						Font font = workbook.createFont();
						//font.setBoldweight(Font.BOLDWEIGHT_BOLD);
						font.setBold(true);
						cellStyle.setFont(font);
						aimedCell.setCellStyle(cellStyle);
					}
					logger.debug("set the value of cell[" + (this.firstIndex + index) + ", " + cellIndex + "] to " + value);
					//给列填值
					ExcelReportUtil.setCellValue(aimedCell, value);
				}
				index++;
			}
			//remove comment
			ExcelReportUtil.removeComment(sheet, this.comment);
		} catch (OgnlException e) {
			throw new XLSReportException("extracting data error while using OGNL expression[" +
					this.expression + "] with root object : " + dataSource);
		}
	}
}

excel填充数据处理类


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Implementation of XLSReportDataSource, which is constructed by a original bean.
 * The original bean will be processed as following,
 * 1. Collections.emptyMap() if it is null
 * 2. used directly if its type is Map
 * 3. otherwise it will be transformed to Map, {@link #transformPropertiesToMap(Object)}
 */
public class ExcelDataSource  {
	
	private static Log logger = LogFactory.getLog(ExcelDataSource.class);
	
	/**
	 * the original bean 
	 */
	private Object dataSource;
	
	public ExcelDataSource(Object dataSource) {
		this.dataSource = dataSource;
	}
	
	public Map getData() {
		Map ds = null;
		if (this.dataSource == null) {
			ds = Collections.emptyMap();
		} else if (this.dataSource instanceof Map) {
			ds = (Map) this.dataSource;
		} else {
			logger.debug("the type of dataSource is [" + dataSource.getClass() + 
					"], will be transformed to Map");
			ds = transformPropertiesToMap(this.dataSource);
		}
		return ds;
	}
	
	/**
	 * Used locally to transform a bean to Map.
	 * The property names are transformed to the keys,
	 * theirs values are transformed to the value of the corresponding key.
	 * Besides, the property named 'class' is excluded.
	 * @param bean
	 * @return
	 */
	private Map transformPropertiesToMap(Object bean) {
		Map properties = new HashMap();
		BeanInfo beanInfo;
		try {
			beanInfo = Introspector.getBeanInfo(bean.getClass());
			PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
			for (PropertyDescriptor pd : pds) {
				if (!"class".equals(pd.getName())) {
					properties.put(pd.getName(), pd.getReadMethod().invoke(bean));
				}
			}
		} catch (Exception e) {
			throw new XLSReportException(e);
		}
		return properties;
	}

}

excel填充处理类

import com.alibaba.fastjson.JSON;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.usermodel.*;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
* @ClassName: ExcelReportFiller 
* @Description: 读取模板数据处理
* @version v1.0
 */
public class ExcelReportFiller {
	
	private static final Log logger = LogFactory.getLog(ExcelReportFiller.class);
	
	public void fill(Workbook template, Map dataSource) {
		int sheetCount = template.getNumberOfSheets();
		for (int i = 0; i < sheetCount; i++) {
			logger.debug("scan the sheet at index[" + i + "]");
			fillSheet(template.getSheetAt(i), dataSource);
		}
	}
	
	public void fillSheetName(String sheetName, Workbook template,
			Map dataSource) {
		logger.debug("scan the sheet at [" + sheetName + "]");
		fillSheet(template.getSheet(sheetName), dataSource);
	}
	
	/**
	 * fill the XLS sheet by data
	 * @param sheet 模板template
	 * @param dataSource
	 */
	private void fillSheet(Sheet sheet, Map dataSource) {
		int rowCount = sheet.getLastRowNum();
		for (int i = 0; i <= rowCount; i++) {
			Row row = sheet.getRow(i);
			if (row != null) {
				int cellCount = row.getLastCellNum();
				for (int j = 0; j <= cellCount; j++) {
					Cell cell = row.getCell(j);
					if (cell != null ) {
						Comment comment = cell.getCellComment();
						if (comment != null) {
							logger.debug("comment is found at [" + i + ", " + j + "]");
							ExcelProcessor processor = ExcelProcessorFactory.getCommentProcessor(comment);
							processor.process(sheet, dataSource);
							//refresh rowCount
							rowCount = sheet.getLastRowNum();
						}
					}
				}
			}
		}
	}
}

excel模板处理


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
 * 
* @ClassName: ExcelReportTemplate 
* @Description: 通过模板创建流
* @version v1.0
 */
public class ExcelReportTemplate  {
	
	private static final Log logger = LogFactory.getLog(ExcelReportTemplate.class);
	
	private final String path;

	private ClassLoader classLoader;
	
	/**
	 * 
	 * @param path
	 */
	public ExcelReportTemplate(String path) {
		this(path, (ClassLoader) null);
	}
	
	/**
	 * 
	 * @param path
	 * @param classLoader
	 */
	public ExcelReportTemplate(String path, ClassLoader classLoader) {
		if (path == null) {
			throw new IllegalArgumentException("Path must not be null");
		}
		this.path = path;
		if (classLoader == null) {
			try {
				classLoader = Thread.currentThread().getContextClassLoader();
			} catch (Throwable ex) {
				logger.debug("Cannot access thread context ClassLoader - falling back to system class loader", ex);
				classLoader = ExcelReportTemplate.class.getClassLoader();
			}
		}
		this.classLoader = classLoader;
	}
	
	
	public Workbook getTemplate() throws IOException, InvalidFormatException {
		InputStream is =new FileInputStream(this.path);
		if (is == null) {
			throw new FileNotFoundException(
					"class path resource [" + this.path + "] cannot be opened because it does not exist");
		}
		//return new HSSFWorkbook(is);
		Workbook workbook = WorkbookFactory.create(is);
		if(is != null){
			is.close();
		}
		return workbook;
	}
	

	public Workbook getTemplate(HttpServletRequest resquest) throws IOException, InvalidFormatException {
		InputStream is = this.classLoader.getResourceAsStream(this.path);
		if (is == null) {
			throw new FileNotFoundException(
					"class path resource [" + this.path + "] cannot be opened because it does not exist");
		}
		Workbook workbook = WorkbookFactory.create(is);
		if(is != null){
			is.close();
		}
		return workbook;
	}

}

实现关键代码展示
通过模板实现导出功能

 try {
            os = new FileOutputStream(excelPth);
            ExcelReportCreator.createXLS(new ExcelReportTemplate(excelTempletPath),
                    new ExcelDataSource(jsonMap),
                    new ExcelReportFiller(),
                    os);
            excelFilePathName = ftpPath + fileModel.getRealFileName();
        } catch (Exception e) {
            log.error("导出excel文件出错" + " excel文件路径=" + excelPth + " 模板路径=" + excelTempletPath, e);
            log.error("excel内容 " + jsonMap);
            throw e;
        } finally {
            if (os != null) {
                os.close();
            }
        }

ExcelReportCreator 中的代码

	
	/**
	 * 
	 * @param dataSource
	 * @param filler
	 * @param os
	 * @throws IOException
	 * @throws InvalidFormatException
	 */
	public static void createXLS(ExcelReportTemplate template,
			ExcelDataSource dataSource, ExcelReportFiller filler,
			OutputStream os) throws IOException, InvalidFormatException {
		Workbook workbook = template.getTemplate();
		filler.fill(workbook, dataSource.getData());
		workbook.write(os);
	}
	

导入数据案例展示
在这里插入图片描述
excel模板批注案例
每个sheet页都需要写批注,通过批注中的expression对应的值来判断是哪个sheet页的数据,从而进行填充。dataMapping中的key值指的是列序号,value值指的是填充的字段名称,通过名称找对应的数据。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

泛微E-Cology XXE漏洞复现(QVD-2023-16177)

0x01 产品简介 泛微协同管理应用平台E-Cology是一套兼具企业信息门户、知识文档管理、工作流程管理、人力资源管理、客户关系管理、项目管理、财务管理、资产管理、供应链管理、数据中心功能的企业大型协同管理平台。 0x02 漏洞概述 泛微e-cology某处功能点最初针对用户输入的…

STM32 点灯实现 7.18

嵌入式&#xff1a; 以应用为中心&#xff0c;以专用计算机为基础&#xff0c;软硬件可裁剪ARM A系列芯片&#xff1a;高端芯片&#xff0c;实现人机互动 R系列&#xff1a;实现时效性 M系列&#xff1a;低端芯片&#xff0c;控制硬件设备&#xff0c;灯&#xff0c;风扇....…

Springboot初识(一)

一.什么是Spring Boot Spring Boot是一个开源的、用于简化Spring应用程序开发的框架。它是Spring项目的一个子项目&#xff0c;旨在为Spring应用程序提供更快速、更便捷的开发体验。Spring Boot基于Spring框架&#xff0c;同时也整合了其他Spring项目和第三方库&#xff0c;使…

Unity-AssetBundle

一、AB 包介绍 ​ AB 包是特定于平台的资源压缩包&#xff0c;类似于压缩文件。其中资源可包括&#xff1a;模型、贴图、预设体、音效、材质球等等。 ​ 相较于 Resources 文件夹下的资源文件&#xff0c;AB 包能够更好管理资源&#xff1a; Resources 文件夹&#xff1a;打包…

【设计模式】23种设计模式——建造者模式Builder(原理讲解+应用场景介绍+案例介绍+Java代码实现)

介绍 建造者模式又叫生成器模式&#xff0c;是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别)&#xff0c;使这个抽象过程的不同实现方法可以构造出不同属性的对象建造者模式是一步一步创建一个复杂的对象&#xff0c;它允许用户只通过指定复杂对象的类型和…

【PHP面试题79】在Linux中如何设置MySQL和PHP服务开机启动

文章目录 &#x1f680;一、前言&#x1f680;二、设置MySQL服务开机启动&#x1f50e;2.1 打开终端&#x1f50e;2.2 编辑MySQL配置文件&#x1f50e;2.3 修改配置文件&#x1f50e;2.4 检查MySQL服务是否已启动&#x1f50e;2.5 设置MySQL服务开机启动 &#x1f680;三、设置…

C# Modbus通信从入门到精通(12)——Modbus ASCII协议原理

Modbus ASCII是串行链路上的协议,也就是说ModbusASCII是通过串口通信来实现的,它可以通过RS232、RS485物理层的接口来实现,同时它也是一个主从协议,在同一时间总线上只能有一个主站和一个或多个(最多247)个从站。Modbus通信总是由主站发起,从站没有接收到主站的请求时不…

NOAA国家强风暴实验室的天气雷达研究历史(1962年~2016年)

一、1962年-NSSP开始研究WSR-57 美国气象局国家严重风暴项目(NSSP)的一小群研究人员从堪萨斯城搬到俄克拉荷马州诺曼的天气雷达实验室,并开始研究最近安装的研究天气监视雷达-1957(WSR-57)。 二、1964年-NSSL开发的脉冲多普勒雷达技术 1956年,康奈尔航空实验室建造了一…

C++OpenCV(2):图像处理基础概念与操作

&#x1f506; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 &#x1f506; OpenCV项目地址及源代码&#xff1a;点击这里 文章目录 图形读取与显示加载图片显示图片打印图片信息保存图片 色彩模型转换RGB颜色模型HSV颜色模型HLS模型LAB模型 图像像素读写操作像素算数运…

python机器学习(二)特征工程、K-近邻算法、KNN工作流程、scikit-learn实现K近邻算法、K值选择、距离计算、KD树

特征工程 把特征转换为机器容易识别的数据&#xff0c;把特征a转化为机器容易读懂、量化的语言 归一化Min-Max 将原始数据映射到[0,1]之间 X ′ x − m i n m a x − m i n X \frac{x-min}{max-min} X′max−minx−min​ 但是归一化是有弊端的&#xff0c;比如有一个值错误…

OJ练习第142题——路径总和 II

113. 路径总和 II 力扣链接&#xff1a;113. 路径总和 II 题目描述 给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 Java代码&#xff08;深度优先搜…

基于linux下的高并发服务器开发(第三章)- 3.8 线程同步

sellticket.c /*使用多线程实现买票的案例。有3个窗口&#xff0c;一共是100张票。 */#include <stdio.h> #include <pthread.h> #include <unistd.h>// 全局变量&#xff0c;所有的线程都共享这一份资源。 int tickets 100;void * sellticket(void * arg)…

后处理材质球:黄金螺旋分割线和参考图

后处理材质球&#xff1a;黄金螺旋分割线和参考图 Begin Object Class/Script/UnrealEd.MaterialGraphNode Name"MaterialGraphNode_0"Begin Object Class/Script/Engine.MaterialExpressionLinearInterpolate Name"MaterialExpressionLinearInterpolate_1&qu…

(202307)wonderful-sql:初识数据库(task1)

学习知识 初识数据库 关系型数据库简介 特点是由行和列组成的二维表来管理数据&#xff0c;这种类型的 DBMS 称为关系数据库管理系统&#xff08;Relational Database Management System&#xff0c;RDBMS&#xff09;。本课程将向大家介绍使用 SQL 语言的数据库管理系统&am…

No5:学习过程中基础语法积累

文章目录 基础语法&#xff1a;对象对象构建和数据封装 集合列表截取输出&#xff08;特色是数据可变即可重新赋值&#xff09;元组截取输出&#xff08;元组特色是数据不可变&#xff09;字典&#xff08;根据key取value&#xff09; 字符串函数 基础语法&#xff1a;对象 对…

【动态规划part04】| 背包问题理论基础、416.分割等和子集

目录 &#x1f388;背包问题理论基础 &#x1f45c;01背包 ✨二维dp数组01背包 ✨一维dp数组01背包&#xff08;滚动数组&#xff09; &#x1f388;LeetCode416.分割等和子集 &#x1f388;背包问题理论基础 &#x1f45c;01背包 有n件物品和一个最多能背重量为w 的背…

AUTOSAR从入门到精通-【应用篇】基于 LIN 总线的汽车自动天窗防夹控制系统的设计与实现

目录 前言 天窗控制系统的 LIN 总线 2.1 LIN 总线概述 2.2 LIN 总线协议规范 2.3 防夹控制系统的 LIN 总线 2.4 系统 LIN 网络测试 天窗防夹控制系统整体设计方案 3.1 天窗防夹控制系统功能 3.2 控制系统总体设计 3.2.1 系统结构 3.2.2 天窗防夹控制器 3.2.3 天窗传…

小黑子—JavaWeb:第二章 Maven与MyBatis

JavaWeb入门2.0 1.Maven1.1 Maven 简介1.2 Maven 安装配置1.3 Maven 基本使用1.3.1 Maven常用命令1.3.2 Maven生命周期 1.4 IDEA 配置 Maven1.4.1 配置 Maven 环境1.4.2 Maven 坐标详情1.4.3 IDEA 创建Maven项目1.4.4 IDEA 导入Maven文件1.4.5 配置Maven-Helper 插件 1.5 依赖管…

逻辑斯特回归

*分类是离散的&#xff0c;回归是连续的 下载数据集 trainTrue&#xff1a;下载训练集 逻辑斯蒂函数保证输出值在0-1之间 能够把实数值映射到0-1之间 导函数类似正态分布 其他饱和函数sigmoid functions 循环神经网络经常使用tanh函数 与线性回归区别 塞戈马无参数&#x…

《嵌入式 - 工具》J-link读写MCU内部Flash

1 J-Link简介 J-Link是SEGGER公司为支持仿真ARM内核芯片推出的JTAG仿真器。配合IAR EWAR&#xff0c;ADS&#xff0c;KEIL&#xff0c;WINARM&#xff0c;RealView等集成开发环境支持所有ARM7/ARM9/ARM11,Cortex M0/M1/M3/M4, Cortex A5/A8/A9等内核芯片的仿真&#xff0c;是学…