转载请注明出处:https://blog.csdn.net/l1028386804/article/details/79659605

新版地址  https://blog.csdn.net/l1028386804/article/details/103791256

一、概述

相信大家在工作过程中,都会遇到这样一个需求,就是将相关的数据列表导出成excel,那么,有没有通用的导出方式呢,这里,就带着大家一起来用Java实现一个通用的导出Excel的工具。

二、项目实现

1、构建pom.xml

我们的工程是利用Maven来构建的,项目具体搭建过程大家可以参见网上其他资料,这里我们仅给出最核心的Maven配置

<dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>3.11-beta2</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.11-beta2</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>3.11-beta2</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-excelant</artifactId><version>3.11-beta2</version>
</dependency>

2、编写ExportExcelUtil类

这个类使我们整个工具的核心,它实现了Excel文件的导出功能,具体代码如下:

package com.lyz.utils.excel.poi;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;/*** 导出Excel* @author liuyazhuang** @param <T>*/
public class ExportExcelUtil<T>{// 2007 版本以上 最大支持1048576行public  final static String  EXCEl_FILE_2007 = "2007";// 2003 版本 最大支持65536 行public  final static String  EXCEL_FILE_2003 = "2003";/*** <p>* 导出无头部标题行Excel <br>* 时间格式默认:yyyy-MM-dd hh:mm:ss <br>* </p>* * @param title 表格标题* @param dataset 数据集合* @param out 输出流* @param version 2003 或者 2007,不传时默认生成2003版本*/public void exportExcel(String title, Collection<T> dataset, OutputStream out, String version) {if(StringUtils.isEmpty(version) || EXCEL_FILE_2003.equals(version.trim())){exportExcel2003(title, null, dataset, out, "yyyy-MM-dd HH:mm:ss");}else{exportExcel2007(title, null, dataset, out, "yyyy-MM-dd HH:mm:ss");}}/*** <p>* 导出带有头部标题行的Excel <br>* 时间格式默认:yyyy-MM-dd hh:mm:ss <br>* </p>* * @param title 表格标题* @param headers 头部标题集合* @param dataset 数据集合* @param out 输出流* @param version 2003 或者 2007,不传时默认生成2003版本*/public void exportExcel(String title,String[] headers, Collection<T> dataset, OutputStream out,String version) {if(StringUtils.isBlank(version) || EXCEL_FILE_2003.equals(version.trim())){exportExcel2003(title, headers, dataset, out, "yyyy-MM-dd HH:mm:ss");}else{exportExcel2007(title, headers, dataset, out, "yyyy-MM-dd HH:mm:ss");}}/*** <p>* 通用Excel导出方法,利用反射机制遍历对象的所有字段,将数据写入Excel文件中 <br>* 此版本生成2007以上版本的文件 (文件后缀:xlsx)* </p>* * @param title*            表格标题名* @param headers*            表格头部标题集合* @param dataset*            需要显示的数据集合,集合中一定要放置符合JavaBean风格的类的对象。此方法支持的*            JavaBean属性的数据类型有基本数据类型及String,Date* @param out*            与输出设备关联的流对象,可以将EXCEL文档导出到本地文件或者网络中* @param pattern*            如果有时间数据,设定输出格式。默认为"yyyy-MM-dd hh:mm:ss"*/@SuppressWarnings({ "unchecked", "rawtypes" })public void exportExcel2007(String title, String[] headers, Collection<T> dataset, OutputStream out, String pattern) {// 声明一个工作薄XSSFWorkbook workbook = new XSSFWorkbook();// 生成一个表格XSSFSheet sheet = workbook.createSheet(title);// 设置表格默认列宽度为15个字节sheet.setDefaultColumnWidth(20);// 生成一个样式XSSFCellStyle style = workbook.createCellStyle();// 设置这些样式style.setFillForegroundColor(new XSSFColor(java.awt.Color.gray));style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);style.setBorderBottom(XSSFCellStyle.BORDER_THIN);style.setBorderLeft(XSSFCellStyle.BORDER_THIN);style.setBorderRight(XSSFCellStyle.BORDER_THIN);style.setBorderTop(XSSFCellStyle.BORDER_THIN);style.setAlignment(XSSFCellStyle.ALIGN_CENTER);// 生成一个字体XSSFFont font = workbook.createFont();font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);font.setFontName("宋体"); font.setColor(new XSSFColor(java.awt.Color.BLACK));font.setFontHeightInPoints((short) 11);// 把字体应用到当前的样式style.setFont(font);// 生成并设置另一个样式XSSFCellStyle style2 = workbook.createCellStyle();style2.setFillForegroundColor(new XSSFColor(java.awt.Color.WHITE));style2.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);style2.setBorderBottom(XSSFCellStyle.BORDER_THIN);style2.setBorderLeft(XSSFCellStyle.BORDER_THIN);style2.setBorderRight(XSSFCellStyle.BORDER_THIN);style2.setBorderTop(XSSFCellStyle.BORDER_THIN);style2.setAlignment(XSSFCellStyle.ALIGN_CENTER);style2.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);// 生成另一个字体XSSFFont font2 = workbook.createFont();font2.setBoldweight(XSSFFont.BOLDWEIGHT_NORMAL);// 把字体应用到当前的样式style2.setFont(font2);// 产生表格标题行XSSFRow row = sheet.createRow(0);XSSFCell cellHeader;for (int i = 0; i < headers.length; i++) {cellHeader = row.createCell(i);cellHeader.setCellStyle(style);cellHeader.setCellValue(new XSSFRichTextString(headers[i]));}// 遍历集合数据,产生数据行Iterator<T> it = dataset.iterator();int index = 0;T t;Field[] fields;Field field;XSSFRichTextString richString;Pattern p = Pattern.compile("^//d+(//.//d+)?$");Matcher matcher;String fieldName;String getMethodName;XSSFCell cell;Class tCls;Method getMethod;Object value;String textValue;SimpleDateFormat sdf = new SimpleDateFormat(pattern);while (it.hasNext()) {index++;row = sheet.createRow(index);t = (T) it.next();// 利用反射,根据JavaBean属性的先后顺序,动态调用getXxx()方法得到属性值fields = t.getClass().getDeclaredFields();for (int i = 0; i < fields.length; i++) {cell = row.createCell(i);cell.setCellStyle(style2);field = fields[i];fieldName = field.getName();getMethodName = "get" + fieldName.substring(0, 1).toUpperCase()+ fieldName.substring(1);try {tCls = t.getClass();getMethod = tCls.getMethod(getMethodName, new Class[] {});value = getMethod.invoke(t, new Object[] {});// 判断值的类型后进行强制类型转换textValue = null;if (value instanceof Integer) {cell.setCellValue((Integer) value);} else if (value instanceof Float) {textValue = String.valueOf((Float) value);cell.setCellValue(textValue);} else if (value instanceof Double) {textValue = String.valueOf((Double) value);cell.setCellValue(textValue);} else if (value instanceof Long) {cell.setCellValue((Long) value);}if (value instanceof Boolean) {textValue = "是";if (!(Boolean) value) {textValue = "否";}} else if (value instanceof Date) {textValue = sdf.format((Date) value);} else {// 其它数据类型都当作字符串简单处理if (value != null) {textValue = value.toString();}}if (textValue != null) {matcher = p.matcher(textValue);if (matcher.matches()) {// 是数字当作double处理cell.setCellValue(Double.parseDouble(textValue));} else {richString = new XSSFRichTextString(textValue);cell.setCellValue(richString);}}} catch (SecurityException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} finally {// 清理资源}}}try {workbook.write(out);} catch (IOException e) {e.printStackTrace();}}/*** <p>* 通用Excel导出方法,利用反射机制遍历对象的所有字段,将数据写入Excel文件中 <br>* 此方法生成2003版本的excel,文件名后缀:xls <br>* </p>* * @param title*            表格标题名* @param headers*            表格头部标题集合* @param dataset*            需要显示的数据集合,集合中一定要放置符合JavaBean风格的类的对象。此方法支持的*            JavaBean属性的数据类型有基本数据类型及String,Date* @param out*            与输出设备关联的流对象,可以将EXCEL文档导出到本地文件或者网络中* @param pattern*            如果有时间数据,设定输出格式。默认为"yyyy-MM-dd hh:mm:ss"*/@SuppressWarnings({ "unchecked", "rawtypes" })public void exportExcel2003(String title, String[] headers, Collection<T> dataset, OutputStream out, String pattern) {// 声明一个工作薄HSSFWorkbook workbook = new HSSFWorkbook();// 生成一个表格HSSFSheet sheet = workbook.createSheet(title);// 设置表格默认列宽度为15个字节sheet.setDefaultColumnWidth(20);// 生成一个样式HSSFCellStyle style = workbook.createCellStyle();// 设置这些样式style.setFillForegroundColor(HSSFColor.GREY_50_PERCENT.index);style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);style.setBorderBottom(HSSFCellStyle.BORDER_THIN);style.setBorderLeft(HSSFCellStyle.BORDER_THIN);style.setBorderRight(HSSFCellStyle.BORDER_THIN);style.setBorderTop(HSSFCellStyle.BORDER_THIN);style.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 生成一个字体HSSFFont font = workbook.createFont();font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);font.setFontName("宋体"); font.setColor(HSSFColor.WHITE.index);font.setFontHeightInPoints((short) 11);// 把字体应用到当前的样式style.setFont(font);// 生成并设置另一个样式HSSFCellStyle style2 = workbook.createCellStyle();style2.setFillForegroundColor(HSSFColor.WHITE.index);style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);style2.setBorderRight(HSSFCellStyle.BORDER_THIN);style2.setBorderTop(HSSFCellStyle.BORDER_THIN);style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 生成另一个字体HSSFFont font2 = workbook.createFont();font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);// 把字体应用到当前的样式style2.setFont(font2);// 产生表格标题行HSSFRow row = sheet.createRow(0);HSSFCell cellHeader;for (int i = 0; i < headers.length; i++) {cellHeader = row.createCell(i);cellHeader.setCellStyle(style);cellHeader.setCellValue(new HSSFRichTextString(headers[i]));}// 遍历集合数据,产生数据行Iterator<T> it = dataset.iterator();int index = 0;T t;Field[] fields;Field field;HSSFRichTextString richString;Pattern p = Pattern.compile("^//d+(//.//d+)?$");Matcher matcher;String fieldName;String getMethodName;HSSFCell cell;Class tCls;Method getMethod;Object value;String textValue;SimpleDateFormat sdf = new SimpleDateFormat(pattern);while (it.hasNext()) {index++;row = sheet.createRow(index);t = (T) it.next();// 利用反射,根据JavaBean属性的先后顺序,动态调用getXxx()方法得到属性值fields = t.getClass().getDeclaredFields();for (int i = 0; i < fields.length; i++) {cell = row.createCell(i);cell.setCellStyle(style2);field = fields[i];fieldName = field.getName();getMethodName = "get" + fieldName.substring(0, 1).toUpperCase()+ fieldName.substring(1);try {tCls = t.getClass();getMethod = tCls.getMethod(getMethodName, new Class[] {});value = getMethod.invoke(t, new Object[] {});// 判断值的类型后进行强制类型转换textValue = null;if (value instanceof Integer) {cell.setCellValue((Integer) value);} else if (value instanceof Float) {textValue = String.valueOf((Float) value);cell.setCellValue(textValue);} else if (value instanceof Double) {textValue = String.valueOf((Double) value);cell.setCellValue(textValue);} else if (value instanceof Long) {cell.setCellValue((Long) value);}if (value instanceof Boolean) {textValue = "是";if (!(Boolean) value) {textValue = "否";}} else if (value instanceof Date) {textValue = sdf.format((Date) value);} else {// 其它数据类型都当作字符串简单处理if (value != null) {textValue = value.toString();}}if (textValue != null) {matcher = p.matcher(textValue);if (matcher.matches()) {// 是数字当作double处理cell.setCellValue(Double.parseDouble(textValue));} else {richString = new HSSFRichTextString(textValue);cell.setCellValue(richString);}}} catch (SecurityException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} finally {// 清理资源}}}try {workbook.write(out);} catch (IOException e) {e.printStackTrace();}}
}

为了演示导出功能,这里我们创建了一个Student学生类。

3、创建Student类

package com.lyz.utils.excel.poi;/*** 例子JavaBean* @author liuyazhuang**/
public class Student {private int id;private String name;private String sex;public Student(int id, String name, String sex) {this.id = id;this.name = name;this.sex = sex;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}
}

4、创建测试类TestExportExcelUtil

这个类,主要是用来测试我们的工具类。具体代码如下:

package com.lyz.test;import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;import com.lyz.utils.excel.poi.ExportExcelUtil;
import com.lyz.utils.excel.poi.Student;/*** 测试文件导出* @author liuyazhuang**/
public class TestExportExcelUtil {public static void main(String[] args) throws Exception{ExportExcelUtil<Student> util = new ExportExcelUtil<Student>();// 准备数据List<Student> list = new ArrayList<>();for (int i = 0; i < 10; i++) {list.add(new Student(111,"张三asdf","男"));list.add(new Student(111,"李四asd","男"));list.add(new Student(111,"王五","女"));}String[] columnNames = { "ID", "姓名", "性别" };util.exportExcel("用户导出", columnNames, list, new FileOutputStream("E:/test.xls"), ExportExcelUtil.EXCEL_FILE_2003);}
}

5、测试

我们运行TestExportExcelUtil类,会发现在我们的E盘下生成了test.xls文件,具体如下:

三、项目扩展

以上实现均是在本地磁盘生成excel文件,但更多的时候,我们需要通过点击网页上的某个按钮来自动生成并下载Excel文档,那么,这又如何实现呢?下面我们就一起来实现这个功能。

1、扩展ExportExcelUtil类

根据Java的继承思想,我们不在ExportExcelUtil类上修改添加,我们创建一个ExportExcelUtil类的子类ExportExcelWrapper,这个类继承ExportExcelUtil的所有功能,同时,扩展了网页生成Excel的功能。具体代码如下:

package com.lyz.utils.excel.poi;import java.net.URLEncoder;
import java.util.Collection;import javax.servlet.http.HttpServletResponse;import org.apache.commons.lang3.StringUtils;/*** 包装类* @author liuyazhuang** @param <T>*/
public class ExportExcelWrapper<T> extends ExportExcelUtil<T> {/*** <p>* 导出带有头部标题行的Excel <br>* 时间格式默认:yyyy-MM-dd hh:mm:ss <br>* </p>* * @param title 表格标题* @param headers 头部标题集合* @param dataset 数据集合* @param out 输出流* @param version 2003 或者 2007,不传时默认生成2003版本*/public void exportExcel(String fileName, String title, String[] headers, Collection<T> dataset, HttpServletResponse response,String version) {try {response.setContentType("application/vnd.ms-excel");  response.addHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8") + ".xls");if(StringUtils.isBlank(version) || EXCEL_FILE_2003.equals(version.trim())){exportExcel2003(title, headers, dataset, response.getOutputStream(), "yyyy-MM-dd HH:mm:ss");}else{exportExcel2007(title, headers, dataset, response.getOutputStream(), "yyyy-MM-dd HH:mm:ss");}} catch (Exception e) {e.printStackTrace();}}
}

这样,我们可以在Controller层调用ExportExcelWrapper将相关的数据和HttpServletResponse传递进来,即可实现通过网页生生并下载Excel文档了。

2、编写Controller类

@Controller("test")
@RequestMapping("/test")
public class TestController {@RequestMapping("/get/excel")public void getExcel(HttpServletRequest request, HttpServletResponse response) throws Exception {// 准备数据List<Student> list = new ArrayList<>();for (int i = 0; i < 10; i++) {list.add(new Student(111,"张三asdf","男"));list.add(new Student(111,"李四asd","男"));list.add(new Student(111,"王五","女"));}String[] columnNames = { "ID", "姓名", " 性别"};String fileName = "excel1";ExportExcelWrapper<Student> util = new ExportExcelWrapper<Student>();util.exportExcel(fileName, fileName, columnNames, list, response, ExportExcelUtil.EXCEL_FILE_2003);}
}

3、编写index.html

这个网页很简单,具体实现如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>导出Excel</title>
</head>
<body>
<form id="form_login" action="http://127.0.0.1:8080/test/get/excel" method="post"></form>
<button id="btn-submit" onclick="beforeSubmit()">Submit</button>
<script type="text/javascript">var loginForm = document.getElementById('form_login');function beforeSubmit() {loginForm.submit();}
</script>
</body>
</html>

4、测试

我们将程序发布到Tomcat,并点击网上的按钮,效果如下:

我们打开excel1.xls文件如下:

至此,我们的工具就编写完成了。

Java之——导出Excel通用工具类相关推荐

  1. JAVA导出Excel通用工具类——第一篇:详细介绍POI 导出excel的多种复杂情况,包括动态设置筛选、动态合并横向(纵向)单元格等多种复杂情况——保姆级别,真的不能再详细了,代码拿来即用)

    JAVA导出Excel通用工具--第一篇:详细介绍POI 导出excel的多种复杂情况,包括动态设置筛选.动态合并横向(纵向)单元格等多种复杂情况--保姆级别,真的不能再详细了,封装通用工具类,代码拿 ...

  2. Java导入导出Excel工具类ExcelUtil

    前段时间做的分布式集成平台项目中,许多模块都用到了导入导出Excel的功能,于是决定封装一个ExcelUtil类,专门用来处理Excel的导入和导出 本项目的持久化层用的是JPA(底层用hiberna ...

  3. JAVA工具类(17)--Java导入导出Excel工具类ExcelUtil

    实战 导出就是将List转化为Excel(listToExcel) 导入就是将Excel转化为List(excelToList) 导入导出中会出现各种各样的问题,比如:数据源为空.有重复行等,我自定义 ...

  4. java通用解析excel_java读取简单excel通用工具类

    本文实例为大家分享了java读取简单excel通用工具类的具体代码,供大家参考,具体内容如下 读取excel通用工具类 import java.io.File; import java.io.File ...

  5. 利用poi 读取excel通用工具类

    poi excel导出通用工具 | 这一行是废话 根据上一篇利用poi 导出excel通用工具类去年写的一个工具类,同样根据业务需求重新封装了一个读excel 工具类,感觉还算通用,分享到博客,欢迎各 ...

  6. 【工具篇】java导出excel工具类,多种模式自动配置,绝对值得你收藏

    文章目录 项目环境: 实现功能: 工具类实现 定义参数bean:ExportExcelBean.java 定义导出excel的表格主题:ExportExcelTheme.java [重点]导出exce ...

  7. java实现导出Excel的功能

    这篇文章主要为大家详细介绍了java实现导出Excel的功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 导出excel是咱Java开发的必备技能啦,之前项目有这个功能,现在将其独立出来,分享一 ...

  8. 利用java导入导出excel到oracle数据库

    用到的JAR包如下(可以直接到POI官网上下载也可以在文章的附件中下载): poi-3.9-20121203.jar poi-ooxml-3.9-20121203.jar poi-ooxml-sche ...

  9. Java POI 导出 Excel 单元格 合并单元格 相邻的相同值 合并

    通过poi导出合并单元格 合并单元格 并合并相邻并相同值的单元格 poi依赖 <dependency><groupId>org.apache.poi</groupId&g ...

最新文章

  1. webStroage案例
  2. UA MATH567 高维统计II 随机向量11 kernel的构造 用内积替换反三角函数
  3. pxe+kickstart部署多个版本的Linux操作系统(上)---原理篇
  4. 网页禁用鼠标右键和复制功能兼容方式
  5. 2.18 特殊权限set_uid 2.19 特殊权限set_gid 2.20 特殊权限stick_bit 2.21 软链接文件 2.22 硬连接文件...
  6. CSS hr修改样式
  7. 刷题总结——湫湫系列故事——设计风景线(hdu4514 并差集判环+树的直径)
  8. C++头文件中定义全局变量在多次引用时出现变量多次定义符号冲突的解决办法...
  9. 洛谷 P2420 让我们异或吧 解题报告
  10. 速达服务器远程登录设置,ERP速达软件online远程客户端登录常见问题(三)
  11. 图片上传返回淘宝链接
  12. Java设计模式大全
  13. 应用于素描人脸识别的迁移学习
  14. 硬件学习应涉及到的几个方面?
  15. asp生成带参数的二维码并合成推广海报图片,asp合并合成推广海报图片asp代码...
  16. 【xlwings api语言参考】Worksheets.Add 方法
  17. 关于安装VISO过程中出现的1406错误解决方案
  18. 如何建设教育信息化评价指标体系?
  19. 400G QSFP-DD长距产品—QSFP-DD ER4光模块
  20. 天籁obd接口针脚定义_OBD接口位置大全与obd接口针脚定义----太实用了!一定分享呀!...

热门文章

  1. nginx 配置域名 http https 80+443端口
  2. xml是什么?什么是XML?XML有什么用处?xml可以用来做什么?为什么要用xml
  3. 【CodeM初赛B轮】A 贪心
  4. Php炫技,唱歌,还在炫技?
  5. 耳切法处理多边形三角划分
  6. 凯云水利水电工程造价系统 (四)配合比单价(2)
  7. LED闪烁与LED流水灯
  8. 4G工业路由器地铁站环境监测
  9. Windows 10 1809和Office 2019下载(20190222更新)
  10. 9代cpu装linux,客户新买的电脑要重装系统,9代处理器装Windows7,谁有本事装?