Relatórios com Spring

Relatórios com Spring

1. Visão geral

JasperReports é uma biblioteca de relatórios de código aberto que permite aos usuários criar relatórios perfeitos que podem ser impressos ou exportados em muitos formatos, incluindo PDF, HTML e XLS.

Neste artigo, vamos explorar seus principais recursos e classes e implementar exemplos para mostrar seus recursos.

2. Dependência do Maven

Primeiro, precisamos adicionar a dependênciajasperreports ao nossopom.xml:


    net.sf.jasperreports
    jasperreports
    6.4.0

A versão mais recente deste artefato pode ser encontradahere.

3. Modelos de relatório

Os designs de relatório são definidos nos arquivos JRXML. Esses são arquivos XML comuns com uma estrutura específica que o mecanismo JasperReports pode interpretar.

Vamos agora dar uma olhada apenas na estrutura relevante dos arquivos JRXML - para entender melhor a parte Java do processo de geração de relatório, que é nosso foco principal.

Vamos criar um relatório simples para mostrar as informações do funcionário:


    
    
    
    
    
        
            
                
                
                
                  
            
            
                
                
                
                  
            
            
                
                
                
                  
            
        
    

3.1. Compilando relatórios

Os arquivos JRXML precisam ser compilados para que o mecanismo de relatório possa preenchê-los com dados.

Vamos realizar esta operação com a ajuda da classeJasperCompilerManager:

InputStream employeeReportStream
  = getClass().getResourceAsStream("/employeeReport.jrxml");
JasperReport jasperReport
  = JasperCompileManager.compileReport(employeeReportStream);

Para evitar compilá-lo sempre, podemos salvá-lo em um arquivo:

JRSaver.saveObject(jasperReport, "employeeReport.jasper");

4. Povoando Relatórios

A maneira mais comum de preencher relatórios compilados é com registros de um banco de dados. Isso requer que o relatório contenha uma consulta SQL que o mecanismo executará para obter os dados.

Primeiro, vamos modificar nosso relatório para adicionar uma consulta SQL:


    
        
    
    ...

Agora, vamos criar uma fonte de dados simples:

@Bean
public DataSource dataSource() {
    return new EmbeddedDatabaseBuilder()
      .setType(EmbeddedDatabaseType.HSQL)
      .addScript("classpath:employee-schema.sql")
      .build();
}

Agora, podemos preencher o relatório:

JasperPrint jasperPrint = JasperFillManager.fillReport(
  jasperReport, null, dataSource.getConnection());

Observe que estamos passandonull para o segundo argumento, já que nosso relatório ainda não recebeu nenhum parâmetro.

4.1. Parâmetros

Os parâmetros são úteis para passar dados ao mecanismo de relatório que ele não consegue encontrar em sua fonte de dados ou quando os dados mudam dependendo das diferentes condições de tempo de execução.

Também podemos alterar partes ou até toda a consulta SQL com parâmetros recebidos na operação de preenchimento de relatório.

Primeiro, vamos modificar o relatório para receber três parâmetros:


    
    
    
        
          
    
    // ...

Agora, vamos adicionar uma seção de título para mostrar o parâmetrotitle:


    // ...
    
        <band height="20" splitType="Stretch">
            <textField>
                <reportElement x="238" y="0" width="100" height="20"/>
                <textElement/>
                <textFieldExpression class="java.lang.String">
                  <![CDATA[$P{title}]]></textFieldExpression>
            </textField>
        </band>
    
    ...

A seguir, vamos alterar a consulta para usar os parâmetrosminSalaryecondition:

SELECT * FROM EMPLOYEE
  WHERE SALARY >= $P{minSalary} AND $P!{condition}

Observe a sintaxe diferente ao usar o parâmetrocondition. Isso informa ao mecanismo que o parâmetro não deve ser usado como um parâmetroPreparedStatement padrão, mas como se o valor desse parâmetro tivesse sido escrito originalmente na consulta SQL.

Por fim, vamos preparar os parâmetros e preencher o relatório:

Map parameters = new HashMap<>();
parameters.put("title", "Employee Report");
parameters.put("minSalary", 15000.0);
parameters.put("condition", " LAST_NAME ='Smith' ORDER BY FIRST_NAME");

JasperPrint jasperPrint
  = JasperFillManager.fillReport(..., parameters, ...);

Observe que as chaves deparameters correspondem aos nomes dos parâmetros no relatório. Se o mecanismo detectar a falta de um parâmetro, ele obterá o valor dedefaultValueExpression do parâmetro, se houver.

5. Exportador

Para exportar um relatório, primeiro, instanciamos um objeto de uma classe exportadora que corresponde ao formato de arquivo que precisamos.

Em seguida, definimos nosso relatório preenchido anterior como entrada e definimos onde produzir o arquivo resultante.

Opcionalmente, podemos definir o relatório correspondente e exportar objetos de configuração para personalizar o processo de exportação.

5.1. PDF

JRPdfExporter exporter = new JRPdfExporter();

exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(
  new SimpleOutputStreamExporterOutput("employeeReport.pdf"));

SimplePdfReportConfiguration reportConfig
  = new SimplePdfReportConfiguration();
reportConfig.setSizePageToContent(true);
reportConfig.setForceLineBreakPolicy(false);

SimplePdfExporterConfiguration exportConfig
  = new SimplePdfExporterConfiguration();
exportConfig.setMetadataAuthor("example");
exportConfig.setEncrypted(true);
exportConfig.setAllowedPermissionsHint("PRINTING");

exporter.setConfiguration(reportConfig);
exporter.setConfiguration(exportConfig);

exporter.exportReport();

5.2. XLS

JRXlsxExporter exporter = new JRXlsxExporter();

// Set input and output ...
SimpleXlsxReportConfiguration reportConfig
  = new SimpleXlsxReportConfiguration();
reportConfig.setSheetNames(new String[] { "Employee Data" });

exporter.setConfiguration(reportConfig);
exporter.exportReport();

5.3. CSV

JRCsvExporter exporter = new JRCsvExporter();

// Set input ...
exporter.setExporterOutput(
  new SimpleWriterExporterOutput("employeeReport.csv"));

exporter.exportReport();

5.4. HTML

HtmlExporter exporter = new HtmlExporter();

// Set input ...
exporter.setExporterOutput(
  new SimpleHtmlExporterOutput("employeeReport.html"));

exporter.exportReport();

6. Sub-relatórios

Os sub-relatórios nada mais são do que um relatório padrão incorporado em outro relatório.

Primeiro, vamos criar um relatório para mostrar os e-mails de um funcionário:


    
    
        
    
    
    
        
            
                
                
                
                  
            
        
    

Agora, vamos modificar nosso relatório de funcionários para incluir o anterior:


    
        
            
            
                
                  
            
            
              
            
              
        
    

Observe que estamos referenciando o sub-relatório pelo nome do arquivo compilado e passandoidEmployeee a conexão do relatório atual como parâmetros.

A seguir, vamos compilar os dois relatórios:

InputStream employeeReportStream
  = getClass().getResourceAsStream("/employeeReport.jrxml");
JasperReport jasperReport
  = JasperCompileManager.compileReport(employeeReportStream);
JRSaver.saveObject(jasperReport, "employeeReport.jasper");

InputStream emailReportStream
  = getClass().getResourceAsStream("/employeeEmailReport.jrxml");
JRSaver.saveObject(
  JasperCompileManager.compileReport(emailReportStream),
  "employeeEmailReport.jasper");

Nosso código para preencher e exportar o relatório não requer modificações.

7. Conclusão

Neste artigo, vimos brevemente os principais recursos da biblioteca JasperReports.

Conseguimos compilar e preencher relatórios com registros de um banco de dados; passamos parâmetros para alterar os dados mostrados no relatório de acordo com diferentes condições de tempo de execução, incorporamos sub-relatórios e exportamos para os formatos mais comuns.

O código-fonte completo para este artigo pode ser encontradoover on GitHub.