IT/development

[spring] spring excel download 모듈화 ver 2

알 수 없는 사용자 2024. 1. 14. 13:28
반응형

목차

    아래 포스팅에서 이어진 내용입니다.

     

    [spring] spring excel download (feat. 공통으로 분리)

    목차 아래 포스팅에서 이어진 내용입니다. [spring] spring excel download (feat. 체크박스) 목차 화면에서 사용자가 체크한 row의 데이터들만 서버로 보내서 엑셀 다운로드 창을 브라우저에게 띄우게 하

    yaga.tistory.com


    모듈화 ver 1에서는 화면이 늘어나고 구분자가 늘어남에 따라 ExcelUtil의 static method가 길어진다는 단점이 있어서 불편했다.

    그래서 더 고민 끝에 구분자에 따른 시트명, 파일명, 헤더정보를 별도의 파일로 빼기로 했다.

    이렇게 되면 파일에 내용만 추가하면 되고 소스는 건드릴 필요가 없게된다.


    pages.json(시트명, 파일명, 헤더 정보가 있는 파일) resources 하위에 생성

    {
      "comments": {
        "description": "이 파일은 엑셀 다운로드에 사용되는 엑셀 정보를 포함합니다.",
        "fileType": "json"
      },
      "singer": {
        "sheetName": "가수시트",
        "fileName": "가수",
        "headers": ["아이디", "이름", "직업"]
      },
      "currency": {
        "sheetName": "통화시트",
        "fileName": "통화",
        "headers": ["나라", "통화"]
      },
      "actor": {
        "sheetName": "배우시트",
        "fileName": "배우",
        "headers": ["성명", "연기력"]
      }
      //필요 시 추가..
    }

     

    PageInfo

    package study.dev.thboard3.board.file.web;
    
    import lombok.Data;
    
    @Data
    //pages.json의 필드를 담을 객체
    public class PageInfo {
    
        private String sheetName;   //시트명
        private String fileName;    //엑셀파일명
        private String headers[];   //헤더 목록
    }

    Controller

    매개변수 개수가 줄었다.

    package study.dev.thboard3.board.file.web;
    
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.servlet.ModelAndView;
    import study.dev.thboard3.board.file.service.ExcelService;
    
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @Controller
    @Slf4j
    @RequiredArgsConstructor
    public class ExcelController {
    
        private final ExcelService excelService;
    
        /**
         * 엑셀 다운로드 처리
         * @param paramData
         * @param pageGubun
         * @param response
         */
        @GetMapping("/exceldownload")
        public void downloadExcel(@RequestParam(name = "selectedData") String paramData,
                                  @RequestParam(name = "pageGubun") String pageGubun,
                                  HttpServletResponse response) throws IOException {
    
            excelService.download(paramData, response, pageGubun);
        }
    }

    Service

    package study.dev.thboard3.board.file.service;
    
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.ObjectMapper;
    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;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.core.io.Resource;
    import org.springframework.stereotype.Service;
    import study.dev.thboard3.board.file.web.PageInfo;
    
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.net.URLEncoder;
    import java.util.List;
    import java.util.Map;
    
    @Service("excelService")
    public class ExcelService {
    
        @Value("classpath:pages.json")
        private Resource pagesJsonResources;
    
        /**
         * 엑셀 다운로드 처리
         * @param paramData
         * @param response
         * @param pageGubun
         * @throws IOException
         */
        public void download(String paramData, HttpServletResponse response, String pageGubun) throws IOException {
    
            ObjectMapper objectMapper = new ObjectMapper();
            //json파일에서 페이지 정보 읽어서 map으로 반환
            Map<String, PageInfo> pageMap = objectMapper.readValue(pagesJsonResources.getInputStream(), new TypeReference<Map<String, PageInfo>>() {});
            //구분자에 해당되는 json파일의 내용이 담긴 객체
            PageInfo pageInfo = pageMap.get(pageGubun);
            // map타입의 list로 반환
            List<Map<String, String>> dataList = convertJsonToList(paramData);
    
            if (pageInfo != null) {
                // 엑셀 생성/다운로드 처리
                excelParsingProcess(dataList, response, pageInfo.getSheetName(), pageInfo.getFileName(), pageInfo.getHeaders());
            }
        }
    
        /**
         * 엑셀 파싱, 다운로드 처리
         * @param dataList
         * @param response
         * @param sheetName
         * @param fileName
         * @param headers
         * @throws IOException
         */
        private void excelParsingProcess(List<Map<String, String>> dataList,
                                         HttpServletResponse response,
                                         String sheetName,
                                         String fileName,
                                         String[] headers) throws IOException {
            //엑셀 생성
            Workbook wb = new XSSFWorkbook();
            //시트 생성
            Sheet sheet = wb.createSheet(sheetName);
    
            // header row  세팅
            Row headerRow = sheet.createRow(0);
    
            int cellNum = 0;
            for (String header : headers) {
                //헤더값 세팅
                headerRow.createCell(cellNum++).setCellValue(header);
            }
    
            // body row 세팅
            int rowNum = 1;
            for (Map<String, String> data : dataList) {
               Row row = sheet.createRow(rowNum++);
    
               cellNum = 0;
               //데이터 세팅
               for (String key : data.keySet()) {
                   row.createCell(cellNum++).setCellValue(data.get(key));
               }
            }
    
            String extension = ".xlsx";
    
            // HTTP 응답 설정
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName + extension, "UTF-8"));
    
            wb.write(response.getOutputStream());
            wb.close();
        }
    
        /**
         * json 형식 데이터를 map타입의 list로 반환한다.
         * @param jsonData
         * @return
         * @throws JsonProcessingException
         */
        private List<Map<String, String>> convertJsonToList(String jsonData) throws JsonProcessingException {
    
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(jsonData, new TypeReference<List<Map<String, String>>>() {});
        }
    
    
    }

    ver 1의 ExcelUtil 클래스는 삭제해도 된다.(pages.json로 대체)

    테스트


    개인 스터디 기록을 메모하는 공간이라 틀린점이 있을 수 있습니다.

    틀린 점 있을 경우 댓글 부탁드립니다.

    반응형