Java Excel (Apache POI + annotation)

思路: 自定義注解, 導(dǎo)出/讀取 excel 根據(jù)注解自動(dòng)解析字段

  • 注解
package com.excel;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelClassAnnotation {

    String sheetName();

}

package com.excel;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelFieldAnnotation {

    int columnIndex();

    String headerName() default "";
    
}


  • 注解與excel mapping
package com.excel;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;

public class CellTemplate implements Comparable<CellTemplate> {

    private final static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:ss:mm");

    private Field field;
    private String annotation_headerName;
    private int annotation_columnIndex;

    public static CellTemplate getInstance(Field field) {
        CellTemplate mappingCell = new CellTemplate();
        Annotation[] annotations = field.getAnnotations();
        if (annotations == null || annotations.length == 0) {
            return null;
        }
        for (Annotation annotation : annotations) {
            if (annotation instanceof ExcelFieldAnnotation) {
                ExcelFieldAnnotation res = (ExcelFieldAnnotation) annotation;
                mappingCell.field = field;
                mappingCell.annotation_columnIndex = res.columnIndex();
                mappingCell.annotation_headerName = res.headerName();
                if (mappingCell.annotation_headerName == null || mappingCell.annotation_headerName.trim().length() == 0) {
                    mappingCell.annotation_headerName = field.getName();
                }
                return mappingCell;
            }
        }

        return null;
    }

    public void createCell(Row row, Object obj) throws IllegalArgumentException, IllegalAccessException {
        Cell cell = row.createCell(annotation_columnIndex);
        boolean isAccessible = field.isAccessible();
        field.setAccessible(true);

        Class<?> fieldClass = field.getType();

        if (fieldClass == Integer.class || fieldClass == int.class) {
            int value = field.getInt(obj);
            cell.setCellValue(value);
            cell.setCellType(CellType.NUMERIC);
        } else if (fieldClass == Short.class || fieldClass == short.class) {
            short value = field.getShort(obj);
            cell.setCellValue(value);
            cell.setCellType(CellType.NUMERIC);
        } else if (fieldClass == Long.class || fieldClass == long.class) {
            long value = field.getShort(obj);
            cell.setCellValue(value);
            cell.setCellType(CellType.NUMERIC);
        } else if (fieldClass == String.class) {
            String value = field.get(obj).toString();
            cell.setCellValue(value);
            cell.setCellType(CellType.STRING);
        } else if (fieldClass == Double.class || fieldClass == double.class) {
            double value = field.getDouble(obj);
            cell.setCellValue(value);
            cell.setCellType(CellType.NUMERIC);
        } else if (fieldClass == Float.class || fieldClass == float.class) {
            float value = field.getFloat(obj);
            cell.setCellValue(value);
            cell.setCellType(CellType.NUMERIC);
        } else if (fieldClass == Byte.class || fieldClass == byte.class) {
            byte value = field.getByte(obj);
            cell.setCellValue(value);
            cell.setCellType(CellType.NUMERIC);
        } else if (fieldClass == Character.class || fieldClass == char.class) {
            char value = field.getChar(obj);
            cell.setCellValue(value);
            cell.setCellType(CellType.STRING);
        } else if (fieldClass == Boolean.class) {
            boolean value = field.getBoolean(obj);
            cell.setCellValue(value);
            cell.setCellType(CellType.BOOLEAN);
        } else if (fieldClass == Date.class) {
            String value = DATE_FORMAT.format((Date) field.get(obj));
            cell.setCellValue(value);
            cell.setCellType(CellType.STRING);
        } else {
            throw new RuntimeException(fieldClass + " is not supported.");
        }

        field.setAccessible(isAccessible);
    }

    public void createHeaderCell(Row row) {
        Cell cell = row.createCell(annotation_columnIndex);
        cell.setCellValue(annotation_headerName);
        cell.setCellType(CellType.STRING);
    }

    public void invokeObjectProperty(Cell cell, Object obj) throws IllegalArgumentException, IllegalAccessException, ParseException {
        boolean isAccessible = field.isAccessible();
        field.setAccessible(true);

        Class<?> fieldClass = field.getType();

        if (fieldClass == Integer.class || fieldClass == int.class) {
            int value = (int) cell.getNumericCellValue();
            field.set(obj, value);
        } else if (fieldClass == Short.class || fieldClass == short.class) {
            short value = (short) cell.getNumericCellValue();
            field.set(obj, value);
        } else if (fieldClass == Long.class || fieldClass == long.class) {
            long value = (long) cell.getNumericCellValue();
            field.set(obj, value);
        } else if (fieldClass == String.class) {
            String value = cell.getStringCellValue();
            field.set(obj, value);
        } else if (fieldClass == Double.class || fieldClass == double.class) {
            double value = cell.getNumericCellValue();
            field.set(obj, value);
        } else if (fieldClass == Float.class || fieldClass == float.class) {
            float value = (float) cell.getNumericCellValue();
            field.set(obj, value);
        } else if (fieldClass == Byte.class || fieldClass == byte.class) {
            byte value = (byte) cell.getNumericCellValue();
            field.set(obj, value);
        } else if (fieldClass == Character.class || fieldClass == char.class) {
            char value = (char) cell.getNumericCellValue();
            field.set(obj, value);
        } else if (fieldClass == Boolean.class) {
            Boolean value = (Boolean) cell.getBooleanCellValue();
            field.set(obj, value);
        } else if (fieldClass == Date.class) {
            Date value = DATE_FORMAT.parse(cell.getStringCellValue());
            field.set(obj, value);
        } else {
            throw new RuntimeException(fieldClass + " is not supported.");
        }

        field.setAccessible(isAccessible);
    }

    public int compareTo(CellTemplate obj) {
        if (this.annotation_columnIndex == obj.annotation_columnIndex) {
            return 0;
        }
        return this.annotation_columnIndex > obj.annotation_columnIndex ? 1 : -1;
    }

}


  • 工廠, 根據(jù)后綴名調(diào)用不同的api
package com.excel;

import java.io.IOException;

public class ExcelUtilsFactory {

    static final String EXCEL_XLS = ".xls";
    static final String EXCEL_XLSX = ".xlsx";

    public static ExcelUtilsBase getInstance(String fileFullName) throws IOException {
        ExcelVersionEnum version = getExcelPostfix(fileFullName);
        switch (version) {
        case XLS:
            return new ExcelUtilsXls(fileFullName);
        case XLSX:
            return new ExcelUtilsXlsx(fileFullName);
        default:
            throw new IllegalArgumentException(fileFullName);
        }
    }

    private static ExcelVersionEnum getExcelPostfix(String excelFileName) {
        if (excelFileName == null) {
            throw new IllegalArgumentException(excelFileName);
        }

        if (excelFileName.endsWith(EXCEL_XLS)) {
            return ExcelVersionEnum.XLS;
        } else if (excelFileName.endsWith(EXCEL_XLSX)) {
            return ExcelVersionEnum.XLSX;
        }
        throw new IllegalArgumentException(excelFileName);
    }

}

package com.excel;
public enum ExcelVersionEnum {

    NONE, XLS, XLSX;
}

  • 核心類
package com.excel;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

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;

public abstract class ExcelUtilsBase {

    protected String fileFullName;

    public ExcelUtilsBase(String fileFullName) {
        this.fileFullName = fileFullName;
    }

    /**
     * add a sheet to the excel located on fileFullName; <br/>
     * If the file exist, will add a new sheet to it; if not will create a new
     * excel.
     * 
     * @param srcContent
     *            the excel content
     * @param cls
     *            the type of the content pojo
     * @throws IOException
     */
    public <T> void create(List<T> srcContent, Class<T> cls) throws IOException {
        FileOutputStream outputStream = null;
        Workbook workbook = null;
        try {
            String sheetName = getExportSheetName(cls);
            List<CellTemplate> templateList = getExportableFields(cls);

            workbook = createOrGetWorkBook(true);
            fillWorkBook(workbook, sheetName, templateList, srcContent);

            outputStream = new FileOutputStream(fileFullName);
            workbook.write(outputStream);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            close(workbook, outputStream);
        }
    }

    public <T> List<T> read(Class<T> cls) throws IOException {
        List<T> content = new ArrayList<T>();
        FileInputStream inputStream = null;
        Workbook workbook = null;

        try {
            workbook = createOrGetWorkBook(false);
            Sheet sheet = readSheet(cls, workbook);
            content = readContent(sheet, cls);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            close(workbook, inputStream);
        }
        return content;
    }

    protected abstract Workbook createBlankNewWorkbook();

    protected abstract Workbook getWorkbook() throws FileNotFoundException, IOException;

    protected abstract <T> void fillWorkBook(Workbook workbook, String sheetName, List<CellTemplate> templateList, List<T> srcContent) throws IllegalArgumentException, IllegalAccessException;

    private <T> Workbook createOrGetWorkBook(boolean createNewIfNotFound) throws FileNotFoundException, IOException {
        if (fileExist()) {
            return getWorkbook();
        } else {
            if (createNewIfNotFound) {
                return createBlankNewWorkbook();
            } else {
                throw new FileNotFoundException(fileFullName);
            }
        }

    }

    protected boolean fileExist() {
        File file = new File(fileFullName);
        return file.exists();
    }
    

    private Sheet getSheetBySheetName(Workbook workbook, String sheetName) {
        Iterator<Sheet> iterator = workbook.sheetIterator();
        while (iterator.hasNext()) {
            Sheet sheet = iterator.next();
            if (sheet.getSheetName().equals(sheetName)) {
                return sheet;
            }
        }
        throw new RuntimeException("Can't find sheet " + sheetName);
    }

    private <T> Sheet readSheet(Class<T> cls, Workbook workbook) {
        String sheetName = getExportSheetName(cls);
        Sheet sheet = getSheetBySheetName(workbook, sheetName);
        return sheet;
    }

    private <T> List<T> readContent(Sheet sheet, Class<T> cls) throws InstantiationException, IllegalAccessException, IllegalArgumentException, ParseException {
        List<T> result = new ArrayList<T>();
        List<CellTemplate> templateList = getExportableFields(cls);
        Iterator<Row> rows = sheet.rowIterator();
        skipExcelHeader(rows);
        while (rows.hasNext()) {
            Row row = rows.next();
            T item = readRow(cls, templateList, row);
            result.add(item);
        }

        return result;
    }

    private void skipExcelHeader(Iterator<Row> rows) {
        rows.next();
    }

    private <T> T readRow(Class<T> cls, List<CellTemplate> templateList, Row row) throws InstantiationException, IllegalAccessException, IllegalArgumentException, ParseException {
        T item = cls.newInstance();
        Iterator<Cell> cells = row.cellIterator();
        int columnIndex = 0;
        while (cells.hasNext()) {
            Cell cell = cells.next();
            templateList.get(columnIndex).invokeObjectProperty(cell, item);
            columnIndex++;
        }
        return item;
    }

    private <T> String getExportSheetName(Class<T> cls) {
        Annotation[] annotations = cls.getAnnotations();
        for (Annotation annotation : annotations) {
            if (annotation instanceof ExcelClassAnnotation) {
                return ((ExcelClassAnnotation) annotation).sheetName();
            }
        }
        throw new IllegalArgumentException(cls + "is not exportable.");
    }

    private <T> List<CellTemplate> getExportableFields(Class<T> cls) {
        List<CellTemplate> templateList = new ArrayList<CellTemplate>();
        Field[] declaredFields = cls.getDeclaredFields();

        for (Field field : declaredFields) {
            CellTemplate template = CellTemplate.getInstance(field);
            if (template != null) {
                templateList.add(template);
            }
        }
        Collections.sort(templateList);
        return templateList;
    }

    protected void close(Closeable... itemsToClose) throws IOException {
        if (itemsToClose != null) {
            for (Closeable closeable : itemsToClose) {
                if (closeable != null) {
                    closeable.close();
                }
            }
        }
    }
}


package com.excel;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

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.ss.usermodel.Workbook;

public class ExcelUtilsXls extends ExcelUtilsBase {

    public ExcelUtilsXls(String fileFullName) {
        super(fileFullName);
    }

    @Override
    protected Workbook createBlankNewWorkbook() {
        return new HSSFWorkbook();
    }

    @Override
    protected Workbook getWorkbook() throws FileNotFoundException, IOException {
        try (FileInputStream inputStream = new FileInputStream(fileFullName)) {
            return new HSSFWorkbook(inputStream);
        }
    }

    @Override
    public <T> void fillWorkBook(Workbook workbook, String sheetName, List<CellTemplate> templateList, List<T> srcContent) throws IllegalArgumentException, IllegalAccessException {
        HSSFSheet sheet = ((HSSFWorkbook) workbook).createSheet(sheetName);
        createHeaderRow(templateList, sheet);
        createBodyRows(templateList, srcContent, sheet);
    }

    private void createHeaderRow(List<CellTemplate> templateList, HSSFSheet sheet) {
        HSSFRow headerRow = sheet.createRow(0);
        for (CellTemplate template : templateList) {
            template.createHeaderCell(headerRow);
        }
    }

    private <T> void createBodyRows(List<CellTemplate> templateList, List<T> srcContent, HSSFSheet sheet) throws IllegalAccessException {
        int rownum = 1;
        for (T item : srcContent) {
            HSSFRow row = sheet.createRow(rownum++);
            for (CellTemplate template : templateList) {
                template.createCell(row, item);
            }
        }
    }

}


package com.excel;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelUtilsXlsx extends ExcelUtilsBase {

    public ExcelUtilsXlsx(String fileFullName) {
        super(fileFullName);
    }

    @Override
    protected Workbook createBlankNewWorkbook() {
        return new XSSFWorkbook();
    }

    @Override
    protected Workbook getWorkbook() throws FileNotFoundException, IOException {
        try (FileInputStream inputStream = new FileInputStream(fileFullName)) {
            return new XSSFWorkbook(inputStream);
        }
    }

    @Override
    public <T> void fillWorkBook(Workbook workbook, String sheetName, List<CellTemplate> templateList, List<T> srcContent) throws IllegalArgumentException, IllegalAccessException {
        XSSFSheet sheet = ((XSSFWorkbook) workbook).createSheet(sheetName);
        createHeaderRow(templateList, sheet);
        createBodyRows(templateList, srcContent, sheet);
    }

    private void createHeaderRow(List<CellTemplate> templateList, XSSFSheet sheet) {
        XSSFRow headerRow = sheet.createRow(0);
        for (CellTemplate template : templateList) {
            template.createHeaderCell(headerRow);
        }
    }

    private <T> void createBodyRows(List<CellTemplate> templateList, List<T> srcContent, XSSFSheet sheet) throws IllegalAccessException {
        int rownum = 1;
        for (T item : srcContent) {
            XSSFRow row = sheet.createRow(rownum++);
            for (CellTemplate template : templateList) {
                template.createCell(row, item);
            }
        }
    }

}


  • test
package pojo;


import java.util.Date;

import com.excel.ExcelClassAnnotation;
import com.excel.ExcelFieldAnnotation;

@ExcelClassAnnotation(sheetName = "staff")
public class Record {

    @ExcelFieldAnnotation(columnIndex = 1, headerName = "id")
    private int id;

    @ExcelFieldAnnotation(columnIndex = 3, headerName = "name")
    private String name;

    @ExcelFieldAnnotation(columnIndex = 0, headerName = "age")
    private int age;

    @ExcelFieldAnnotation(columnIndex = 2)
    private double salary;
    
    @ExcelFieldAnnotation(columnIndex = 4)
    private Date aaa;
    
    public Record(){}
    
    public Record(int id, String name, int age, double salary,Date date) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.aaa=date;
    }

    @Override
    public String toString() {
        return String.format("id:%s\tage:%s\tsalary:%s\tname:%s\tdate:%s", id, age, salary,name,aaa.toLocaleString());
    }

    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 int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

}




import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.excel.ExcelUtilsFactory;

import pojo.Record;

public class Main {

    public static void main(String[] args) throws IOException, IllegalArgumentException, IllegalAccessException, InstantiationException {
        test7();
        test8();
        test9();

        // test10();
    }

    private static void test10() throws IOException {
        List<Record> records = new ArrayList<Record>();
        records.add(new Record(1, "a", 12, 11.1d,new Date()));
        records.add(new Record(2, "b", 13, 12.1d,new Date()));
        records.add(new Record(3, "c", 14, 13.1d,new Date()));

        ExcelUtilsFactory.getInstance("c:\\work\\b.xls").create(records, Record.class);
        ExcelUtilsFactory.getInstance("c:\\work\\b.xlsx").create(records, Record.class);
    }

    private static void test9() throws IOException {
        System.out.println(ExcelUtilsFactory.getInstance("c:\\work\\b.xlsx").read(Record.class));
        System.out.println(ExcelUtilsFactory.getInstance("c:\\work\\b.xls").read(Record.class));
    }

    static void test7() throws IOException, IllegalArgumentException, IllegalAccessException {
        List<Record> records = new ArrayList<Record>();
        records.add(new Record(1, "a", 12, 11.1d,new Date()));
        records.add(new Record(2, "b", 13, 12.1d,new Date()));
        records.add(new Record(3, "c", 14, 13.1d,new Date()));

        ExcelUtilsFactory.getInstance("c:\\work\\b.xls").create(records, Record.class);
    }

    static void test8() throws IOException, IllegalArgumentException, IllegalAccessException {
        List<Record> records = new ArrayList<Record>();
        records.add(new Record(1, "a", 12, 11.1d,new Date()));
        records.add(new Record(2, "b", 13, 12.1d,new Date()));
        records.add(new Record(3, "c", 14, 13.1d,new Date()));
        ExcelUtilsFactory.getInstance("c:\\work\\b.xlsx").create(records, Record.class);
    }

}


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蔚润,一起剝皮案震驚了整個(gè)濱河市革骨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌搁进,老刑警劉巖炕吸,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡旧噪,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門脓匿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)淘钟,“玉大人,你說(shuō)我怎么就攤上這事陪毡∶啄福” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵毡琉,是天一觀的道長(zhǎng)铁瞒。 經(jīng)常有香客問(wèn)我,道長(zhǎng)桅滋,這世上最難降的妖魔是什么慧耍? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任身辨,我火速辦了婚禮,結(jié)果婚禮上芍碧,老公的妹妹穿的比我還像新娘煌珊。我一直安慰自己,他們只是感情好泌豆,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布定庵。 她就那樣靜靜地躺著,像睡著了一般践美。 火紅的嫁衣襯著肌膚如雪洗贰。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,785評(píng)論 1 314
  • 那天陨倡,我揣著相機(jī)與錄音敛滋,去河邊找鬼。 笑死兴革,一個(gè)胖子當(dāng)著我的面吹牛绎晃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播杂曲,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼擎勘!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起棚饵,我...
    開(kāi)封第一講書(shū)人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎噪漾,沒(méi)想到半個(gè)月后硼砰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體欣硼,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年诈胜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了豹障。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡耘斩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤薛夜,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布恨课,位于F島的核電站条获,受9級(jí)特大地震影響啄寡,放射性物質(zhì)發(fā)生泄漏拷窜。R本人自食惡果不足惜咆疗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一母债、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迅皇,春花似錦衙熔、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)扁耐。三九已至产阱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間王暗,已是汗流浹背庄敛。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绷雏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓坤检,卻偏偏與公主長(zhǎng)得像期吓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子讨勤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理潭千,服務(wù)發(fā)現(xiàn),斷路器逝段,智...
    卡卡羅2017閱讀 134,716評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,867評(píng)論 6 342
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,332評(píng)論 25 707
  • 以前總認(rèn)為堅(jiān)持會(huì)讓我們變強(qiáng)大 但是長(zhǎng)大后發(fā)現(xiàn) 讓我們強(qiáng)大的是放下
    沫小草閱讀 115評(píng)論 0 0
  • 秋風(fēng)萬(wàn)里覆斜陽(yáng)奶躯,吾家兒郎坐書(shū)窗亿驾。 翰墨揮灑落花舞,詩(shī)酒年華不彷徨儡蔓。 春風(fēng)勤學(xué)需尚早疼邀,寒冬磨礪寶劍芒。 胸中成竹書(shū)有...
    倚樓聽(tīng)雨聲閱讀 526評(píng)論 0 0