Springboot 之 使用 POI 导出 Excel 文件

本贴最后更新于 2551 天前,其中的信息可能已经时移世改

  • 创建表头信息

表头信息用于自动生成表头结构及排序

public class ExcelHeader implements Comparable<ExcelHeader>{ /** * excel的标题名称 */ private String title; /** * 每一个标题的顺序 */ private int order; /** * 说对应方法名称 */ private String methodName; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public int compareTo(ExcelHeader o) { return order>o.order?1:(order<o.order?-1:0); } public ExcelHeader(String title, int order, String methodName) { super(); this.title = title; this.order = order; this.methodName = methodName; } }``` * 表头信息的Annotation

/**

  • 用来在对象的 get 方法上加入的 annotation,通过该
  • annotation 说明某个属性所对应的标题
  • Created by 钟述林 393156105@qq.com on 2016/10/29 0:14.
    /
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ExcelResources {
    /
    *
    • 属性的标题名称
    • @return
      /
      String title();
      /
      *
    • 在 excel 的顺序
    • @return
      */
      int order() default 9999;
      }```
  • 创建数据实体
public class WebDto { //网站名称 private String name; //网址 private String url; //用户名 private String username; //密码 private String password; //日均访问量 private Integer readCount; public WebDto(String name, String url, String username, String password, Integer readCount) { this.name = name; this.url = url; this.username = username; this.password = password; this.readCount = readCount; } public WebDto() {} @Override public String toString() { return "WebDto{" + "name='" + name + '\'' + ", url='" + url + '\'' + ", username='" + username + '\'' + ", password='" + password + '\'' + ", readCount=" + readCount + '}'; } @ExcelResources(title="网站名称",order=1) public String getName() { return name; } public void setName(String name) { this.name = name; } @ExcelResources(title="网址",order=2) public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } @ExcelResources(title="用户名",order=3) public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @ExcelResources(title="密码",order=4) public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @ExcelResources(title="日均访问量",order=5) public Integer getReadCount() { return readCount; } public void setReadCount(Integer readCount) { this.readCount = readCount; } }``` **注意:**这里使用到了`@ExcelResources`来自动识别表头信息及序号 * 获取模板文件的工具类

public class TemplateFileUtil {

public static FileInputStream getTemplates(String tempName) throws FileNotFoundException { return new FileInputStream(ResourceUtils.getFile("classpath:excel-templates/"+tempName)); }

}```

**注意:**从这里可以看出,所有的 Excel 模板文件都放在 resources/excel-templates/ 目录下。

  • 模板工具类

通过此类可以自动复制表样式等功能

/** * 该类实现了基于模板的导出 如果要导出序号,需要在excel中定义一个标识为sernums * 如果要替换信息,需要传入一个Map,这个map中存储着要替换信息的值,在excel中通过#来开头 要从哪一行那一列开始替换需要定义一个标识为datas * 如果要设定相应的样式,可以在该行使用styles完成设定,此时所有此行都使用该样式 * 如果使用defaultStyls作为表示,表示默认样式,如果没有defaultStyles使用datas行作为默认样式 Created by 钟述林 * 393156105@qq.com on 2016/10/28 23:38. */ public class ExcelTemplate { /** * 数据行标识 */ public final static String DATA_LINE = "datas"; /** * 默认样式标识 */ public final static String DEFAULT_STYLE = "defaultStyles"; /** * 行样式标识 */ public final static String STYLE = "styles"; /** * 插入序号样式标识 */ public final static String SER_NUM = "sernums"; private static ExcelTemplate et = new ExcelTemplate(); private Workbook wb; private Sheet sheet; /** * 数据的初始化列数 */ private int initColIndex; /** * 数据的初始化行数 */ private int initRowIndex; /** * 当前列数 */ private int curColIndex; /** * 当前行数 */ private int curRowIndex; /** * 当前行对象 */ private Row curRow; /** * 最后一行的数据 */ private int lastRowIndex; /** * 默认样式 */ private CellStyle defaultStyle; /** * 默认行高 */ private float rowHeight; /** * 存储某一方所对于的样式 */ private Map<Integer, CellStyle> styles; /** * 序号的列 */ private int serColIndex; private ExcelTemplate() { } public static ExcelTemplate getInstance() { return et; } /** * 从classpath路径下读取相应的模板文件 * * @param path * @return */ public ExcelTemplate readTemplateByClasspath(String path) { try { wb = new HSSFWorkbook(TemplateFileUtil.getTemplates(path)); initTemplate(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("读取模板不存在!请检查"); } return this; } /** * 将文件写到相应的路径下 * * @param filepath */ public void writeToFile(String filepath) { FileOutputStream fos = null; try { fos = new FileOutputStream(filepath); wb.write(fos); } catch (FileNotFoundException e) { e.printStackTrace(); throw new RuntimeException("写入的文件不存在"); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("写入数据失败:" + e.getMessage()); } finally { try { if (fos != null) fos.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 将文件写到某个输出流中 * * @param os */ public void wirteToStream(OutputStream os) { try { wb.write(os); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("写入流失败:" + e.getMessage()); } } /** * 从某个路径来读取模板 * * @param path * @return */ public ExcelTemplate readTemplateByPath(String path) { try { wb = new HSSFWorkbook(TemplateFileUtil.getTemplates(path)); initTemplate(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("读取模板不存在!请检查"); } return this; } /** * 创建相应的元素,基于String类型 * * @param value */ public void createCell(String value) { Cell c = curRow.createCell(curColIndex); setCellStyle(c); c.setCellValue(value); curColIndex++; } public void createCell(int value) { Cell c = curRow.createCell(curColIndex); setCellStyle(c); c.setCellValue((int) value); curColIndex++; } public void createCell(Date value) { Cell c = curRow.createCell(curColIndex); setCellStyle(c); c.setCellValue(value); curColIndex++; } public void createCell(double value) { Cell c = curRow.createCell(curColIndex); setCellStyle(c); c.setCellValue(value); curColIndex++; } public void createCell(boolean value) { Cell c = curRow.createCell(curColIndex); setCellStyle(c); c.setCellValue(value); curColIndex++; } public void createCell(Calendar value) { Cell c = curRow.createCell(curColIndex); setCellStyle(c); c.setCellValue(value); curColIndex++; } public void createCell(BigInteger value) { Cell c = curRow.createCell(curColIndex); setCellStyle(c); c.setCellValue(value == null ? 0 : value.intValue()); curColIndex++; } /** * 设置某个元素的样式 * * @param c */ private void setCellStyle(Cell c) { if (styles.containsKey(curColIndex)) { c.setCellStyle(styles.get(curColIndex)); } else { c.setCellStyle(defaultStyle); } } /** * 创建新行,在使用时只要添加完一行,需要调用该方法创建 */ public void createNewRow() { if (lastRowIndex > curRowIndex && curRowIndex != initRowIndex) { sheet.shiftRows(curRowIndex, lastRowIndex, 1, true, true); lastRowIndex++; } curRow = sheet.createRow(curRowIndex); curRow.setHeightInPoints(rowHeight); curRowIndex++; curColIndex = initColIndex; } /** * 插入序号,会自动找相应的序号标示的位置完成插入 */ public void insertSer() { int index = 1; Row row = null; Cell c = null; for (int i = initRowIndex; i < curRowIndex; i++) { row = sheet.getRow(i); c = row.createCell(serColIndex); setCellStyle(c); c.setCellValue(index++); } } /** * 根据map替换相应的常量,通过Map中的值来替换#开头的值 * * @param datas */ public void replaceFinalData(Map<String, String> datas) { if (datas == null) return; for (Row row : sheet) { for (Cell c : row) { // if(c.getCellType()!=Cell.CELL_TYPE_STRING) continue; String str = c.getStringCellValue().trim(); if (str.startsWith("#")) { if (datas.containsKey(str.substring(1))) { c.setCellValue(datas.get(str.substring(1))); } } } } } /** * 基于Properties的替换,依然也是替换#开始的 * * @param prop */ public void replaceFinalData(Properties prop) { if (prop == null) return; for (Row row : sheet) { for (Cell c : row) { // if(c.getCellType()!=Cell.CELL_TYPE_STRING) continue; String str = c.getStringCellValue().trim(); if (str.startsWith("#")) { if (prop.containsKey(str.substring(1))) { c.setCellValue(prop.getProperty(str.substring(1))); } } } } } private void initTemplate() { sheet = wb.getSheetAt(0); initConfigData(); lastRowIndex = sheet.getLastRowNum(); curRow = sheet.createRow(curRowIndex); } /** * 初始化数据信息 */ private void initConfigData() { boolean findData = false; boolean findSer = false; for (Row row : sheet) { if (findData) break; for (Cell c : row) { // if(c.getCellType()!=Cell.CELL_TYPE_STRING) continue; String str = c.getStringCellValue().trim(); if (str.equals(SER_NUM)) { serColIndex = c.getColumnIndex(); findSer = true; } if (str.equals(DATA_LINE)) { initColIndex = c.getColumnIndex(); initRowIndex = row.getRowNum(); curColIndex = initColIndex; curRowIndex = initRowIndex; findData = true; defaultStyle = c.getCellStyle(); rowHeight = row.getHeightInPoints(); initStyles(); break; } } } if (!findSer) { initSer(); } } /** * 初始化序号位置 */ private void initSer() { for (Row row : sheet) { for (Cell c : row) { // if(c.getCellType()!=Cell.CELL_TYPE_STRING) continue; String str = c.getStringCellValue().trim(); if (str.equals(SER_NUM)) { serColIndex = c.getColumnIndex(); } } } } /** * 初始化样式信息 */ private void initStyles() { styles = new HashMap<Integer, CellStyle>(); for (Row row : sheet) { for (Cell c : row) { // if(c.getCellType()!=Cell.CELL_TYPE_STRING) continue; String str = c.getStringCellValue().trim(); if (str.equals(DEFAULT_STYLE)) { defaultStyle = c.getCellStyle(); } if (str.equals(STYLE)) { styles.put(c.getColumnIndex(), c.getCellStyle()); } } } } }``` * 操作工具类
/** * 该类实现了将一组对象转换为Excel表格,并且可以从Excel表格中读取到一组List对象中 该类利用了BeanUtils框架中的反射完成 * 使用该类的前提,在相应的实体对象上通过ExcelReources来完成相应的注解 Created by 钟述林 393156105@qq.com * on 2016/10/29 0:15. */ public class ExcelUtil { private static ExcelUtil eu = new ExcelUtil(); private ExcelUtil() { } public static ExcelUtil getInstance() { return eu; } /** * 处理对象转换为Excel * * @param template * @param objs * @param clz * @param isClasspath * @return */ private ExcelTemplate handlerObj2Excel(String template, List objs, Class clz, boolean isClasspath) { ExcelTemplate et = ExcelTemplate.getInstance(); try { if (isClasspath) { et.readTemplateByClasspath(template); } else { et.readTemplateByPath(template); } List<ExcelHeader> headers = getHeaderList(clz); Collections.sort(headers); // 输出标题 et.createNewRow(); for (ExcelHeader eh : headers) { et.createCell(eh.getTitle()); } // 输出值 for (Object obj : objs) { et.createNewRow(); for (ExcelHeader eh : headers) { // Method m = clz.getDeclaredMethod(mn); // Object rel = m.invoke(obj); et.createCell(BeanUtils.getProperty(obj, getMethodName(eh))); } } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return et; } /** * 根据标题获取相应的方法名称 * * @param eh * @return */ private String getMethodName(ExcelHeader eh) { String mn = eh.getMethodName().substring(3); mn = mn.substring(0, 1).toLowerCase() + mn.substring(1); return mn; } /** * 将对象转换为Excel并且导出,该方法是基于模板的导出,导出到流 * * @param datas * 模板中的替换的常量数据 * @param template * 模板路径 * @param os * 输出流 * @param objs * 对象列表 * @param clz * 对象的类型 * @param isClasspath * 模板是否在classPath路径下 */ public void exportObj2ExcelByTemplate(Map<String, String> datas, String template, OutputStream os, List objs, Class clz, boolean isClasspath) { try { ExcelTemplate et = handlerObj2Excel(template, objs, clz, isClasspath); et.replaceFinalData(datas); et.wirteToStream(os); os.flush(); os.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 将对象转换为Excel并且导出,该方法是基于模板的导出,导出到一个具体的路径中 * * @param datas * 模板中的替换的常量数据 * @param template * 模板路径 * @param outPath * 输出路径 * @param objs * 对象列表 * @param clz * 对象的类型 * @param isClasspath * 模板是否在classPath路径下 */ public void exportObj2ExcelByTemplate(Map<String, String> datas, String template, String outPath, List objs, Class clz, boolean isClasspath) { ExcelTemplate et = handlerObj2Excel(template, objs, clz, isClasspath); et.replaceFinalData(datas); et.writeToFile(outPath); } /** * 将对象转换为Excel并且导出,该方法是基于模板的导出,导出到流,基于Properties作为常量数据 * * @param prop * 基于Properties的常量数据模型 * @param template * 模板路径 * @param os * 输出流 * @param objs * 对象列表 * @param clz * 对象的类型 * @param isClasspath * 模板是否在classPath路径下 */ public void exportObj2ExcelByTemplate(Properties prop, String template, OutputStream os, List objs, Class clz, boolean isClasspath) { ExcelTemplate et = handlerObj2Excel(template, objs, clz, isClasspath); et.replaceFinalData(prop); et.wirteToStream(os); } /** * 将对象转换为Excel并且导出,该方法是基于模板的导出,导出到一个具体的路径中,基于Properties作为常量数据 * * @param prop * 基于Properties的常量数据模型 * @param template * 模板路径 * @param outPath * 输出路径 * @param objs * 对象列表 * @param clz * 对象的类型 * @param isClasspath * 模板是否在classPath路径下 */ public void exportObj2ExcelByTemplate(Properties prop, String template, String outPath, List objs, Class clz, boolean isClasspath) { ExcelTemplate et = handlerObj2Excel(template, objs, clz, isClasspath); et.replaceFinalData(prop); et.writeToFile(outPath); } private Workbook handleObj2Excel(List objs, Class clz) { Workbook wb = new HSSFWorkbook(); try { Sheet sheet = wb.createSheet(); Row r = sheet.createRow(0); List<ExcelHeader> headers = getHeaderList(clz); Collections.sort(headers); // 写标题 for (int i = 0; i < headers.size(); i++) { r.createCell(i).setCellValue(headers.get(i).getTitle()); } // 写数据 Object obj = null; for (int i = 0; i < objs.size(); i++) { r = sheet.createRow(i + 1); obj = objs.get(i); for (int j = 0; j < headers.size(); j++) { r.createCell(j).setCellValue(BeanUtils.getProperty(obj, getMethodName(headers.get(j)))); } } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return wb; } /** * 导出对象到Excel,不是基于模板的,直接新建一个Excel完成导出,基于路径的导出 * * @param outPath * 导出路径 * @param objs * 对象列表 * @param clz * 对象类型 */ public void exportObj2Excel(String outPath, List objs, Class clz) { Workbook wb = handleObj2Excel(objs, clz); FileOutputStream fos = null; try { fos = new FileOutputStream(outPath); wb.write(fos); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fos != null) fos.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 导出对象到Excel,不是基于模板的,直接新建一个Excel完成导出,基于流 * * @param os * 输出流 * @param objs * 对象列表 * @param clz * 对象类型 */ public void exportObj2Excel(OutputStream os, List objs, Class clz) { try { Workbook wb = handleObj2Excel(objs, clz); wb.write(os); } catch (IOException e) { e.printStackTrace(); } } /** * 从类路径读取相应的Excel文件到对象列表 * * @param path * 类路径下的path * @param clz * 对象类型 * @param readLine * 开始行,注意是标题所在行 * @param tailLine * 底部有多少行,在读入对象时,会减去这些行 * @return */ public List<Object> readExcel2ObjsByClasspath(String path, Class clz, int readLine, int tailLine) { Workbook wb = null; try { wb = new HSSFWorkbook(TemplateFileUtil.getTemplates(path)); return handlerExcel2Objs(wb, clz, readLine, tailLine); } catch (IOException e) { e.printStackTrace(); } return null; } /** * 从文件路径读取相应的Excel文件到对象列表 * * @param path * 文件路径下的path * @param clz * 对象类型 * @param readLine * 开始行,注意是标题所在行 * @param tailLine * 底部有多少行,在读入对象时,会减去这些行 * @return */ public List<Object> readExcel2ObjsByPath(String path, Class clz, int readLine, int tailLine) { Workbook wb = null; try { wb = new HSSFWorkbook(TemplateFileUtil.getTemplates(path)); return handlerExcel2Objs(wb, clz, readLine, tailLine); } catch (IOException e) { e.printStackTrace(); } return null; } /** * 从类路径读取相应的Excel文件到对象列表,标题行为0,没有尾行 * * @param path * 路径 * @param clz * 类型 * @return 对象列表 */ public List<Object> readExcel2ObjsByClasspath(String path, Class clz) { return this.readExcel2ObjsByClasspath(path, clz, 0, 0); } /** * 从文件路径读取相应的Excel文件到对象列表,标题行为0,没有尾行 * * @param path * 路径 * @param clz * 类型 * @return 对象列表 */ public List<Object> readExcel2ObjsByPath(String path, Class clz) { return this.readExcel2ObjsByPath(path, clz, 0, 0); } private String getCellValue(Cell c) { String o = null; switch (c.getCellType()) { case Cell.CELL_TYPE_BLANK: o = ""; break; case Cell.CELL_TYPE_BOOLEAN: o = String.valueOf(c.getBooleanCellValue()); break; case Cell.CELL_TYPE_FORMULA: o = String.valueOf(c.getCellFormula()); break; case Cell.CELL_TYPE_NUMERIC: o = String.valueOf(c.getNumericCellValue()); break; case Cell.CELL_TYPE_STRING: o = c.getStringCellValue(); break; default: o = null; break; } return o; } private List<Object> handlerExcel2Objs(Workbook wb, Class clz, int readLine, int tailLine) { Sheet sheet = wb.getSheetAt(0); List<Object> objs = null; try { Row row = sheet.getRow(readLine); objs = new ArrayList<Object>(); Map<Integer, String> maps = getHeaderMap(row, clz); if (maps == null || maps.size() <= 0) throw new RuntimeException("要读取的Excel的格式不正确,检查是否设定了合适的行"); for (int i = readLine + 1; i <= sheet.getLastRowNum() - tailLine; i++) { row = sheet.getRow(i); Object obj = clz.newInstance(); for (Cell c : row) { int ci = c.getColumnIndex(); String mn = maps.get(ci).substring(3); mn = mn.substring(0, 1).toLowerCase() + mn.substring(1); BeanUtils.copyProperty(obj, mn, this.getCellValue(c)); } objs.add(obj); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return objs; } private List<ExcelHeader> getHeaderList(Class clz) { List<ExcelHeader> headers = new ArrayList<ExcelHeader>(); Method[] ms = clz.getDeclaredMethods(); for (Method m : ms) { String mn = m.getName(); if (mn.startsWith("get")) { if (m.isAnnotationPresent(ExcelResources.class)) { ExcelResources er = m.getAnnotation(ExcelResources.class); headers.add(new ExcelHeader(er.title(), er.order(), mn)); } } } return headers; } private Map<Integer, String> getHeaderMap(Row titleRow, Class clz) { List<ExcelHeader> headers = getHeaderList(clz); Map<Integer, String> maps = new HashMap<Integer, String>(); for (Cell c : titleRow) { String title = c.getStringCellValue(); for (ExcelHeader eh : headers) { if (eh.getTitle().equals(title.trim())) { maps.put(c.getColumnIndex(), eh.getMethodName().replace("get", "set")); break; } } } return maps; } }```
  • Excel 模板文件

创建一个模板文件,如下图:

POI 导出 Excel 的模板文件

  • 测试类
@SpringBootTest @RunWith(SpringRunner.class) public class ExportExcelTest { @Test public void test() throws Exception { List<WebDto> list = new ArrayList<WebDto>(); list.add(new WebDto("知识林", "http://www.zslin.com", "admin", "111111", 555)); list.add(new WebDto("权限系统", "http://basic.zslin.com", "admin", "111111", 111)); list.add(new WebDto("校园网", "http://school.zslin.com", "admin", "222222", 333)); Map<String, String> map = new HashMap<String, String>(); map.put("title", "网站信息表"); map.put("total", list.size() + " 条"); map.put("date", getDate()); ExcelUtil.getInstance().exportObj2ExcelByTemplate(map, "web-info-template.xls", new FileOutputStream("D:/temp/out.xls"), list, WebDto.class, true); } private String getDate() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); return sdf.format(new Date()); } }``` 执行测试方法后,查看`D:/temp/out.xls`文件后可以看到如下图的内容: ![POI导出Excel结果图](http://img.zslin.com/study16-result.jpg)
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    948 引用 • 1460 回帖 • 2 关注
  • POI
    23 引用 • 21 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
Ethan
从前现在过去不在回来,红红落叶望眼尘世外! 苏州

推荐标签 标签

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3204 引用 • 8217 回帖
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    59 引用 • 22 回帖 • 2 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 82 关注
  • Outlook
    1 引用 • 5 回帖 • 2 关注
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    125 引用 • 370 回帖
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 188 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    303 引用 • 772 回帖 • 1 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    201 引用 • 120 回帖
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    188 引用 • 832 回帖
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    89 引用 • 1251 回帖 • 390 关注
  • SMTP

    SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。

    4 引用 • 18 回帖 • 650 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖 • 3 关注
  • 倾城之链
    23 引用 • 66 回帖 • 181 关注
  • OneDrive
    2 引用 • 4 关注
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    151 引用 • 257 回帖 • 1 关注
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    316 引用 • 547 回帖
  • SOHO

    为成为自由职业者在家办公而努力吧!

    7 引用 • 55 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 2 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    4 引用 • 16 回帖 • 201 关注
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 353 关注
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    46 引用 • 114 回帖 • 142 关注
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    36 引用 • 35 回帖 • 4 关注
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 415 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    293 引用 • 4496 回帖 • 664 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 39 关注
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 46 关注