Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

一、特殊名词介绍

二、背景、场景介绍

帆软产品中一个非常方便的功能就是导出。使用频率也非常的高。对于常见的一些文件类型的导出,目前产品本身都已支持。但是在一些特殊的行业或者场景中,用户往往有自己的文件规范和导出规范,在帆软产品中专门开放了用于解决这类导出的接口。对于单个类型的导出处理,通常我们都选择了ExportOperateProvider接口实现。但是如果我们需要对所有的报表导出都做某些特殊的操作,诸如对所有的导出信息推送、对导出的文件进行加密、备份等等操作时。我们需要一个更为统一的接口。那么在早期的帆软报表中就提供了ExportExtensionProcessor接口。该接口可以对所有的cpt类型的报表导出场景进行统一的拦截和处理。因为接口开得比较早,早期的决策报表是不支持导出的,所以这个接口也只能处理cpt报表的导出。

可以用于导出的接口比较多,而ExportOperateProvider则主要用于新文件类型的导出使用。使用也跟一般的产品导出一致,通过URL中指定format参数调用。

三、接口介绍

Code Block
languagejava
themeEclipse
firstline1
titleExportExtensionProcessor.java
linenumberstrue
package com.fr.report.fun;

import com.fr.io.collection.ExportCollection;
import com.fr.stable.fun.mark.Immutable;
import com.fr.web.core.ReportSessionIDInfor;
import com.fr.web.core.TemplateSessionIDInfo;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义导出接口
 */
public interface ExportExtensionProcessor extends Immutable{

    String MARK_TAG = "ExportExtensionProcessor";

    int CURRENT_LEVEL = 1;


    /**
     * 导出后的文件名
     * @param req HTTP请求
     * @param sessionIDInfor 报表的会话信息
     * @return 文件名
     */
    String fileName(HttpServletRequest req, TemplateSessionIDInfo sessionIDInfor) throws Exception;

    /**
     * 导出所需要的集合
     * @param req HTTP请求
     * @param res HTTP响应
     * @param sessionIDInfor 报表的会话信息
     * @param format 导出格式
     * @param fileName 导出的文件名
     * @param isEmbed 是否是内置导出
     * @return 导出操作集合
     * @throws Exception 如果导出过程中出现异常则抛出此异常
     */
    ExportCollection createCollection(HttpServletRequest req, HttpServletResponse res,
                                      ReportSessionIDInfor sessionIDInfor, String format,
                                      String fileName, boolean isEmbed) throws Exception;
}

...

Code Block
languagejava
themeEclipse
firstline1
titleBaseOperateDefaultExportExtension.java
linenumberstrue
collapsetrue
package com.fanruan.api.report.export;
fr.web.core.reserve;

import com.fr.data.NetworkHelper;
import com.fr.general.web.ParameterConstants;
import com.fr.io.collection.ExportCollection;
import com.fr.stablereport.fun.impl.AbstractExportExtension;
import com.fr.web.SessionProviderBrowser;
import com.fr.web.core.reserve.Operate.ReportSessionIDInfor;
import com.fr.web.core.TemplateSessionIDInfo;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author richie
 * @version 10.0
 * Created by richie on 201915/911/2630.
 * 导出接口的抽象类
 */
public abstract class BaseOperateDefaultExportExtension implementsextends OperateAbstractExportExtension {

    public  @Override
String fileName(HttpServletRequest req, TemplateSessionIDInfo sessionIDInfor) throws Exception {
     public  void setContent(HttpServletRequest req, HttpServletResponse res, String fileName, boolean isEmbed) {

    }// carl:允许改名,没有就用报表名
        String fileName = NetworkHelper.getHTTPRequestFileNameParameter(req);

    @Override
    public void setContent(HttpServletRequest req, HttpServletResponse res, SessionProvider sessionProvider, String fileName, boolean isEmbed//barry:op=fs程序报表用到
        if (fileName == null) {
        this.setContent(req, res, fileName, isEmbed);
    fileName = (String) sessionIDInfor.getParameterValue(ParameterConstants.__FILENAME__);
        }


      /**
  if (fileName == *null) 导出的实体操作{
     *
       * @param req//p:需要先获得导出报表的名字.
            fileName =  http请求sessionIDInfor.getWebTitle().replaceAll("\\s", "_");
     * @param res     //shoc 导出文件名不能含有逗号 否则抛错
       http响应
     *fileName @param sessionProvider 模板访问会话信息= fileName.replaceAll(",", "_");
        }

 * @param fileName     Browser browser  文件名= Browser.resolve(req);

     * @return 导出实体操作对象   fileName = browser.getEncodedFileName4Download(fileName);
     */   return fileName;
    @Override}

    public abstract ExportCollection newExportCollectioncreateCollection(HttpServletRequest req, HttpServletResponse res, SessionProvider sessionProvider, String fileName);
}

Code Block
languagejava
themeEclipse
firstline1
titleOperate.java
linenumberstrue
collapsetrue
package com.fr.web.core.reserve;

import com.fr.io.collection.ExportCollection;
import com.fr.stable.web.SessionProvider;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by richie on 16/1/19.
 */
public interface Operate {

    void setContent(HttpServletRequest req, HttpServletResponse res, String fileName, boolean isEmbed);

    void setContent(HttpServletRequest req, HttpServletResponse res, SessionProvider sessionIDInfor, String fileName, boolean isEmbed);

    ExportCollection newExportCollection(HttpServletRequest req, HttpServletResponse res, SessionProvider sessionIDInfor, String fileName);
}
,
                                                   ReportSessionIDInfor sessionIDInfor, String format,
                                                   String fileName, boolean isEmbed) throws Exception {
        Operate operate = ExportFactory.getOperate(format.toLowerCase());
        if (operate != null) {
            operate.setContent(req, res, sessionIDInfor, fileName, isEmbed);
            return operate.newExportCollection(req, res, sessionIDInfor, fileName);
        }
        return ExportCollection.create();
    }
}

ExportCollection介绍

四、支持版本

产品线

版本

支持情况

备注

FR8.0支持
FR9.0支持
FR10.0支持
BI3.6支持不支持BI的仪表板
BI4.0支持不支持BI的仪表板
BI5.1支持不支持BI的仪表板
BI5.1.2支持不支持BI的仪表板
BI5.1.3支持不支持BI的仪表板

五、插件注册

Code Block
languagexml
themeEclipse
firstline1
titleplugin.xml
linenumberstrue
<extra-report>
        <ExportOperateProvider<ExportExtensionProcessor class="your class name"/>
</extra-report>


六、原理说明

ExportFactory为所有导出类型的一个工厂类,通过format参数进行指定。工厂类加载时会注册所有插件中声明的新导出类型到OPERATE_MAP<String, Operate>对象中。实际导出服务被调用时,根据format参数,再创建具体的导出类型操作器进行导出。在沿用低版本的报表web服务体系的情况下,10.0中存在一个ExportService【op=export】的服务接口用于处理报表的导出操作。在dealWithExport方法中,会获取当前报表系统中生效的导出扩展申明(ExportExtension),从而进行对应的导出操作。

七、特殊限制说明

OPERATE_MAP<String, Operate> 注册插件中的实例是在加载产品内置的导出类型之后的,而且是直接按format设置的,所以该接口在特殊情况下也可以用于替换原来的某些导出操作器的特性。只要markType接口返回值与需要替换的导出操作器的类型一致即可。

注:如果是作为替换产品固有的导出操作器使用时,该插件不得上架到商城插件!否则容易引发冲突!markType接口返回值就是前端format参数的值。

实际的开发过程中,为了具有较好的兼容性,开发者不要直接实现Operate接口,应继承BaseOperate类进行具体的接口实现。 

BaseOperate#setContent接口主要用于实现在响应头中声明文件类型、编码等信息。【点击看例子

该接口是Immutable的,也就是是独占的,如果多个插件都有使用到,那么只会生效其中的一个。如果没有插件使用这个接口,则默认生效的是DefaultExportExtension 【注:也就是开发的时候可以参考这个类进行开发

因为接口开在了整个导出的入口,所以会影响到所有其他的报表导出相关的接口,使用的时候需要非常谨慎。除特殊情况开发者尽量不要选择这个接口,容易跟其他插件产生冲突。【注:该接口仅用于一般定制,新商城插件严禁使用这个接口,避免造成大面积冲突

该接口仅对cpt报表有效。

八、常用链接

demo地址:demo-export-operate-providerextension-processor

com.fr.report.fun.ExportOperateProvider

com.fr.stable.fun.ExcelExportCellValueProvider

com.fr.form.stable.FormExportProcessor

com.fr.report.fun.ExcelExportAppProvider

com.fr.report.fun.CommentExcelProcessor

com.fr.io.exporter.PDFExporterCreator

com.fr.report.fun.FormatActionProvider

九、开源案例

免责声明:所有文档中的开源示例,均为开发者自行开发并提供。仅用于参考和学习使用,开发者和官方均无义务对开源案例所涉及的所有成果进行教学和指导。若作为商用一切后果责任由使用者自行承担。

demo-export-xml暂无