Как реализовать шаблон проектирования фабрики для CsvProcessing на основе ключа - PullRequest
0 голосов
/ 02 марта 2019

Я написал контроллер, который используется по умолчанию для MototuploadService (для загрузки двигателя), но мне нужно сделать один Factory Design, чтобы на основе parentPkId нужно было вызывать HealUploadService, TempUploadService, PersonalUploadService и т. Д., Который будет иметь отдельный файлэтапы обработки.

контроллер находится ниже.

@RequestMapping(value = "/csvUpload", method = RequestMethod.POST)
    public List<String> csvUpload(@RequestParam String parentPkId, @RequestParam List<MultipartFile> files)
            throws IOException, InterruptedException, ExecutionException, TimeoutException {
        log.info("Entered method csvUpload() of DaoController.class");
        List<String> response = new ArrayList<String>();
        ExecutorService executor = Executors.newFixedThreadPool(10);
        CompletionService<String> compService = new ExecutorCompletionService<String>(executor);
        List< Future<String> > futureList = new ArrayList<Future<String>>();
        for (MultipartFile f : files) {
            compService.submit(new ProcessMutlipartFile(f ,parentPkId,uploadService));
            futureList.add(compService.take());
        }       
        for (Future<String> f : futureList) {
            long timeout = 0;
            System.out.println(f.get(timeout, TimeUnit.SECONDS));
            response.add(f.get());
        }
        executor.shutdown();
        return response;
    }

Вот класс ProcessMutlipartFile, который расширяет вызываемый интерфейс, с CompletionService compService.submit(), вызывающим этот класс, которыйв свою очередь выполняет call() метод, который будет обрабатывать файл.

public class ProcessMutlipartFile implements Callable<String>
{
   private MultipartFile file; 
   private String temp;
   private MotorUploadService motUploadService;
   public ProcessMutlipartFile(MultipartFile file,String temp, MotorUploadService motUploadService )
   {
       this.file=file;
       this.temp=temp;
       this.motUploadService=motUploadService;
   }

   public String call() throws Exception 
   {

    return   motUploadService.csvUpload(temp, file);
    }

}

Ниже приведен класс MotorUploadService, где я обрабатываю загруженный CSV-файл построчно, а затем вызываю метод validateCsvData() дляПроверка данных, которая возвращает ErrorObject, имеющий номер строки и ошибки, связанные с ним.если csvErrorRecords имеет значение null, то без ошибок и продолжить сохранение в Db.иначе сохраните errorList в Db и верните Ошибка при загрузке.

@Component
public class MotorUploadService {

@Value("${external.resource.folder}")
     String resourceFolder;

    public String csvUpload(String parentPkId, MultipartFile file) {

    String OUT_PATH = resourceFolder;

    try {
            DateFormat df = new SimpleDateFormat("yyyyMMddhhmmss"); 
            String filename = file.getOriginalFilename().split(".")[0] + df.format(new Date()) + file.getOriginalFilename().split(".")[1];
            Path  path = Paths.get(OUT_PATH,fileName)
            Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
        }
        catch(IOException e){
            e.printStackTrace();
            return "Failed to Upload File...try Again";
        }
        List<TxnMpMotSlaveRaw> txnMpMotSlvRawlist = new ArrayList<TxnMpMotSlaveRaw>();

        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(file.getInputStream()));
            String line = "";
            int header = 0;
            int lineNum = 1;
            TxnMpSlaveErrorNew txnMpSlaveErrorNew = new TxnMpSlaveErrorNew();
            List<CSVErrorRecords> errList = new ArrayList<CSVErrorRecords>();
            while ((line = br.readLine()) != null) {
                // TO SKIP HEADER
                if (header == 0) {
                    header++;
                    continue;
                }
                lineNum++;
                header++;
                // Use Comma As Separator
                String[] csvDataSet = line.split(",");

                CSVErrorRecords csvErrorRecords = validateCsvData(lineNum, csvDataSet);
                System.out.println("Errors from csvErrorRecords is " + csvErrorRecords);

                if (csvErrorRecords.equals(null) || csvErrorRecords.getRecordNo() == 0) {
                    //Function to Save to Db

                } else {
                    // add to errList
                    continue;
                }
            }
            if (txnMpSlaveErrorNew.getErrRecord().size() == 0) {
                //save all
                return "Successfully Uploaded " + file.getOriginalFilename();   
            } 
            else {
                // save the error in db;
                return "Failure as it contains Faulty Information" + file.getOriginalFilename();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
            return "Failure Uploaded " + file.getOriginalFilename();
        }

    }

    private TxnMpMotSlaveRaw saveCsvData(String[] csvDataSet, String parentPkId) {
        /*
            Mapping csvDataSet to PoJo
            returning Mapped Pojo;
        */
    }

    private CSVErrorRecords validateCsvData(int lineNum, String[] csvDataSet) {
        /*
        Logic for Validation goes here
        */
    }

}

Как сделать это как шаблон фабричного дизайна из controller, чтобы, если

 parentPkId='Motor' call MotorUploadService,
    parentPkId='Heal' call HealUploadService 

, я не был такимПомните, пожалуйста, помогите мне.Заранее спасибо.

1 Ответ

0 голосов
/ 02 марта 2019

Если я понял вопрос, по сути вы создадите интерфейс, а затем вернете конкретную реализацию на основе нужного типа.

Итак

public interface UploadService {
  void csvUpload(String temp, MultipartFile file) throws IOException;
}

Конкретные реализации

public class MotorUploadService implements UploadService
{
  public void csvUpload(String temp, MultipartFile file) {
    ...
  }
}

public class HealUploadService implements UploadService
{
  public void csvUpload(String temp, MultipartFile file) {
    ...
  }
}

Тогда фабрика

public class UploadServiceFactory {
  public UploadService getService(String type) {
    if ("Motor".equals(type)) {
      return new MotorUploadService();
    }
    else if ("Heal".equals(type)) {
      return new HealUploadService();
    }
  }
}

Фабрика может кэшировать конкретные реализации.Можно также использовать абстрактный класс, а не интерфейс, если это уместно.

Я думаю, что в настоящее время у вас есть класс UploadService, но на самом деле это MotorUploadService, если я следую вашему коду, поэтому я бы переименовал его вбыть конкретным.

Затем в контроллере, предположительно, использовав инъекцию для UploadServiceFactory

...
for (MultipartFile f : files) {
  UploadService uploadSrvc = uploadServiceFactory.getService(parentPkId);
  compService.submit(new ProcessMutlipartFile(f ,parentPkId,uploadService));
  futureList.add(compService.take());
} 

Итак, с некоторыми дополнительными чтениями в ваших классах:

public class ProcessMutlipartFile implements Callable<String>
{
   private MultipartFile file; 
   private String temp;
   private UploadService uploadService;

   // change to take the interface UploadService
   public ProcessMutlipartFile(MultipartFile file,String temp, UploadService uploadService )
   {
       this.file=file;
       this.temp=temp;
       this.uploadService=uploadService;
   }

   public String call() throws Exception 
   {
     return   uploadService.csvUpload(temp, file);
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...