class AbstractImExportServiceImpl implements ImExportService {

    @Resource
    @Lazy
    private MonitorService monitorService;

    @Resource
    private TagService tagService;

    @Override
    public void importConfig(InputStream is) {
        var formList = parseImport(is)
                .stream()
                .map(this::convert)
                .collect(Collectors.toUnmodifiableList());
        if (!CollectionUtils.isEmpty(formList)) {
            formList.forEach(monitorDto -> {
                monitorService.validate(monitorDto, false);
                if (monitorDto.isDetected()) {
                    monitorService.detectMonitor(monitorDto.getMonitor(), monitorDto.getParams(), monitorDto.getCollector());
                }
                monitorService.addMonitor(monitorDto.getMonitor(), monitorDto.getParams(), monitorDto.getCollector());
            });
        }
    }

    @Override
    public void exportConfig(OutputStream os, List<Long> configList) {
        var monitorList = configList.stream()
                .map(it -> monitorService.getMonitorDto(it))
                .filter(Objects::nonNull)
                .map(this::convert)
                .collect(Collectors.toUnmodifiableList());
        writeOs(monitorList, os);
    }

    /**
     * Parsing an input stream into a form
     * 将输入流解析为表单
     *
     * @param is 输入流
     * @return 表单
     */
    abstract List<ExportMonitorDTO> parseImport(InputStream is);

    /**
     * Export Configuration to Output Stream
     * 导出配置到输出流
     *
     * @param monitorList 配置列表
     * @param os          输出流
     */
    abstract void writeOs(List<ExportMonitorDTO> monitorList, OutputStream os);

    private ExportMonitorDTO convert(MonitorDto dto) {
        var exportMonitor = new ExportMonitorDTO();
        var monitor = new MonitorDTO();
        BeanUtils.copyProperties(dto.getMonitor(), monitor);
        if (!CollectionUtils.isEmpty(dto.getMonitor().getTags())) {
            monitor.setTags(dto.getMonitor().getTags().stream()
                    .map(Tag::getId).collect(Collectors.toUnmodifiableList()));
        }
        exportMonitor.setMonitor(monitor);
        exportMonitor.setParams(dto.getParams().stream()
                .map(it -> {
                    var param = new ParamDTO();
                    BeanUtils.copyProperties(it, param);
                    return param;
                })
                .collect(Collectors.toUnmodifiableList()));
        exportMonitor.setMetrics(dto.getMetrics());
        exportMonitor.setDetected(false);
        exportMonitor.getMonitor().setCollector(dto.getCollector());
        return exportMonitor;
    }

    private MonitorDto convert(ExportMonitorDTO exportMonitor) {<FILL_FUNCTION_BODY>}

    protected String fileNamePrefix() {
        return "hertzbeat_monitor_" + LocalDate.now();
    }

    @Data
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonIgnoreProperties(ignoreUnknown = true)
    @ExcelTarget(value = "ExportMonitorDTO")
    protected static class ExportMonitorDTO {
        @ExcelEntity(name = "Monitor")
        private MonitorDTO monitor;
        @ExcelCollection(name = "Params")
        private List<ParamDTO> params;
        @ExcelCollection(name = "Metrics")
        private List<String> metrics;
        @ExcelCollection(name = "detected")
        private Boolean detected;
    }


    @Data
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonIgnoreProperties(ignoreUnknown = true)
    @ExcelTarget(value = "MonitorDTO")
    protected static class MonitorDTO {
        @Excel(name = "Name")
        private String name;
        @Excel(name = "App")
        private String app;
        @Excel(name = "Host")
        private String host;
        @Excel(name = "Intervals")
        private Integer intervals;
        @Excel(name = "Status")
        private Byte status;
        @Excel(name = "Description")
        private String description;
        @Excel(name = "Tags")
        private List<Long> tags;
        @Excel(name = "Collector")
        private String collector;
    }


    @Data
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonIgnoreProperties(ignoreUnknown = true)
    @ExcelTarget(value = "ParamDTO")
    protected static class ParamDTO {
        @Excel(name = "Field")
        private String field;
        @Excel(name = "Type")
        private Byte type;
        @Excel(name = "Value")
        private String value;
    }


}

        if (exportMonitor == null || exportMonitor.monitor == null) {
            throw new IllegalArgumentException("exportMonitor and exportMonitor.monitor must not be null");
        }

        var monitorDto = new MonitorDto();
        monitorDto.setDetected(exportMonitor.getDetected());
        var monitor = new Monitor();
        log.debug("exportMonitor.monitor{}", exportMonitor.monitor);
        if (exportMonitor.monitor != null) { //多增加一个null检测
            BeanUtils.copyProperties(exportMonitor.monitor, monitor);
            if (exportMonitor.monitor.tags != null) {
                monitor.setTags(tagService.listTag(new HashSet<>(exportMonitor.monitor.tags))
                        .stream()
                        .filter(tag -> !(tag.getName().equals(CommonConstants.TAG_MONITOR_ID) || tag.getName().equals(CommonConstants.TAG_MONITOR_NAME)))
                        .collect(Collectors.toList()));
            } else {
                monitor.setTags(Collections.emptyList());
            }
        }
        monitorDto.setMonitor(monitor);
        if (exportMonitor.getMonitor() != null) {
            monitorDto.setCollector(exportMonitor.getMonitor().getCollector());
        }
        monitorDto.setMetrics(exportMonitor.metrics);
        if (exportMonitor.params != null) {
            monitorDto.setParams(exportMonitor.params.stream()
                    .map(it -> {
                        var param = new Param();
                        BeanUtils.copyProperties(it, param);
                        return param;
                    })
                    .collect(Collectors.toUnmodifiableList()));
        } else {
            monitorDto.setParams(Collections.emptyList());
        }
        return monitorDto;
    
<no_super_class>