使用静态代理模式实现公用的报表导出功能
先聊一下什么是代理模式?
代理模式 給某個對象提供一個代理對象,并由代理獨(dú)享控制對原對象的引用。什么意思呢?代理模式就有點(diǎn)像我們生活中常見的中介。
舉個例子,我想買輛二手車,第一種方式是自己去找車源,但是像質(zhì)量檢測等一系列的車輛過戶流程都需要自己去辦,我覺得這樣太浪費(fèi)精力和時間了。于是我想到了第二種方式,就是找一個中介公司,他們代替我辦理過戶流程,我只需要負(fù)責(zé)選擇自己喜歡的汽車,然后付錢就行了,這就簡單很多了。
畫個UML圖如下。
前面提到了我們選擇中介是為了省事,其實(shí)在代碼中使用代理模式也可以省事,因為不只有我這個對象會去找這個中介,其他需要買二手車的人也需要去找這個中介,那這個中介的作用就做到了重用了。
下面說在程序中為什么要使用代理模式
- 中介隔離:在某些情況下,一個客戶不想或不能直接引用委托對象。
- 開閉原則,增加功能:當(dāng)代碼需要增加業(yè)務(wù)功能時,我們只需要修改代理類就行,符合開閉原則。
代理模式分為靜態(tài)代理和動態(tài)代理。我們今天著重講靜態(tài)代理
下面進(jìn)入獵殺時刻!!!!
使用靜態(tài)代理模式實(shí)現(xiàn)公用的導(dǎo)出功能
先來一張設(shè)計圖
先看代理接口
public interface ReportWithExcelTempAble<T> {/*** 獲得報表數(shù)據(jù)* @param searchParam* @return*/default List<List<?>> getMultipleSheetData(T searchParam) {ArrayList<List<?>> result = Lists.newArrayList();result.add(getSingleSheetData(searchParam));return result;}default List<?> getSingleSheetData(T searchParam) {throw new RuntimeException("Not support method.");}Class<T> getSearchParamType();/*** 需要導(dǎo)出的文件名* @return*/default String getReportFileName(String tempName) {return tempName;} }getMultipleSheetData、getReportFileName都有默認(rèn)的實(shí)現(xiàn)方法,因為大部分都是一個sheet的報表。
再看看代理類,代理主要是代理了報表在導(dǎo)出中的一系列操作,比如獲取導(dǎo)出模板,設(shè)置導(dǎo)出名稱等等。
package com.sf.esg.occp.core.common.support.report;import com.alibaba.fastjson.JSONObject; import com.sf.erui.context.SpringContextUtil; import com.sf.erui.util.StringUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory;import java.util.List;public class ReportProxy implements ReportWithExcelTempAble<JSONObject> {private static Logger LOG = LoggerFactory.getLogger(ReportProxy.class);/*** 模板名稱*/private String tempName;/*** 報表名稱*/private String reportFileName;private ReportWithExcelTempAble delegateInstance;private ReportProxy() {}public String getReportFileName() {return reportFileName;}public static <T> ReportProxy of(String delegateName) {ReportProxy director = new ReportProxy();director.tempName = delegateName;director.delegateInstance = SpringContextUtil.getBean(StringUtil.toLowerCaseFirstOne(director.tempName), ReportWithExcelTempAble.class);director.reportFileName = director.delegateInstance.getReportFileName(director.tempName);return director;}@Overridepublic List<List<?>> getMultipleSheetData(JSONObject searchParam) {long start = System.currentTimeMillis();Object searchObj = JSONObject.toJavaObject(searchParam, delegateInstance.getSearchParamType());LOG.debug("組裝數(shù)據(jù)費(fèi)時:{}", System.currentTimeMillis() - start);return delegateInstance.getMultipleSheetData(searchObj);}@Overridepublic Class getSearchParamType() {return delegateInstance.getSearchParamType();}}再來看看委托類:
public class BankTransactionExport implements ReportWithExcelTempAble<QueryBankTransactionVO> {@Autowiredprivate BankTransactionService bankTransactionService;@Overridepublic List<List<?>> getMultipleSheetData(QueryBankTransactionVO searchParam) {List<List<?>> lists = bankTransactionService.exportMultipleSheet(searchParam);return lists;}@Overridepublic Class<QueryBankTransactionVO> getSearchParamType() {return QueryBankTransactionVO.class;}@Overridepublic String getReportFileName(String tempName) {SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");String dateStr = format.format(new Date());return "SF銀行流水認(rèn)領(lǐng)明細(xì)" + dateStr;} }Controller層:
@RestController @RequestMapping("/report/excel") public class ReportController {public static final String FILE_SUFFIX = ".xlsx";public static final String TEMP_BASE_PATH = "temp/";public static final String PAGE_SIZE = "pageSize";public static final String CURRENT_PAGE = "currentPage";public static final int PAGE_SIZE_VALUE = 1000;private static Logger LOG = LoggerFactory.getLogger(ReportController.class);@GetMapping(params = {"Action=exportExcelByTemp"})public Response exportExcelByTemp(@RequestParam Map<String, Object> searchParam, HttpServletResponse resp) {LOG.info("Export report by temp:{}", searchParam);String tempName = (String) searchParam.get("tempName");try {ReportProxy reportDirector = ReportProxy.of(tempName);String tempPath = TEMP_BASE_PATH + tempName + FILE_SUFFIX;String fileName = URLEncoder.encode(reportDirector.getReportFileName(), "UTF-8");resp.setHeader("Content-Disposition", "filename=" + fileName + FILE_SUFFIX);resp.setContentType("APPLICATION/OCTET-STREAM");try (InputStream ins = new ClassPathResource(tempPath).getInputStream()) {ExcelWriterBuilder writeBuilder = EasyExcel.write(resp.getOutputStream()).withTemplate(ins);ExcelWriter writer = writeBuilder.autoCloseStream(false).registerConverter(new LocalDateTimeConverter()).build();JSONObject jsonObject = new JSONObject(searchParam);List<List<?>> data = reportDirector.getMultipleSheetData(jsonObject);ExcelUtils.pageExportByTemp(writer, data, tempPath);writer.finish();} catch (IOException e) {LOG.error("Excel Export Err : ", e);}return ResponseHelper.buildOk();} catch (IOException e) {LOG.error("Response get output stream err:{}", e);return ResponseHelper.buildFail("請聯(lián)系管理員");}} }在前端使用get請求調(diào)用:/report/excel?Action=exportExcelByTemp&tempName="a.xmls"
最后別忘了,添加a.xmls在項目的 temp/目錄下,我用的Spring boot,對應(yīng)代碼中的目錄如下
總結(jié)
以上是生活随笔為你收集整理的使用静态代理模式实现公用的报表导出功能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为员工中秋节礼物包括Mate60手机
- 下一篇: 继承、抽象