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

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

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

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

画个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,对应代码中的目录如下

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java前台线程(普通线程) 和 后台线程

【1】普通线程&#xff1a; 就是指 用户 创建的一般线程&#xff0c;具有个体性&#xff0c;不具有提供公共服务的性质&#xff0c;因此&#xff0c; 通常需要我们在 线程的 循环语句中 手动编写 循环结束语句&#xff0c;也即 线程运行终止的条件语句&#xff1b; 【2】后台线…

mysql中使用CASE WHEN

简单的使用CASE WHEN CASE SCORE WHEN A THEN 优 ELSE 不及格 END CASE SCORE WHEN B THEN 良 ELSE 不及格 END CASE SCORE WHEN C THEN 中 ELSE 不及格 END上面的sql等同于 CASE SCORE WHEN A THEN 优 WHEN B THEN 良 WHEN C THEN 中 ELSE 不及格 ENDTHEN后面的值与ELSE后面…

Java生成随机数的几种高级用法

转载自 进阶 | Java生成随机数的几种高级用法&#xff01;言归正传&#xff0c;众所周知&#xff0c;随机数是任何一种编程语言最基本的特征之一。而生成随机数的基本方式也是相同的&#xff1a;产生一个0到1之间的随机数。看似简单&#xff0c;但有时我们也会忽略了一些有趣的…

Java 可重入锁内存可见性分析

转载自 深度好文 | Java 可重入锁内存可见性分析一个习以为常的细节之前在做 ReentrantLock 相关的试验&#xff0c;试验本身很简单&#xff0c;和本文相关的简化版如下&#xff1a;&#xff08;提示&#xff1a;以下代码均可左右滑动&#xff09; private static ReentrantLoc…

java正则表达式 ^expr 和 [^expr] 和 ^[^expr]的比较

public class Main {private static String[] array {"Jav", "Java", "Hello"}; public static void main(String[] args) {String[] regexs {"^Java", // 以 Java开头的字符串"[^Java]",// 除了 J a v a 之外 的任何字符…

优秀 Java 程序员写代码的风格

转载自 涨姿势 | 优秀 Java 程序员写代码的风格今天突发奇想&#xff0c;对编码习惯和 编程风格 很感兴趣&#xff0c;于是乎&#xff0c;找了一下关于编程风格&#xff08;Java篇&#xff09;的资料&#xff0c;希望对爱好编码或者开始学习编码的同学有帮助&#xff01;来自《…

2017尼毕鲁笔试算法题

【1】题目&#xff1a; 给定一个无序数组&#xff0c;找到最长的单调自增子序列&#xff08;不一定连续&#xff0c;但是顺序不能乱&#xff09;的长度&#xff1b; 【2】看个荔枝&#xff1a;给定数组 [10, 9, 2, 5, 3, 7, 101, 18] 输出结果为 [2, 3, 7, 101]。。算法时间…

2018年不能错过的 14 个 Java 库

转载自 2018年不能错过的 14 个 Java 库下面是整理给你的 2018 年不应该错过的 14 个 Java 库包清单&#xff0c;多多少少大家应该都接触过一些&#xff0c;如果还没听过那就OUT了。GuiceGuice是一个Java 6以上支持依赖注入框架。由谷歌提供。OkHttpHTTP是现代网络的通讯方式。…

Spring MVC Boot Cloud 技术教程汇总

转载自 Spring MVC & Boot & Cloud 技术教程汇总昨天我们发布了Java成神之路上的知识汇总&#xff0c;今天继续。 Java成神之路技术整理&#xff08;长期更新&#xff09; 以下是Java技术栈微信公众号发布的关于 Spring/ Spring MVC/ Spring Boot/ Spring Cloud 的技术…

group by分组、having() 筛选组的用法

【1】选出 除语文学科外&#xff0c;且学科平均分大于60 的每个学科的最高最低分&#xff1b;

Java成神之路技术整理

转载自 Java成神之路技术整理以下是Java技术栈微信公众号发布的所有关于 Java 的技术干货&#xff0c;会从以下几个方面汇总&#xff0c;本文会长期更新。 Java 基础篇Java 集合篇Java 多线程篇Java JVM篇Java 进阶篇Java 新特性篇Java 工具篇Java 书籍篇 Java基础篇 8张图带你…

RFC+JSF术语

RFC 请求注解&#xff08;Request For Comments&#xff09; JSF JavaServer Faces (JSF) is a Java specification for building component-based user interfaces for web applications.

图解 5 种 Join 连接及实战案例!(inner/ left/ right/ full/ cross)

转载自 图解 5 种 Join 连接及实战案例&#xff01;&#xff08;inner/ left/ right/ full/ cross&#xff09; Join 连接在日常开发用得比较多&#xff0c;但大家都搞清楚了它们的使用区别吗&#xff1f;&#xff1f;一文带你上车~~ 内连接 inner join 内连接是基于连接谓词…

接口、多态

一.接口 1.接口的定义和使用 接口名&#xff1a;和类名一样&#xff0c;首字母大写 public interface 接口名{//接口中的成员&#xff0c;一般写一些抽象方法 } public class 类名 implements 接口名{//复写接口中所有的抽象方法 } 2.接口的成员热点&#xff1a; &#xff0…

基础笔试编程题(jz)

【1】计算某个单词在某文件中出现的次数. // 计算某个单词在某文件中出现的次数. public class WordCounter {private static int counter;private static String path System.getProperty("user.dir") File.separator "src" File.separator "com…

到底什么是 OAuth 2.0

转载自 到底什么是 OAuth 2.0 ? 一文秒懂&#xff01;- 理解OAuth 2.0OAuth是一个关于授权&#xff08;authorization&#xff09;的开放网络标准&#xff0c;在全世界得到广泛应用&#xff0c;目前的版本是2.0版。本文对OAuth 2.0的设计思路和运行流程&#xff0c;做一个简明…

在eclipse中创建maven项目错误的解决方法:Could not resolve archetype org.apache.maven.archetypes:maven-archetype-qu

当我们在ecipse安装 maven插件后&#xff0c; (how to install maven plugin named m2eclipse) You can install the lastest M2Eclipse release (1.7.0) by using the following update site from within Eclipse: http://download.eclipse.org/technology/m2e/releases 创建…

继承、抽象

继承、抽象 一.继承 1.继承解决的问题&#xff1a;共性抽取 子类中有共性的内容&#xff08;成员变量、成员方法&#xff09;抽取到父类中&#xff0c;子类可以直接使用父类非私有的成员。 2.继承的格式 public cLass 父类{//成员变量、构造方法、成员方法 }public class 子…

JDK 5 ~ 10 新特性倾情整理

转载自 JDK 5 ~ 10 新特性倾情整理最近连 JDK11都在准备发布的路上了&#xff0c;大家都整明白了吗&#xff1f;也许现在大部分人还在用6-8&#xff0c;8的新特性都没用熟&#xff0c;9刚出不久&#xff0c;10-11就不用说了。为了大家对JDK有一个全面的了解&#xff0c;下面我为…

Java 内存模型 JMM 详解

转载自 Java 内存模型 JMM 详解JMM简介 Java Memory Model简称JMM, 是一系列的Java虚拟机平台对开发者提供的多线程环境下的内存可见性、是否可以重排序等问题的无关具体平台的统一的保证。(可能在术语上与Java运行时内存分布有歧义&#xff0c;后者指堆、方法区、线程栈等内存…