先聊一下什么是代理模式?

代理模式 给某个对象提供一个代理对象,并由代理独享控制对原对象的引用。什么意思呢?代理模式就有点像我们生活中常见的中介。

举个例子,我想买辆二手车,第一种方式是自己去找车源,但是像质量检测等一系列的车辆过户流程都需要自己去办,我觉得这样太浪费精力和时间了。于是我想到了第二种方式,就是找一个中介公司,他们代替我办理过户流程,我只需要负责选择自己喜欢的汽车,然后付钱就行了,这就简单很多了。

画个UML图如下。


前面提到了我们选择中介是为了省事,其实在代码中使用代理模式也可以省事,因为不只有我这个对象会去找这个中介,其他需要买二手车的人也需要去找这个中介,那这个中介的作用就做到了重用了。

下面说在程序中为什么要使用代理模式

  • 中介隔离:在某些情况下,一个客户不想或不能直接引用委托对象。
  • 开闭原则,增加功能:当代码需要增加业务功能时,我们只需要修改代理类就行,符合开闭原则。

代理模式分为静态代理和动态代理。我们今天着重讲静态代理

下面进入猎杀时刻!!!!

使用静态代理模式实现公用的导出功能

先来一张设计图

先看代理接口

public interface ReportWithExcelTempAble<T> {/*** 获得报表数据* @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();/*** 需要导出的文件名* @return*/default String getReportFileName(String tempName) {return tempName;}
}

getMultipleSheetDatagetReportFileName都有默认的实现方法,因为大部分都是一个sheet的报表。

再看看代理类,代理主要是代理了报表在导出中的一系列操作,比如获取导出模板,设置导出名称等等。

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("组装数据费时:{}", 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银行流水认领明细" + 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("请联系管理员");}}
}

在前端使用get请求调用:/report/excel?Action=exportExcelByTemp&tempName="a.xmls"

最后别忘了,添加a.xmls在项目的 temp/目录下,我用的Spring boot,对应代码中的目录如下

使用静态代理模式实现公用的报表导出功能相关推荐

  1. 静态代理模式(多线程底部原理)

    静态代理模式总结(线程底部原理) 真实对象和代理对象都要实现同一个接口 代理对象要代理真实角色 好处: - 代理对象可以做很多真实对象做不了的事情 - 真实对象专注做自己的事情 创建静态代理模式:一个 ...

  2. 设计模式之静态代理模式实战

    转载自 设计模式之静态代理模式实战 静态代理模式很简单,代理类和实现类都实现相同的接口,然后通过代理类来调用实现类的方法. 如我们想保存用户信息之前打印用户信息,或者保存用户信息之后把这些信息缓存下来 ...

  3. Java多线程:静态代理模式

    静态代理模式 要求:有真实角色,代理角色 真实角色和代理角色要实现同一个接口 代理角色要持有真实角色的引用 设计静态代理模式 (1)必须有一个共同使用的接口 1 // 共同的接口 2 public i ...

  4. 浅谈java的静态代理模式

    嗨喽-小伙伴们XX好呀, 本章我们来介绍,java中出现的静态代理模式. 代理,对应于英语单词-----Proxy,从字面上理解,就是在实现代理目标(Target)所有的需求的同时,还能够实现代理目标 ...

  5. 多线程中的静态代理模式

    静态代理的例子: 1 /** 2 * 1.真实角色 3 * 2.代理角色 4 * 3.共同实现的接口 5 * @author tele 6 * 7 */ 8 public class StaticPr ...

  6. 【设计模式】--- 装饰器模式、静态代理模式和动态代理模式

    文章目录 1 引子 2 业务场景介绍 3 静态代理模式 4 装饰器模式 5 动态代理模式 5.1 Proxy --- 具体的代理对象生成组件 5.2 InvocationHandler --- 封装被 ...

  7. 研磨23种大话设计模式------动态代理模式 + 小结静态代理模式

    大家好,我是一位在java学习圈中不愿意透露姓名并苟且偷生的小学员,如果文章有错误之处,还望海涵,欢迎多多指正 如果你从本文 get 到有用的干货知识,请帮忙点个赞呗,据说点赞的都拿到了offer 在 ...

  8. 接口(jdk1.8及之后) 单例模式(饿汉式,懒汉式) 静态代理模式 简单工厂模式 匿名内部类 lambda表达式

    接口: jdk1.8及之后新增了2种可以定义存在方法体的方法: 默认方法 (default关键字修饰的方法 ) 使用:通过实现类对象使用 静态方法 (掌握) 使用:通过接口名去调用 目前接口中: 必须 ...

  9. 小白都能懂的设计模式 java版 静态代理模式实战练习(超详细)

    静态代理: 角色分析: 抽象角色:一般使用接口或者是抽象类来解决 真实角色:被代理的角色 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作 客户:访问代理对象的人 以一个租房子的例子来 ...

最新文章

  1. 【springmvc+mybatis项目实战】杰信商贸-16.新增从表货物信息
  2. 构建物联网网络的4个关键步骤简介
  3. 博客园如何转载别人的文章
  4. python教程:实现延时回调普通函数的方法
  5. 「微信小程序免费辅导教程」24,基础内容组件icon的使用探索与7月26日微信公众平台的更新解读...
  6. 大话设计模式—备忘录模式
  7. Java多线程(1)
  8. P6624-[省选联考2020A卷]作业题【矩阵树定理,欧拉反演】
  9. 【shell脚本学习-3】
  10. PL/SQL Developer将Excel表格数据导入表格
  11. C# 让你解决方案乱七八糟的DLL放入指定文件夹
  12. Python之package、module
  13. jQuery幸运大转盘_jQuery+PHP抽奖程序的简单实现
  14. 哨兵2号L1C数据下载及预处理
  15. JS-BOM基本概念
  16. epub格式电子书编辑器
  17. vc 热键、组合键的用法 MFC c++ hotkey WM_HOTKEY
  18. lotus-miner 元数据备份
  19. pynq 环境搭建_PYNQ系列学习(一)——Pynq开发环境配置
  20. C++序列容器之 vector常见用法总结

热门文章

  1. Tree Cutting HDU - 5909
  2. 2018 ICPC Asia Jakarta Regional Contest
  3. [ONTAK2010] Peaks加强版 (kruskal重构树+主席树+倍增)
  4. POJ1821-Fence【单调队列,dp】
  5. Codeforces Round #663 (Div. 2)
  6. 【Trie】阅读理解(luogu 3879/ybtoj Trie-4)
  7. 【dfs】无穷迷宫(jzoj 3924)
  8. 42、Java服务内存OOM原因分析
  9. Windows 通过 SecureCRT 8.x 上传文件到Linux服务器
  10. 这些代码优化的方法,你都用过吗