Excel导出。
简述一下整个结构:通过报表代理类,通过多态动态的选择实现了代理接口的被代理类,从而实现具体的业务逻辑,最后导出表格。
关于代理类不多赘述,点此查看代理类相关。
动态代理实现步骤
- 创建被代理的类(委托类、真实类)(RealSubject)及其接口(RealSubjectInterface)
- 创建一个实现接口InvocationHandler的类(InvocationHandlerImpl),它必须实现接口的invoke方法
- 通过Proxy的静态方法newProxyInstance(), 创建一个代理对象(realSubjectProxy),
RealSubjectInterface realSubjectProxy= (RealSubjectInterface) Proxy.newProxyInstance(loader,interfaces,handler); - 通过代理对象(realSubjectProxy)调用 委托类对象( realSubject)的方法
上代码~~~~~
1.报表代理类
/**
* 报表代理类
*/
@Component
public class SLReportProxy {
private Logger log = LoggerFactory.getLogger(getClass());
@Autowired
private TSaleReportListBiz reportTypeBiz;
private SLReportBase reportBase;
/**
* 初始化
* @param params
*/
private void init(Map<String, Object> params) {
log.debug("[报表代理]初始化");
String reportCode = params.get("reportCode") == null ? "" : String.valueOf(params.get("reportCode"));
String reportType = params.get("reportType") == null ? "" : String.valueOf(params.get("reportType"));
params.remove("reportCode");
TSaleReport TSaleReport = new TSaleReport();
TSaleReport.setReportCode(reportCode);
//TSaleReport.setReportTypeCodes(reportType);
TSaleReport = reportTypeBiz.selectOne(TSaleReport);
if(TSaleReport != null && TSaleReport.getClassName() != null && !"".equals(TSaleReport.getClassName())) {
String className = TSaleReport.getClassName();
log.debug("[报表代理]查找报表编码=" + reportCode + " 报表类型=" + reportType + "成功,对应的处理类为" + className);
reportBase = (SLReportBase) SpringContextHolder.getBean(className);
} else {
log.debug("[报表代理]查找报表编码=" + reportCode + " 报表类型=" + reportType + "失败,未找到对应的处理类");
}
}
/**
* 查询表格数据
* @param params
* @return
*/
public Object queryByTable(Map<String, Object> params) throws Exception {
init(params);
Query query = new Query(params);
return reportBase.queryByTable(query);
}
/**
* 表格导出
* @param params
* @return
*/
public Workbook export(Map<String, Object> params) throws Exception {
init(params);
Query query = new Query(params);
return reportBase.export(query);
}
}
2.代理接口
public interface SLReportBase {
Object queryByTable(Query query) throws Exception;
Workbook export(Query query) throws Exception;
}
3.被代理类
/**
* @author LJG
*/
@Component("slProductionAndSalesGapControlReport")
public class SlProductionAndSalesGapControlReport extends BusinessBiz<AreaWaterMonthMapper,AreaWaterMonth> implements SLReportBase {
@Autowired
SlProductionAndSalesGapControlBiz biz;
@Override
public Object queryByTable(Query query) throws Exception {
return biz.productionAndSalesGapControl(query.get("Iid").toString(),query.get("endTime").toString());
}
@Override
public Workbook export(Query query) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
HashMap<String, Object> paramMap = new HashMap<>();
// 实现深拷贝
paramMap.putAll(query);
map.put("param", paramMap);
Object data = queryByTable(query);
String template = "cxc_production_control_report.xlsx";
map.put("data", data);
ExcelTransformer excel = new ExcelTransformer();
InputStream inputStream = this.getClass().getResourceAsStream(Constant.EXCEL_TEMPLATE_PATH + template);
Workbook wb = excel.transform(inputStream, map);
return wb;
}
}
4.通用Controller
public class SLCommonReportController {
@Autowired
private SLReportProxy slReportProxy;
/**
* @Description: 表格数据查询
* @param params
* @return void
*/
@RequestMapping(value = "/queryByTable/", method = RequestMethod.GET)
@ApiOperation(value="表格数据查询")
public ObjectRestResponse<Object> queryByTable(@RequestParam Map<String, Object> params) throws Exception {
Object obj = slReportProxy.queryByTable(HttpParamUtil.getParams2Map(params));
return ObjectRestResponse.ok(obj);
}
/**
* @Description: 报表导出
* @param params
* @param response
* @return void
*/
@RequestMapping(value = "/export", method = RequestMethod.POST)
@ResponseBody
@ApiOperation(value="报表导出",produces="application/octet-stream")
public void exportDetail(@RequestParam Map<String,Object> params, HttpServletResponse response) {
try {
params = HttpParamUtil.getParams2Map(params);
String suffix = ".xlsx";
String date = params.get("date") == null ? "" : String.valueOf(params.get("date"));
Workbook workbook = slReportProxy.export(params);
if (workbook != null) {
String fileName = "报表("+ date + ")" + suffix;
FileUtil.downLoadExcel(fileName, response, workbook);
}
} catch (Exception e) {
e.printStackTrace();
response.addHeader("Set-Cookie", "fileDownload=false; path=/");
}
}
}
注:service层 就不贴代码了,图太多看起来雷,业务层就实现具体业务,整体框架已经展现
流程: 浏览器请求---controller接收进入代理类--代理类初始化报表,选择被代理类--进入被代理类调用查询或者导出方法;
划重点啦!
代理类初始化报表,通过前端传递的“reportCode”,查询报表实体类信息,获取被代理类的className 确定被代理类实体,className在数据库保存的是@Component("slProductionAndSalesGapControlReport")注释内的名称。原因是IOC;
SpringContextHolder.getBean 获取指定的静态的bean,这个bean是已经被spring控制。直接通过spring获取
reportBase = (SLReportBase) SpringContextHolder.getBean(className);通过多态代替了实现代理接口的被代理类
有许多理解或者描述不到位的,多多包涵,欢迎指出。勿喷!