当前位置: 移动技术网 > IT编程>开发语言>Java > 在java poi导入Excel通用工具类示例详解

在java poi导入Excel通用工具类示例详解

2019年07月19日  | 移动技术网IT编程  | 我要评论

三国之郭嘉异传,女排大冠军杯,牛刀博客

前言

本文主要给大家介绍了关于java poi导入excel通用工具类的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

问题引入和分析

提示:如果不想看罗嗦的文章,可以直接到最后点击源码下载运行即可

最近在做一个导入excel的功能,在做之前在百度上面查找“java通用导入excel工具类”,没有查到,大多数都是java通用导出excel。后来仔细想想,导出可以利用java的反射,做成通用的,放进相应的实体成员变量中,导入为什么不可以呢?也是可以的,不过在做之前我们要解决如下两个问题:

1.表格中的列数和顺序要和实体类中的成员变量个数和顺序一致。

2.表格中的列的类型要和成员变量的类型一致。

第一个问题:

列数一致可以做到,但是我们最后都是要插入数据库的。那么id是必不可少的,或者良好的习惯可能还有创建时间,创建人等信息。

所以我想到了两个办法:

1.封装一个vo,只将需要的字段封装进去,并且字段顺序和表格列的顺序一致,再将vo与实体类po转化(用propertyutil.copy方法);

2.在需要的成员变量上注入自定义注解,并且加入注解的这些字段顺序和表格列的顺序一致,利用反射得到这些字段。
这里主要利用第二个方法,因为扩展性更好

第二个问题:

获取表格数据的时候,我们要判断类型,并取得相应值,全部转化为string类型,当我们给实体类赋值的时候,利用反射获取需要的成员变量的类型,并赋值。

需求

假设我们需求的excel如下:


我们可以看做两部分:

第一部分:

第二行到第11行,为一个列表数据,共有字段5个,分别为:学号,姓名,身份证号码,性别,分数

第二部分:

第12行第五列,第12行第六列,共有字段2个,分别为:总计,平均

项目

需要导入的jar包

1.poi的相关jar包,主要用来处理excel

2.beanutils 利用反射为成员变量赋值

3.commons-lang string判断非空的方法,可以不用自己判断

如若maven项目导入下面的jar包

<!-- poi操作excel --> 
  <dependency> 
   <groupid>org.apache.poi</groupid> 
   <artifactid>poi-ooxml</artifactid> 
   <version>3.8</version> 
  </dependency> 
  <dependency> 
   <groupid>org.apache.poi</groupid> 
   <artifactid>poi</artifactid> 
   <version>3.8</version> 
  </dependency> 
  <dependency> 
   <groupid>org.apache.poi</groupid> 
   <artifactid>poi-ooxml-schemas</artifactid> 
   <version>3.8</version> 
  </dependency> 
<!-- beanutils --> 
  <dependency> 
   <groupid>commons-beanutils</groupid> 
   <artifactid>commons-beanutils</artifactid> 
   <version>1.8.3</version> 
  </dependency> 
<!-- commons-lang--> 
  <dependency> 
    <groupid>commons-lang</groupid> 
    <artifactid>commons-lang</artifactid> 
    <version>2.6</version> 
  </dependency> 

非maven项目导入下面的jar(下面例子当中用到的jar,有些没用到,可自行处理)

commons-beanutils-1.8.3.jar
commons-lang-2.6.jar
commons-logging-1.1.jar
dom4j-1.6.1.jar
log4j-1.2.13.jar
poi-3.8-20120326.jar
poi-excelant-3.8-20120326.jar
poi-ooxml-3.8-20120326.jar
poi-ooxml-schemas-3.8-20120326.jar
poi-scratchpad-3.8-20120326.jar
stax-api-1.0.1.jar
xmlbeans-2.3.0.jar

项目结构

工具类

package com.dao.chu.excel; 
 
import java.io.ioexception; 
import java.io.inputstream; 
import java.lang.reflect.field; 
import java.math.bigdecimal; 
import java.text.decimalformat; 
import java.text.parseexception; 
import java.text.simpledateformat; 
import java.util.arraylist; 
import java.util.date; 
import java.util.list; 
import java.util.locale; 
 
import org.apache.commons.beanutils.propertyutils; 
import org.apache.commons.lang.stringutils; 
import org.apache.poi.hssf.usermodel.hssfcell; 
import org.apache.poi.hssf.usermodel.hssfworkbook; 
import org.apache.poi.ss.usermodel.cell; 
import org.apache.poi.ss.usermodel.row; 
import org.apache.poi.ss.usermodel.sheet; 
import org.apache.poi.ss.usermodel.workbook; 
import org.apache.poi.xssf.usermodel.xssfworkbook; 
 
/** 
 * 
 * excel读取工具类 
 * 
 * @author daochuwenziyao 
 * @see [相关类/方法] 
 * @since [产品/模块版本] 
 */ 
public class importexeclutil 
{ 
  
 private static int totalrows = 0;// 总行数 
  
 private static int totalcells = 0;// 总列数 
  
 private static string errorinfo;// 错误信息 
  
 /** 无参构造方法 */ 
 public importexeclutil() 
 { 
 } 
  
 public static int gettotalrows() 
 { 
  return totalrows; 
 } 
  
 public static int gettotalcells() 
 { 
  return totalcells; 
 } 
  
 public static string geterrorinfo() 
 { 
  return errorinfo; 
 } 
  
 /** 
  * 
  * 根据流读取excel文件 
  * 
  * 
  * @param inputstream 
  * @param isexcel2003 
  * @return 
  * @see [类、类#方法、类#成员] 
  */ 
 public list<list<string>> read(inputstream inputstream, boolean isexcel2003) 
  throws ioexception 
 { 
   
  list<list<string>> datalst = null; 
   
  /** 根据版本选择创建workbook的方式 */ 
  workbook wb = null; 
   
  if (isexcel2003) 
  { 
   wb = new hssfworkbook(inputstream); 
  } 
  else 
  { 
   wb = new xssfworkbook(inputstream); 
  } 
  datalst = readdate(wb); 
   
  return datalst; 
 } 
  
 /** 
  * 
  * 读取数据 
  * 
  * @param wb 
  * @return 
  * @see [类、类#方法、类#成员] 
  */ 
 private list<list<string>> readdate(workbook wb) 
 { 
   
  list<list<string>> datalst = new arraylist<list<string>>(); 
   
  /** 得到第一个shell */ 
  sheet sheet = wb.getsheetat(0); 
   
  /** 得到excel的行数 */ 
  totalrows = sheet.getphysicalnumberofrows(); 
   
  /** 得到excel的列数 */ 
  if (totalrows >= 1 && sheet.getrow(0) != null) 
  { 
   totalcells = sheet.getrow(0).getphysicalnumberofcells(); 
  } 
   
  /** 循环excel的行 */ 
  for (int r = 0; r < totalrows; r++) 
  { 
   row row = sheet.getrow(r); 
   if (row == null) 
   { 
    continue; 
   } 
    
   list<string> rowlst = new arraylist<string>(); 
    
   /** 循环excel的列 */ 
   for (int c = 0; c < gettotalcells(); c++) 
   { 
     
    cell cell = row.getcell(c); 
    string cellvalue = ""; 
     
    if (null != cell) 
    { 
     // 以下是判断数据的类型 
     switch (cell.getcelltype()) 
     { 
      case hssfcell.cell_type_numeric: // 数字 
       cellvalue = cell.getnumericcellvalue() + ""; 
       break; 
       
      case hssfcell.cell_type_string: // 字符串 
       cellvalue = cell.getstringcellvalue(); 
       break; 
       
      case hssfcell.cell_type_boolean: // boolean 
       cellvalue = cell.getbooleancellvalue() + ""; 
       break; 
       
      case hssfcell.cell_type_formula: // 公式 
       cellvalue = cell.getcellformula() + ""; 
       break; 
       
      case hssfcell.cell_type_blank: // 空值 
       cellvalue = ""; 
       break; 
       
      case hssfcell.cell_type_error: // 故障 
       cellvalue = "非法字符"; 
       break; 
       
      default: 
       cellvalue = "未知类型"; 
       break; 
     } 
    } 
     
    rowlst.add(cellvalue); 
   } 
    
   /** 保存第r行的第c列 */ 
   datalst.add(rowlst); 
  } 
   
  return datalst; 
 } 
  
 /** 
  * 
  * 按指定坐标读取实体数据 
  * <按顺序放入带有注解的实体成员变量中> 
  * 
  * @param wb 工作簿 
  * @param t 实体 
  * @param in 输入流 
  * @param integers 指定需要解析的坐标 
  * @return t 相应实体 
  * @throws ioexception 
  * @throws exception 
  * @see [类、类#方法、类#成员] 
  */ 
 @suppresswarnings("unused") 
 public static <t> t readdatet(workbook wb, t t, inputstream in, integer[]... integers) 
  throws ioexception, exception 
 { 
  // 获取该工作表中的第一个工作表 
  sheet sheet = wb.getsheetat(0); 
   
  // 成员变量的值 
  object entitymembervalue = ""; 
   
  // 所有成员变量 
  field[] fields = t.getclass().getdeclaredfields(); 
  // 列开始下标 
  int startcell = 0; 
   
  /** 循环出需要的成员 */ 
  for (int f = 0; f < fields.length; f++) 
  { 
    
   fields[f].setaccessible(true); 
   string fieldname = fields[f].getname(); 
   boolean fieldhasanno = fields[f].isannotationpresent(isneeded.class); 
   // 有注解 
   if (fieldhasanno) 
   { 
    isneeded annotation = fields[f].getannotation(isneeded.class); 
    boolean isneeded = annotation.isneeded(); 
     
    // excel需要赋值的列 
    if (isneeded) 
    { 
      
     // 获取行和列 
     int x = integers[startcell][0] - 1; 
     int y = integers[startcell][1] - 1; 
      
     row row = sheet.getrow(x); 
     cell cell = row.getcell(y); 
      
     if (row == null) 
     { 
      continue; 
     } 
      
     // excel中解析的值 
     string cellvalue = getcellvalue(cell); 
     // 需要赋给成员变量的值 
     entitymembervalue = getentitymembervalue(entitymembervalue, fields, f, cellvalue); 
     // 赋值 
     propertyutils.setproperty(t, fieldname, entitymembervalue); 
     // 列的下标加1 
     startcell++; 
    } 
   } 
    
  } 
   
  return t; 
 } 
  
 /** 
  * 
  * 读取列表数据 
  * <按顺序放入带有注解的实体成员变量中> 
  * 
  * @param wb 工作簿 
  * @param t 实体 
  * @param beginline 开始行数 
  * @param totalcut 结束行数减去相应行数 
  * @return list<t> 实体列表 
  * @throws exception 
  * @see [类、类#方法、类#成员] 
  */ 
 @suppresswarnings("unchecked") 
 public static <t> list<t> readdatelistt(workbook wb, t t, int beginline, int totalcut) 
  throws exception 
 { 
  list<t> listt = new arraylist<t>(); 
   
  /** 得到第一个shell */ 
  sheet sheet = wb.getsheetat(0); 
   
  /** 得到excel的行数 */ 
  totalrows = sheet.getphysicalnumberofrows(); 
   
  /** 得到excel的列数 */ 
  if (totalrows >= 1 && sheet.getrow(0) != null) 
  { 
   totalcells = sheet.getrow(0).getphysicalnumberofcells(); 
  } 
   
  /** 循环excel的行 */ 
  for (int r = beginline - 1; r < totalrows - totalcut; r++) 
  { 
   object newinstance = t.getclass().newinstance(); 
   row row = sheet.getrow(r); 
   if (row == null) 
   { 
    continue; 
   } 
    
   // 成员变量的值 
   object entitymembervalue = ""; 
    
   // 所有成员变量 
   field[] fields = t.getclass().getdeclaredfields(); 
   // 列开始下标 
   int startcell = 0; 
    
   for (int f = 0; f < fields.length; f++) 
   { 
     
    fields[f].setaccessible(true); 
    string fieldname = fields[f].getname(); 
    boolean fieldhasanno = fields[f].isannotationpresent(isneeded.class); 
    // 有注解 
    if (fieldhasanno) 
    { 
     isneeded annotation = fields[f].getannotation(isneeded.class); 
     boolean isneeded = annotation.isneeded(); 
     // excel需要赋值的列 
     if (isneeded) 
     { 
      cell cell = row.getcell(startcell); 
      string cellvalue = getcellvalue(cell); 
      entitymembervalue = getentitymembervalue(entitymembervalue, fields, f, cellvalue); 
      // 赋值 
      propertyutils.setproperty(newinstance, fieldname, entitymembervalue); 
      // 列的下标加1 
      startcell++; 
     } 
    } 
     
   } 
    
   listt.add((t)newinstance); 
  } 
   
  return listt; 
 } 
  
 /** 
  * 
  * 根据excel表格中的数据判断类型得到值 
  * 
  * @param cell 
  * @return 
  * @see [类、类#方法、类#成员] 
  */ 
 private static string getcellvalue(cell cell) 
 { 
  string cellvalue = ""; 
   
  if (null != cell) 
  { 
   // 以下是判断数据的类型 
   switch (cell.getcelltype()) 
   { 
    case hssfcell.cell_type_numeric: // 数字 
     if (org.apache.poi.ss.usermodel.dateutil.iscelldateformatted(cell)) 
     { 
      date thedate = cell.getdatecellvalue(); 
      simpledateformat dff = new simpledateformat("yyyy-mm-dd"); 
      cellvalue = dff.format(thedate); 
     } 
     else 
     { 
      decimalformat df = new decimalformat("0"); 
      cellvalue = df.format(cell.getnumericcellvalue()); 
     } 
     break; 
    case hssfcell.cell_type_string: // 字符串 
     cellvalue = cell.getstringcellvalue(); 
     break; 
     
    case hssfcell.cell_type_boolean: // boolean 
     cellvalue = cell.getbooleancellvalue() + ""; 
     break; 
     
    case hssfcell.cell_type_formula: // 公式 
     cellvalue = cell.getcellformula() + ""; 
     break; 
     
    case hssfcell.cell_type_blank: // 空值 
     cellvalue = ""; 
     break; 
     
    case hssfcell.cell_type_error: // 故障 
     cellvalue = "非法字符"; 
     break; 
     
    default: 
     cellvalue = "未知类型"; 
     break; 
   } 
    
  } 
  return cellvalue; 
 } 
  
 /** 
  * 
  * 根据实体成员变量的类型得到成员变量的值 
  * 
  * @param realvalue 
  * @param fields 
  * @param f 
  * @param cellvalue 
  * @return 
  * @see [类、类#方法、类#成员] 
  */ 
 private static object getentitymembervalue(object realvalue, field[] fields, int f, string cellvalue) 
 { 
  string type = fields[f].gettype().getname(); 
  switch (type) 
  { 
   case "char": 
   case "java.lang.character": 
   case "java.lang.string": 
    realvalue = cellvalue; 
    break; 
   case "java.util.date": 
    realvalue = stringutils.isblank(cellvalue) ? null : dateutil.strtodate(cellvalue, dateutil.yyyy_mm_dd); 
    break; 
   case "java.lang.integer": 
    realvalue = stringutils.isblank(cellvalue) ? null : integer.valueof(cellvalue); 
    break; 
   case "int": 
   case "float": 
   case "double": 
   case "java.lang.double": 
   case "java.lang.float": 
   case "java.lang.long": 
   case "java.lang.short": 
   case "java.math.bigdecimal": 
    realvalue = stringutils.isblank(cellvalue) ? null : new bigdecimal(cellvalue); 
    break; 
   default: 
    break; 
  } 
  return realvalue; 
 } 
  
 /** 
  * 
  * 根据路径或文件名选择excel版本 
  * 
  * 
  * @param filepathorname 
  * @param in 
  * @return 
  * @throws ioexception 
  * @see [类、类#方法、类#成员] 
  */ 
 public static workbook chooseworkbook(string filepathorname, inputstream in) 
  throws ioexception 
 { 
  /** 根据版本选择创建workbook的方式 */ 
  workbook wb = null; 
  boolean isexcel2003 = excelversionutil.isexcel2003(filepathorname); 
   
  if (isexcel2003) 
  { 
   wb = new hssfworkbook(in); 
  } 
  else 
  { 
   wb = new xssfworkbook(in); 
  } 
   
  return wb; 
 } 
  
 static class excelversionutil 
 { 
   
  /** 
   * 
   * 是否是2003的excel,返回true是2003 
   * 
   * 
   * @param filepath 
   * @return 
   * @see [类、类#方法、类#成员] 
   */ 
  public static boolean isexcel2003(string filepath) 
  { 
   return filepath.matches("^.+\\.(?i)(xls)$"); 
    
  } 
   
  /** 
   * 
   * 是否是2007的excel,返回true是2007 
   * 
   * 
   * @param filepath 
   * @return 
   * @see [类、类#方法、类#成员] 
   */ 
  public static boolean isexcel2007(string filepath) 
  { 
   return filepath.matches("^.+\\.(?i)(xlsx)$"); 
    
  } 
   
 } 
  
 public static class dateutil 
 { 
   
  // ======================日期格式化常量=====================// 
   
  public static final string yyyy_mm_ddhhmmss = "yyyy-mm-dd hh:mm:ss"; 
   
  public static final string yyyy_mm_dd = "yyyy-mm-dd"; 
   
  public static final string yyyy_mm = "yyyy-mm"; 
   
  public static final string yyyy = "yyyy"; 
   
  public static final string yyyymmddhhmmss = "yyyymmddhhmmss"; 
   
  public static final string yyyymmdd = "yyyymmdd"; 
   
  public static final string yyyymm = "yyyymm"; 
   
  public static final string yyyymmddhhmmss_1 = "yyyy/mm/dd hh:mm:ss"; 
   
  public static final string yyyy_mm_dd_1 = "yyyy/mm/dd"; 
   
  public static final string yyyy_mm_1 = "yyyy/mm"; 
   
  /** 
   * 
   * 自定义取值,date类型转为string类型 
   * 
   * @param date 日期 
   * @param pattern 格式化常量 
   * @return 
   * @see [类、类#方法、类#成员] 
   */ 
  public static string datetostr(date date, string pattern) 
  { 
   simpledateformat format = null; 
    
   if (null == date) 
    return null; 
   format = new simpledateformat(pattern, locale.getdefault()); 
    
   return format.format(date); 
  } 
   
  /** 
   * 将字符串转换成date类型的时间 
   * <hr> 
   * 
   * @param s 日期类型的字符串<br> 
   *   datepattern :yyyy_mm_dd<br> 
   * @return java.util.date 
   */ 
  public static date strtodate(string s, string pattern) 
  { 
   if (s == null) 
   { 
    return null; 
   } 
   date date = null; 
   simpledateformat sdf = new simpledateformat(pattern); 
   try 
   { 
    date = sdf.parse(s); 
   } 
   catch (parseexception e) 
   { 
    e.printstacktrace(); 
   } 
   return date; 
  } 
 } 
  
} 

自定义注解

import java.lang.annotation.elementtype; 
import java.lang.annotation.retention; 
import java.lang.annotation.retentionpolicy; 
import java.lang.annotation.target; 
 
/** 
 * 
 * 是否需要从解析excel赋值 
 * @author daochuwenziyao 
 * @see [相关类/方法] 
 * @since [产品/模块版本] 
 */ 
@retention(value = retentionpolicy.runtime) 
@target(value = {elementtype.field}) 
public @interface isneeded 
{ 
  
 /** 
  * 是否需要从解析excel赋值 
  * @return 
  *   true:需要 false:不需要 
  * @see [类、类#方法、类#成员] 
  */ 
 boolean isneeded() default true; 
} 

学生基本信息

import java.math.bigdecimal; 
 
/** 
 * 
 * 学生基本信息 
 * @author daochuwenziyao 
 * @see [相关类/方法] 
 * @since [产品/模块版本] 
 */ 
public class studentbaseinfo 
{ 
 private integer id; 
 @isneeded 
 private string no; 
 @isneeded 
 private string name; 
 @isneeded 
 private string idnum; 
 @isneeded 
 private string sex; 
 @isneeded 
 private bigdecimal grade; 
  
  
 @override 
 public string tostring() 
 { 
  return "studentbaseinfo [id=" + id + ", no=" + no + ", name=" + name + ", idnum=" + idnum + ", sex=" + sex 
   + ", grade=" + grade + "]"; 
 } 
 public integer getid() 
 { 
  return id; 
 } 
 public void setid(integer id) 
 { 
  this.id = id; 
 } 
 public string getno() 
 { 
  return no; 
 } 
 public void setno(string no) 
 { 
  this.no = no; 
 } 
 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; 
 } 
 public string getidnum() 
 { 
  return idnum; 
 } 
 public void setidnum(string idnum) 
 { 
  this.idnum = idnum; 
 } 
 public bigdecimal getgrade() 
 { 
  return grade; 
 } 
 public void setgrade(bigdecimal grade) 
 { 
  this.grade = grade; 
 } 
  
} 

学生统计信息

/** 
 * 
 * 学生统计信息 
 * @author daochuwenziyao 
 * @see [相关类/方法] 
 * @since [产品/模块版本] 
 */ 
public class studentstatistics 
{ 
 private integer id; 
 @isneeded 
 private bigdecimal totalgrade; 
 @isneeded 
 private bigdecimal avggrade; 
  
 @override 
 public string tostring() 
 { 
  return "studentstatistics [id=" + id + ", totalgrade=" + totalgrade + ", avggrade=" + avggrade + "]"; 
 } 
 public integer getid() 
 { 
  return id; 
 } 
 public void setid(integer id) 
 { 
  this.id = id; 
 } 
 public bigdecimal gettotalgrade() 
 { 
  return totalgrade; 
 } 
 public void settotalgrade(bigdecimal totalgrade) 
 { 
  this.totalgrade = totalgrade; 
 } 
 public bigdecimal getavggrade() 
 { 
  return avggrade; 
 } 
 public void setavggrade(bigdecimal avggrade) 
 { 
  this.avggrade = avggrade; 
 } 
  
} 

测试类

package com.dao.chu.excel; 
 
 
import java.io.file; 
import java.io.fileinputstream; 
import java.io.ioexception; 
import java.io.inputstream; 
import java.util.list; 
 
 
import org.apache.poi.ss.usermodel.workbook; 
 
 
public class testimportexcel 
{ 
  
 public static void main(string[] args) throws ioexception, exception 
 { 
   
  string filename="student.xlsx"; 
  inputstream in = new fileinputstream(new file("excelfile\\student.xlsx")); 
  workbook wb = importexeclutil.chooseworkbook(filename, in); 
  studentstatistics studentstatistics = new studentstatistics(); 
   
  //读取一个对象的信息 
  studentstatistics readdatet = 
   importexeclutil.readdatet(wb, studentstatistics, in, new integer[] {12, 5}, new integer[] {13, 5}); 
  system.out.println(readdatet); 
   
  //读取对象列表的信息 
  studentbaseinfo studentbaseinfo = new studentbaseinfo(); 
  //第二行开始,到倒数第三行结束(总数减去两行) 
  list<studentbaseinfo> readdatelistt = importexeclutil.readdatelistt(wb, studentbaseinfo, 2, 2); 
  system.out.println(readdatelistt); 
   
 } 
} 

输出结果

studentstatistics [id=null, totalgrade=845, avggrade=84]
[studentbaseinfo [id=null, no=2012240001, name=张三1, idnum=233314199009062304, sex=男, grade=80], studentbaseinfo [id=null, no=2012240002, name=张三2, idnum=233314199009062304, sex=男, grade=81], studentbaseinfo [id=null, no=2012240003, name=张三3, idnum=233314199009062304, sex=男, grade=82], studentbaseinfo [id=null, no=2012240004, name=张三4, idnum=233314199009062304, sex=男, grade=83], studentbaseinfo [id=null, no=2012240005, name=张三5, idnum=233314199009062304, sex=男, grade=84], studentbaseinfo [id=null, no=2012240006, name=张三6, idnum=233314199009062304, sex=男, grade=85], studentbaseinfo [id=null, no=2012240007, name=张三7, idnum=233314199009062304, sex=男, grade=86], studentbaseinfo [id=null, no=2012240008, name=张三8, idnum=233314199009062304, sex=男, grade=87], studentbaseinfo [id=null, no=2012240009, name=张三9, idnum=233314199009062304, sex=男, grade=88], studentbaseinfo [id=null, no=2012240010, name=张三10, idnum=233314199009062304, sex=男, grade=89]]

源码下载

源码分享给大家,上面提到的都在这里,由于很多的数据类型没有试验到,可能会有些类型有问题,所以希望大家如果遇到问题回复我,我会将其完善。

源码下载:

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对移动技术网的支持。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网