Master Efficient Excel Imports in Java with EasyExcel and Spring Boot

This article explains how Java backend developers can replace memory‑heavy Apache POI with EasyExcel for fast, low‑memory Excel imports, covering basic reading, custom converters for gender and dates, and multiple Spring Boot integration patterns including controllers, listeners, constructor injection and lambda‑based approaches.

Programmer DD
Programmer DD
Programmer DD
Master Efficient Excel Imports in Java with EasyExcel and Spring Boot

Java backend developers often face memory‑intensive Excel imports when using Apache POI, which loads the entire file into memory. EasyExcel solves this problem by reading rows sequentially, reducing memory usage from hundreds of megabytes to just a few megabytes even for large files.

Simple Read

Assuming an Excel sheet with name and age columns, define a User entity:

@Data
public class User {
    /** Name */
    @ExcelProperty(index = 0)
    private String name;

    /** Age */
    @ExcelProperty(index = 1)
    private Integer age;
}

The @ExcelProperty annotation can use index (column order) or name (header text). The official documentation recommends not mixing both:

Do not use index and name simultaneously; choose one method per field.

If the Excel template columns are fixed, use index for stability.

If column order changes frequently, use name to avoid updating indices.

Custom Converter

To map gender values "男"/"女" to numeric codes, create a converter:

public class GenderConverter implements Converter<Integer> {
    public static final String MALE = "男";
    public static final String FEMALE = "女";

    @Override
    public Class supportJavaTypeKey() { return Integer.class; }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() { return CellDataTypeEnum.STRING; }

    @Override
    public Integer convertToJavaData(CellData cellData, ExcelContentProperty prop, GlobalConfiguration cfg) {
        String value = cellData.getStringValue();
        return MALE.equals(value) ? 1 : 2;
    }

    @Override
    public CellData convertToExcelData(Integer value, ExcelContentProperty prop, GlobalConfiguration cfg) {
        return null; // not needed for import
    }
}

Apply it to the entity:

/** Gender: 1‑Male, 2‑Female */
@ExcelProperty(index = 2, converter = GenderConverter.class)
private Integer gender;

Date Conversion

For a birth date column, use @DateTimeFormat to specify the desired pattern:

@ExcelProperty(index = 3)
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private String birth;

Web Reading with Spring Boot

Expose a REST endpoint that reads an uploaded Excel file:

@RestController
@RequestMapping("/users")
@Slf4j
public class UserController {
    @PostMapping("/upload")
    public String upload(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), User.class, new UserExcelListener())
                 .sheet().doRead();
        return "success";
    }
}

Several listener integration patterns are demonstrated:

Anonymous Inner Class

EasyExcel.read(file.getInputStream(), User.class, new AnalysisEventListener<User>() {
    private static final int BATCH_COUNT = 2;
    List<User> list = new ArrayList<>();
    @Override
    public void invoke(User user, AnalysisContext ctx) {
        log.info("Parsed: {}", JSON.toJSONString(user));
        list.add(user);
        if (list.size() >= BATCH_COUNT) { saveData(); list.clear(); }
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext ctx) { saveData(); }
    private void saveData() { iUser.saveData(list); }
}).sheet().doRead();

Constructor Injection

public class UserExcelListener extends AnalysisEventListener<User> {
    private final IUser iUser;
    public UserExcelListener(IUser iUser) { this.iUser = iUser; }
    // invoke / doAfterAllAnalysed similar to above, calling iUser.saveData(...)
}

// Controller usage
EasyExcel.read(file.getInputStream(), User.class, new UserExcelListener(iUser))
         .sheet().doRead();

Lambda‑Based Listener

Wrap the listener creation in a utility that accepts a Consumer<List<User>>:

public static <T> AnalysisEventListener<T> getListener(Consumer<List<T>> consumer) {
    return new AnalysisEventListener<T>() {
        private static final int BATCH_COUNT = 1000;
        List<T> buffer = new ArrayList<>();
        @Override
        public void invoke(T data, AnalysisContext ctx) {
            buffer.add(data);
            if (buffer.size() >= BATCH_COUNT) { consumer.accept(buffer); buffer.clear(); }
        }
        @Override
        public void doAfterAllAnalysed(AnalysisContext ctx) { consumer.accept(buffer); }
    };
}

// Controller usage
EasyExcel.read(file.getInputStream(), User.class,
    ExcelDemoUtils.getListener(list -> iUser.saveData(list)))
    .sheet().doRead();

Summary

EasyExcel provides a memory‑efficient way to import Excel data in Java, supporting simple row mapping, custom converters for complex fields, and seamless integration with Spring Boot controllers through various listener patterns. By leveraging Java 8 functional interfaces, developers can keep controller code clean while maintaining flexible, reusable data‑processing logic.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBatch ProcessingSpring BooteasyexcelExceldata import
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.