2016年9月13日 星期二

[JasperReport] JasperReport 報表設計套用 command 模式

[JasperReport] JasperReport 報表設計套用 command 模式

預設報表須輸出 pdf,ods 兩種格式
需要
CommandProcessor interface
Command interface
設定 Processor 可以執行的 command,假設有三種
InputModel 為從前端 controller 所傳遞過來的屬性or資料
public interface CommandProcessor {
    String TO_FILE = "toFile";
    String TO_STREAM = "toStream";
    String TO_BYTE_ARRAY = "toByteArray";
   
    genReportToFile(InputModel inputModel)
    genReportToStream(InputModel inputModel)
    genReportToByteArray(InputModel inputModel)
}



因為我們有設定兩種輸出格式,故需 implements 兩個
Processor(OdsCommandProcessor/PdfCommandProcessor)
所有的實際操作細節皆隱藏在此處
public class PdfCommandProcessor extends BaseCommand implements CommandProcessor {
    private static final Logger log = LoggerFactory.getLogger(PdfCommandProcessor.class);

    @Override
    public void genReportToFile(InputModel inputModel) {
        // 實際操作細節
    }

    @Override
    public void genReportToStream(InputModel inputModel) {
        // 實際操作細節
    }

    @Override
    public void genReportToByteArray(InputModel inputModel) {
        // 實際操作細節
    }
}

相對的
command interface 為
public interface Command {
    void execute(CommandProcessor commandProcessor);
}

就必須準備六種種不一樣的 command

public class OdsToFileCommand implements Command
public class OdsToStreamCommand implements Command
public class OdsToByteArrayCommand implements Command
public class PdfToFileCommand implements Command
public class PdfToStreamCommand implements Command
public class PdfToByteArrayCommand implements Command


若於命令中要帶入前端所帶進來的資料,可制定 InputModel 此一 Model
來置放相關屬性,用來傳到 CommandProcessor 中
例如:
public class PdfToStreamCommand extends BaseCommand implements Command {

    private PdfToStreamCommand() {}

    public PdfToStreamCommand(InputModel inputModel) {
        // attribute from BaseCommand
        this.baseModel = inputModel;
    }

    @Override
    public void execute(CommandProcessor commandProcessor) throws ReportException {
        // 傳遞資料到 processor 中
        commandProcessor.genReportToStream(baseModel);
    }
}

實際調用可建立一 CommandService interfate
如:
public interface CommandService {
    void addCommand(String process, Command command);

    void doProcess(String process);
}

並 implements 他 (OdsCommandServiceImpl / PdfCommandServiceImpl)
如:
@Service("odsCommandService")
public class OdsCommandServiceImpl implements CommandService {

    private static final Logger log = LoggerFactory.getLogger(OdsCommandServiceImpl.class);

    private Map commands = new HashMap();

    private CommandProcessor commandProcessor = new OdsCommandProcessor();

    @Override
    public void addCommand(String process, Command command) {
        commands.put(process, command);
    }

    @Override
    public void doProcess(String process) {
        commands.get(process).execute(commandProcessor);
    }
}

最後由 一個 Facade 來呼叫該Service
如:
public interface OutputFacade {

    public void genReportToFile(InputModel inputModel);

    public void genReportToStream(InputModel inputModel);

    public void genReportToByteArray(InputModel inputModel);
}

實作該 interface
@Service
public class OutputFacadeImpl implements OutputFacade {

    @Autowired
    ApplicationContext appContext;

    @Override
    public void genReportToFile(InputModel inputModel) {

        CommandService commandService =
                (CommandService) appContext.getBean(inputModel.getReportType() + "CommandService");

        if ("PDF".equals(inputModel.getReportType().toUpperCase(Locale.ENGLISH))) {
            commandService.addCommand(
                    CommandProcessor.TO_FILE, new PdfToFileCommand(inputModel));
        } else {
            commandService.addCommand(
                    CommandProcessor.TO_FILE, new OdsToFileCommand(inputModel));
        }

        commandService.doProcess(CommandProcessor.TO_FILE);
    }

    @Override
    public void genReportToStream(InputModel inputModel)) {
        // 實際操作細節
    }

    @Override
    public void genReportToByteArray(InputModel inputModel)) {
        // 實際操作細節
    }
}




沒有留言 :

張貼留言