java - Spring Boot 应用程序中的 BIRT

标签 java spring-boot birt

我需要在现有的 spring boot web 应用程序中创建一个报告功能(函数)。建议是使用 BIRT,我可以将其与 spring boot web 应用程序集成。

我找到了下面的文章,并且能够在 spring boot 启动项目中运行报告(使用 http://start.spring.io/ )。这篇相当古老的文章确实帮助我找到了一个工作示例。 https://spring.io/blog/2012/01/30/spring-framework-birt .这篇文章基本上正是我想要的,但是在 spring boot web 应用程序中。

我面临的挑战是使用 BIRT 查看器运行报告,它具有不错的附加功能。 (打印、Expoet 数据、PDF、分页等)

我找不到任何按照本文描述的方式使用 BIRT 的 spring boot 示例。

我的问题是:

  1. 在 spring boot web 应用程序中是否有替代或其他方法来生成报告? (显然不想通过从头开始创建类似 BIRT 的功能来重新发明轮子,或者如果可能的话,将报告引擎与 Web 应用程序分开运行)

  2. 今天有没有人在 spring boot web 应用程序中使用 BIRT(与查看器一起工作)并且愿意分享或指导我如何做到这一点? (我试图让 JSP 页面与 spring boot 一起工作,但未能如此成功......更多的是缺乏经验)

谁能帮帮我。

亲切的问候, 亨克

最佳答案

依赖项、IReportEngine 实例和目录是在 spring boot web 应用程序中设置 BIRT 最具挑战性的部分。 此示例有一些错误处理,并依赖于环境变量来指定重要目录的路径。

此设置的一个优点是它是一个独立的 ReST API,用于构建和生成报告。作为一个附带的好处,它根本不依赖于 JSP。

我在 Docker 容器中运行它。

最初有计划使用一些接口(interface)来尝试其他报告框架,如 Jasper 报告或其他东西。

虽然我认为这在某些情况下更好,但这并不是您所要求的。您可以非常灵活地使用、配置和部署 BIRT 报告运行程序作为这样的应用程序。这不使用 Actian 提供的预打包 BIRT 查看器。

我会为名为 birt-report-runner-data 的报告创建一个数据容器,然后将所有用于日志记录和报告的目录放在该容器上,然后您可以将其安装到 BIRT 容器中。

主要组成部分

主文件(BirtReportRunnerApplication.java)

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BirtReportRunnerApplication {

    public static void main(String[] args) {
        SpringApplication.run(BirtReportRunnerApplication.class, args);
    }
}

接收报告请求的 Controller (ReportController.java)

package com.example.core.web.controller;

import com.example.core.model.BIRTReport;
import com.example.core.service.ReportRunner;
import com.example.core.web.dto.ReportRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController("ReportController")
@RequestMapping("/reports")
public class ReportController {

    private Logger logger = LoggerFactory.getLogger(ReportController.class);

    @Autowired
    @Qualifier("birt")
    ReportRunner reportRunner;

    @RequestMapping(value = "/birt", method = RequestMethod.POST)
    public ResponseEntity<byte[]> getBIRTReport(@RequestBody ReportRequest reportRequest) {
        byte[] reportBytes;
        ResponseEntity<byte[]> responseEntity;
        try {
            logger.info("REPORT REQUEST NAME:   " + reportRequest.getReportName());
            reportBytes =
                new BIRTReport(
                    reportRequest.getReportName(),
                    reportRequest.getReportParameters(),
                    reportRunner)
                    .runReport().getReportContent().toByteArray();

            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.setContentType(MediaType.parseMediaType("application/pdf"));
            String fileName = reportRequest.getReportName() + ".pdf";
            httpHeaders.setContentDispositionFormData(fileName, fileName);
            httpHeaders.setCacheControl("must-revalidate, post-check=0, pre-check=0");
            responseEntity = new ResponseEntity<byte[]>(reportBytes, httpHeaders, HttpStatus.OK);
        } catch (Exception e) {
            responseEntity = new ResponseEntity<byte[]>(HttpStatus.NOT_IMPLEMENTED);
            return responseEntity;
        }
        return responseEntity;
    }
}

用于指定要运行的报告的报告请求 DTO (ReportRequest.java)

package com.example.core.web.dto;

import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.List;

public class ReportRequest {
    private String reportName;
    private String reportParameters;

    public ReportRequest(@JsonProperty("reportName") String reportName,
                         @JsonProperty("reportParameters") String reportParameters) {
        this.reportName = reportName;
        this.reportParameters = reportParameters;
    }

    public String getReportName() {
        return reportName;
    }

    public String getReportParameters() {
        return reportParameters;
    }

    public void setReportParameters(String reportParameters) {
        this.reportParameters = reportParameters;
    }
}

报表运行程序接口(interface) (ReportRunner.java)

package com.example.core.service;

import com.example.core.model.Report;

import java.io.ByteArrayOutputStream;

public interface ReportRunner {

    ByteArrayOutputStream runReport(Report report);
}

完成大部分工作的最大类 (BIRTReportRunner.java)

package com.example.core.service;

import com.example.core.model.Report;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.report.engine.api.*;
import org.eclipse.core.internal.registry.RegistryProviderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;

@Service
@Qualifier("birt")
public class BIRTReportRunner implements ReportRunner {
    private static final String DEFAULT_LOGGING_DIRECTORY = "defaultBirtLoggingDirectory/";
    private Logger logger = LoggerFactory.getLogger(BIRTReportRunner.class);

    private static String reportOutputDirectory;

    private IReportEngine birtReportEngine = null;

    @Autowired
    private Environment env;

    /**
     * Starts up and configures the BIRT Report Engine
     */
    @PostConstruct
    public void startUp() {
        if(env.getProperty("birt_report_input_dir") == null)
            throw new RuntimeException("Cannot start application since birt report input directory was not specified.");
        try {
            String birtLoggingDirectory = env.getProperty("birt_logging_directory") == null ? DEFAULT_LOGGING_DIRECTORY : env.getProperty("birt_logging_directory");
            Level birtLoggingLevel = env.getProperty("birt_logging_level") == null ? Level.SEVERE : Level.parse(env.getProperty("birt_logging_level"));
            EngineConfig engineConfig = new EngineConfig();
            logger.info("BIRT LOG DIRECTORY SET TO : {}", birtLoggingDirectory);
            logger.info("BIRT LOGGING LEVEL SET TO {}", birtLoggingLevel);
            engineConfig.setLogConfig(birtLoggingDirectory, birtLoggingLevel);

            // Required due to a bug in BIRT that occurs in calling Startup after the Platform has already been started up
            RegistryProviderFactory.releaseDefault();
            Platform.startup(engineConfig);
            IReportEngineFactory reportEngineFactory = (IReportEngineFactory) Platform.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
            birtReportEngine = reportEngineFactory.createReportEngine(engineConfig);
        } catch (BirtException e) {
            // TODO add logging aspect and find out how to log a platform startup problem from this catch block, if possible, using the aspect.
            // Possibly rethrow the exception here and catch it in the aspect.
            logger.error("Birt Startup Error: {}", e.getMessage());
        }

        reportOutputDirectory = env.getProperty("birt_temp_file_output_dir");
    }

    /**
     * Shuts down the BIRT Report Engine
     */
    @PreDestroy
    public void shutdown() {
        birtReportEngine.destroy();
        RegistryProviderFactory.releaseDefault();
        Platform.shutdown();
    }

    public File getReportFromFilesystem(String reportName) throws RuntimeException {
        String reportDirectory = env.getProperty("birt_report_input_dir");
        Path birtReport = Paths.get(reportDirectory + File.separator + reportName + ".rptdesign");
        if(!Files.isReadable(birtReport))
            throw new RuntimeException("Report " + reportName + " either did not exist or was not writable.");

        return birtReport.toFile();
    }

    /**
     * This method creates and executes the report task, the main responsibility
     * of the entire Report Service.
     * This method is key to enabling pagination for the BIRT report. The IRunTask run task
     * is created and then used to generate an ".rptdocument" binary file.
     * This binary file is then read by the separately created IRenderTask render
     * task. The render task renders the binary document as a binary PDF output
     * stream which is then returned from the method.
     * <p>
     *
     * @param birtReport the report object created at the controller to hold the data of the report request.
     * @return Returns a ByteArrayOutputStream of the PDF bytes generated by the
     */
    @Override
    public ByteArrayOutputStream runReport(Report birtReport) {

        ByteArrayOutputStream byteArrayOutputStream;
        File rptDesignFile;

        // get the path to the report design file
        try {
            rptDesignFile = getReportFromFilesystem(birtReport.getName());
        } catch (Exception e) {
            logger.error("Error while loading rptdesign: {}.", e.getMessage());
            throw new RuntimeException("Could not find report");
        }

        // process any additional parameters
        Map<String, String> parsedParameters = parseParametersAsMap(birtReport.getParameters());

        byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            IReportRunnable reportDesign = birtReportEngine.openReportDesign(rptDesignFile.getPath());
            IRunTask runTask = birtReportEngine.createRunTask(reportDesign);

            if (parsedParameters.size() > 0) {
                for (Map.Entry<String, String> entry : parsedParameters.entrySet()) {
                    runTask.setParameterValue(entry.getKey(), entry.getValue());
                }
            }
            runTask.validateParameters();

            String rptdocument = reportOutputDirectory + File.separator
                    + "generated" + File.separator
                    + birtReport.getName() + ".rptdocument";
            runTask.run(rptdocument);

            IReportDocument reportDocument = birtReportEngine.openReportDocument(rptdocument);
            IRenderTask renderTask = birtReportEngine.createRenderTask(reportDocument);

            PDFRenderOption pdfRenderOption = new PDFRenderOption();
            pdfRenderOption.setOption(IPDFRenderOption.REPAGINATE_FOR_PDF, new Boolean(true));
            pdfRenderOption.setOutputFormat("pdf");
            pdfRenderOption.setOutputStream(byteArrayOutputStream);
            renderTask.setRenderOption(pdfRenderOption);

            renderTask.render();
            renderTask.close();
        } catch (EngineException e) {
            logger.error("Error while running report task: {}.", e.getMessage());
            // TODO add custom message to thrown exception
            throw new RuntimeException();
        }

        return byteArrayOutputStream;
    }

    /**
     * Takes a String of parameters started by '?', delimited by '&', and with
     * keys and values split by '=' and returnes a Map of the keys and values
     * in the String.
     *
     * @param reportParameters a String from a HTTP request URL
     * @return a map of parameters with Key,Value entries as strings
     */
    public Map<String, String> parseParametersAsMap(String reportParameters) {
        Map<String, String> parsedParameters = new HashMap<String, String>();
        String[] paramArray;
        if (reportParameters.isEmpty()) {
            throw new IllegalArgumentException("Report parameters cannot be empty");
        } else if (!reportParameters.startsWith("?") && !reportParameters.contains("?")) {
            throw new IllegalArgumentException("Report parameters must start with a question mark '?'!");
        } else {
            String noQuestionMark = reportParameters.substring(1, reportParameters.length());
            paramArray = noQuestionMark.split("&");
            for (String param : paramArray) {
                String[] paramGroup = param.split("=");
                if (paramGroup.length == 2) {
                    parsedParameters.put(paramGroup[0], paramGroup[1]);
                } else {
                    parsedParameters.put(paramGroup[0], "");
                }

            }
        }
        return parsedParameters;
    }
}

报表对象类(Report.java)

package com.example.core.model;

import com.example.core.service.ReportRunner;

import java.io.ByteArrayOutputStream;
import java.util.List;

/**
 * A Report object has a byte representation of the report output that can be
 * used to write to any output stream. This class is designed around the concept
 * of using ByteArrayOutputStreams to write PDFs to an output stream.
 *
 *
 */
public abstract class Report {

    protected String name;
    protected String parameters;
    protected ByteArrayOutputStream reportContent;
    protected ReportRunner reportRunner;

    public Report(String name, String parameters, ReportRunner reportRunner) {
        this.name = name;
        this.parameters = parameters;
        this.reportRunner = reportRunner;
    }

    /**
     * This is the processing method for a Report. Once the report is ran it
     * populates an internal field with a ByteArrayOutputStream of the
     * report content generated during the run process.
     * @return Returns itself with the report content output stream created.
     */
    public abstract Report runReport();

    public ByteArrayOutputStream getReportContent() {
        return this.reportContent;
    }

    public String getName() {
        return name;
    }

    public String getParameters() {
        return parameters;
    }
}

BIRTReport 对象类 (BIRTReport.java)

package com.example.core.model;

import com.example.core.service.ReportRunner;

public class BIRTReport extends Report {

    public BIRTReport(String name, String reportParameters, ReportRunner reportRunner) {
        super(name, reportParameters, reportRunner);
    }

    @Override
    public Report runReport() {
        this.reportContent = reportRunner.runReport(this);
        return this;
    }
}

构建文件(build.gradle)

buildscript {
    ext {
        springBootVersion = '1.3.2.RELEASE'
    }
    repositories {
        jcenter()

    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("io.spring.gradle:dependency-management-plugin:0.5.2.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'com.example.simple-birt-runner'
    version = '1.0.0'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

ext {
    springBootVersion = '1.3.0.M5'
}

repositories {
    jcenter()
    mavenCentral()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-actuator:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")


    // BIRT Runtime and ReportEngine dependencies
    // These were pulled from the Actuate download site at http://download.eclipse.org/birt/downloads/ for version 4.5.0
    compile fileTree(dir: 'lib', include: '*.jar')
    /*compile("org.eclipse.birt.runtime:org.eclipse.birt.runtime:4.4.2") {
        exclude group: "org.eclipse.birt.runtime", module: "org.apache.poi"
        exclude group: "org.eclipse.birt.runtime", module: "org.eclipse.orbit.mongodb"
    }*/

    compile("org.springframework.boot:spring-boot-starter-tomcat")

    // include any runtime JDBC driver dependencies here

    testCompile("org.springframework.boot:spring-boot-starter-test")
}

依赖

获取 Birt Viewer lib 目录中的所有依赖项并将它们放在类路径中。以下是外部依赖项的完整列表:

com.ibm.icu_54.1.1.v201501272100.jar
com.lowagie.text_2.1.7.v201004222200.jar
derby.jar
flute.jar
javax.wsdl_1.5.1.v201012040544.jar
javax.xml.stream_1.0.1.v201004272200.jar
javax.xml_1.3.4.v201005080400.jar
net.sourceforge.lpg.lpgjavaruntime_1.1.0.v201004271650.jar
org.apache.batik.bridge_1.6.0.v201011041432.jar
org.apache.batik.css_1.6.0.v201011041432.jar
org.apache.batik.dom.svg_1.6.0.v201011041432.jar
org.apache.batik.dom_1.6.1.v201505192100.jar
org.apache.batik.ext.awt_1.6.0.v201011041432.jar
org.apache.batik.parser_1.6.0.v201011041432.jar
org.apache.batik.pdf_1.6.0.v201105071520.jar
org.apache.batik.svggen_1.6.0.v201011041432.jar
org.apache.batik.transcoder_1.6.0.v201011041432.jar
org.apache.batik.util.gui_1.6.0.v201011041432.jar
org.apache.batik.util_1.6.0.v201011041432.jar
org.apache.batik.xml_1.6.0.v201011041432.jar
org.apache.commons.codec_1.6.0.v201305230611.jar
org.apache.commons.logging_1.1.1.v201101211721.jar
org.apache.lucene.core_3.5.0.v20120725-1805.jar
org.apache.poi_3.9.0.v201405241750.jar
org.apache.xerces_2.9.0.v201101211617.jar
org.apache.xml.resolver_1.2.0.v201005080400.jar
org.apache.xml.serializer_2.7.1.v201005080400.jar
org.eclipse.birt.runtime_4.5.0.jar
org.eclipse.core.contenttype_3.5.0.v20150421-2214.jar
org.eclipse.core.expressions_3.5.0.v20150421-2214.jar
org.eclipse.core.filesystem_1.5.0.v20150421-0713.jar
org.eclipse.core.jobs_3.7.0.v20150330-2103.jar
org.eclipse.core.resources_3.10.0.v20150423-0755.jar
org.eclipse.core.runtime.compatibility_3.2.300.v20150423-0821.jar
org.eclipse.core.runtime_3.11.0.v20150405-1723.jar
org.eclipse.datatools.connectivity.apache.derby.dbdefinition_1.0.2.v201107221459.jar
org.eclipse.datatools.connectivity.apache.derby_1.0.103.v201212070447.jar
org.eclipse.datatools.connectivity.console.profile_1.0.10.v201109250955.jar
org.eclipse.datatools.connectivity.db.generic_1.0.1.v201107221459.jar
org.eclipse.datatools.connectivity.dbdefinition.genericJDBC_1.0.2.v201310181001.jar
org.eclipse.datatools.connectivity.oda.consumer_3.2.6.v201403131814.jar
org.eclipse.datatools.connectivity.oda.design_3.3.6.v201403131814.jar
org.eclipse.datatools.connectivity.oda.flatfile_3.1.8.v201403010906.jar
org.eclipse.datatools.connectivity.oda.profile_3.2.9.v201403131814.jar
org.eclipse.datatools.connectivity.oda_3.4.3.v201405301249.jar
org.eclipse.datatools.connectivity.sqm.core_1.2.8.v201401230755.jar
org.eclipse.datatools.connectivity_1.2.11.v201401230755.jar
org.eclipse.datatools.enablement.hsqldb.dbdefinition_1.0.0.v201107221502.jar
org.eclipse.datatools.enablement.hsqldb_1.0.0.v201107221502.jar
org.eclipse.datatools.enablement.ibm.db2.iseries.dbdefinition_1.0.3.v201107221502.jar
org.eclipse.datatools.enablement.ibm.db2.iseries_1.0.2.v201107221502.jar
org.eclipse.datatools.enablement.ibm.db2.luw.dbdefinition_1.0.7.v201405302027.jar
org.eclipse.datatools.enablement.ibm.db2.luw_1.0.3.v201401170830.jar
org.eclipse.datatools.enablement.ibm.db2.zseries.dbdefinition_1.0.4.v201107221502.jar
org.eclipse.datatools.enablement.ibm.db2.zseries_1.0.2.v201107221502.jar
org.eclipse.datatools.enablement.ibm.db2_1.0.0.v201401170830.jar
org.eclipse.datatools.enablement.ibm.informix.dbdefinition_1.0.4.v201107221502.jar
org.eclipse.datatools.enablement.ibm.informix_1.0.1.v201107221502.jar
org.eclipse.datatools.enablement.ibm_1.0.0.v201401170830.jar
org.eclipse.datatools.enablement.msft.sqlserver.dbdefinition_1.0.1.v201201240505.jar
org.eclipse.datatools.enablement.msft.sqlserver_1.0.3.v201308161009.jar
org.eclipse.datatools.enablement.mysql.dbdefinition_1.0.4.v201109022331.jar
org.eclipse.datatools.enablement.mysql_1.0.4.v201212120617.jar
org.eclipse.datatools.enablement.oda.ws_1.2.6.v201403131825.jar
org.eclipse.datatools.enablement.oda.xml_1.2.5.v201403131825.jar
org.eclipse.datatools.enablement.oracle.dbdefinition_1.0.103.v201206010214.jar
org.eclipse.datatools.enablement.oracle_1.0.0.v201107221506.jar
org.eclipse.datatools.enablement.postgresql.dbdefinition_1.0.2.v201110070445.jar
org.eclipse.datatools.enablement.postgresql_1.1.1.v201205252207.jar
org.eclipse.datatools.enablement.sap.maxdb.dbdefinition_1.0.0.v201107221507.jar
org.eclipse.datatools.enablement.sap.maxdb_1.0.0.v201107221507.jar
org.eclipse.datatools.modelbase.dbdefinition_1.0.2.v201107221519.jar
org.eclipse.datatools.modelbase.derby_1.0.0.v201107221519.jar
org.eclipse.datatools.modelbase.sql.query_1.1.4.v201212120619.jar
org.eclipse.datatools.modelbase.sql_1.0.6.v201208230744.jar
org.eclipse.datatools.sqltools.data.core_1.2.3.v201212120623.jar
org.eclipse.datatools.sqltools.parsers.sql.lexer_1.0.1.v201107221520.jar
org.eclipse.datatools.sqltools.parsers.sql.query_1.2.1.v201201250511.jar
org.eclipse.datatools.sqltools.parsers.sql_1.0.2.v201107221520.jar
org.eclipse.datatools.sqltools.result_1.1.6.v201402080246.jar
org.eclipse.emf.common_2.11.0.v20150512-0501.jar
org.eclipse.emf.ecore.change_2.11.0.v20150512-0501.jar
org.eclipse.emf.ecore.xmi_2.11.0.v20150512-0501.jar
org.eclipse.emf.ecore_2.11.0.v20150512-0501.jar
org.eclipse.equinox.app_1.3.300.v20150423-1356.jar
org.eclipse.equinox.common_3.7.0.v20150402-1709.jar
org.eclipse.equinox.preferences_3.5.300.v20150408-1437.jar
org.eclipse.equinox.registry_3.6.0.v20150318-1503.jar
org.eclipse.help_3.6.0.v20130326-1254.jar
org.eclipse.osgi.services_3.5.0.v20150519-2006.jar
org.eclipse.osgi_3.10.100.v20150529-1857.jar
org.eclipse.update.configurator_3.3.300.v20140518-1928.jar
org.mozilla.javascript_1.7.5.v201504281450.jar
org.w3c.css.sac_1.3.1.v200903091627.jar
org.w3c.dom.events_3.0.0.draft20060413_v201105210656.jar
org.w3c.dom.smil_1.0.1.v200903091627.jar
org.w3c.dom.svg_1.1.0.v201011041433.jar

应用程序属性(application.yml)

birt:
  report:
    output:
      dir: ${birt_temp_file_output_dir}
    input:
      dir: ${birt_report_input_dir}
  logging:
    level: ${birt_logging_level}


server:
  port: 8080
  context-path: /simple-birt-runner


birt:
  logging:
    level: SEVERE

logging:
  level:
    org:
      springframework:
        web: ERROR

运行用的Dockerfile(Dockerfile)

FROM java:openjdk-8u66-jre
MAINTAINER Kent O. Johnson <kentoj@gmail.com>

COPY com.example.simple-birt-runner-*.jar /opt/soft/simple-birt-runner.jar

RUN mkdir -p /reports/input \
    && mkdir /reports/output \
    && mkdir -p /reports/log/engine

WORKDIR /opt/soft

CMD java -jar -Xms128M -Xmx4G simple-birt-runner.jar

EXPOSE 8080

运行镜像的docker compose文件(docker-compose.yml)

simple-birt-runner:
  image: soft/simple-birt-runner-release
  ports:
  - "8090:8080"
  environment:
  - birt_temp_file_output_dir=/reports/output
  - birt_report_input_dir=/reports/input
  - birt_logging_directory=/reports/log/engine
  - birt_logging_level=SEVERE
  volumes_from:
  - birt-report-runner-data

关于java - Spring Boot 应用程序中的 BIRT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32069938/

相关文章:

java - 如何填充 GridView 中的空单元格并使其不可点击

java - 在 Google App Engine 上存储 google protocol buffers

java - Java 中的对象清除与恢复

java - 使用 dx.bat 时错误的类文件魔术

java - 基于 BIRT 中的另一个表更改表值

PostgreSQL - 查询 3 个表

spring-boot - Spring Boot Multi Module Gradle Project 类路径问题 : Package Not Found, Symbol not Found

json - 如何将flutter中的日期解析为与Java ZonedDateTime兼容的json字符串

java - 根据 application.yml 中的属性使用 Spring Boot 进行注入(inject)

maven - 没有启动 Maven 的 Birt Report Viewer