Implementar Springboot para integrar UReport2

1. ¿Qué es UReport2?

UReport2 es un motor de informes de Java puro de alto rendimiento basado en Spring, que puede generar informes de estilo chino arbitrariamente complejos mediante la iteración de celdas. Este informe es un motor de informes chino de código abierto basado en el protocolo Apache-2.0 desarrollado por Shanghai Ruidao Information Technology Co., Ltd. (haga clic para ingresar a la página de código fuente de gitee ). El motor de informes actual no ha sido mantenido por el autor por razones desconocidas, pero los documentos anteriores son relativamente detallados ( haga clic para ingresar a la página del documento ).

2. ¿Por qué se debe integrar UReport2?

El autor también está interesado en el principio de implementación del motor de informes, así que descargué el código fuente y ajusté y optimicé algunos detalles. Se recomienda que los estudiantes que estén interesados ​​en el motor de informes puedan descargar el código fuente para el ajuste personalizado y la optimización de la investigación. Al mismo tiempo, se implementa una demostración de informe simple usando springboot+mysql+jfinal+iview+jquery. Aquí hay un registro de estudio simple y compártalo con todos los estudiantes. Espero poder continuar mejorando y mejorando mi capacidad técnica junto con tú.

3. Date cuenta del resultado

Primera parte de la captura de pantalla para mostrar los resultados de la implementación.

3.1 Lista de informes

inserte la descripción de la imagen aquí

3.2 Diseñador de informes

inserte la descripción de la imagen aquí

3.3 Vista previa del informe de puntaje promedio del estudiante

inserte la descripción de la imagen aquí

3.4 Vista previa del informe de puntuación integral

inserte la descripción de la imagen aquí

3.5 Vista previa del informe de expediente académico del estudiante

inserte la descripción de la imagen aquí

4. Proceso de implementación

Primero ponga un diagrama de estructura de archivos del sistema
inserte la descripción de la imagen aquí

4.1 Crear un proyecto springboot

Asigne un nombre al proyecto ureport y agregue las dependencias maven requeridas en el archivo pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.crwl</groupId>
    <artifactId>ureport</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring-cloud.version>2.1.1.RELEASE</spring-cloud.version>
        <flowable.version>6.5.0</flowable.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <version>2.0.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.0.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.0.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
            <version>1.16.20</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>6.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>RELEASE</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.6.10</version>
        </dependency>
        <dependency>
            <groupId>com.jfinal</groupId>
            <artifactId>activerecord</artifactId>
            <version>4.8</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>
        <dependency>
            <groupId>com.bstek.ureport</groupId>
            <artifactId>ureport2-console</artifactId>
            <version>2.3.0-pro</version>
        </dependency>
    </dependencies>
</project>

Aquí, el paquete jar de ureport2 depende de que el autor vuelva a editar y compilar el código fuente para generarlo. Si utiliza directamente el paquete jar descargado oficial de UReport2, es posible que esta demostración no pueda ejecutarse. Si el usuario necesita la versión actual paquete jar, póngase en contacto con el autor.

4.2 Agregar información de configuración de yml

aplicación.yaml

server:
  port: 9090
  servlet:
    context-path: /pro
spring:
  http:
    encoding:
      force: true
      enabled: true
      charset: UTF-8
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ureport?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false&allowMultiQueries=true&nullNamePatternMatchesAll=true
    username: root
    password:
    type: com.alibaba.druid.pool.DruidDataSource
  resources:
    static-locations: classpath:/,classpath:/static/

4.3 Agregue el archivo de configuración de Spring context.xml que hace referencia a UReport2

El autor se coloca en el directorio resources/config

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <import resource="classpath:ureport-console-context.xml" />
    <bean id="propertyConfigurer" parent="ureport.props">
        <property name="locations">
            <list>
                <value>classpath:config/config.properties</value>
            </list>
        </property>
    </bean>
    <bean id="ureport.fielToDataBaseProvider" class="com.crwl.provider.FileToDatabaserProvider">
        <property name="fileStoreDir" value="${ureport.fileToDbStoreDir}"></property>
        <property name="disabled" value="${ureport.disableFileDbProvider}"></property>
    </bean>
</beans>

4.4, agregar archivo de propiedades

config.properties

#配置文件系统对应的报表文件地址
#ureport.fileStoreDir=D:/myfile/ureportfiles
# 是否禁用
ureport.disableFileProvider=true
#配置同数据库关联文件系统对应的报表文件地址
ureport.fileToDbStoreDir=D:/myfile/ureportDbfiles
# 是否禁用
ureport.disableFileDbProvider=false
# 配置ureport根路径,对应ureport-console/src/main/resources/ureport-console-context.xml中的ureport.designerServletAction
ureport.contextPath=/pro

4.4.1, ureport.fileStoreDir

El motor de informes de UReport2 utiliza el sistema de archivos de forma predeterminada, donde ureport.fileStoreDir es la ruta física del archivo de informe generado por la configuración, ureport.disableFileProvider define si deshabilitar el sistema de archivos del informe actual, verdadero está deshabilitado, falso está habilitado . La idea actual del autor es combinar el sistema de archivos con la base de datos mysql para la administración, por lo que la configuración está deshabilitada.

4.4.2, ureport.fileToDbStoreDir

ureport.fileToDbStoreDir es una forma de combinar el sistema de archivos mysql+ ampliado por el autor. Este parámetro también es la ruta de configuración. Si la configuración de ureport.disableFileDbProvider está deshabilitada

4.4.3, ureport.contextPath

El parámetro ureport.contextPath es un parámetro agregado por el autor.Este parámetro puede ayudar a los usuarios a darse cuenta de la situación en la que la dirección de ruta de recursos predeterminada del informe no coincide cuando el sistema de antecedentes comerciales está separado del front-end. La demostración actual no utiliza la separación front-end y back-end, por lo que este parámetro se puede configurar o no. Si no se configura, el valor predeterminado es la ruta de contexto correspondiente al archivo application.yaml.

4.5, código fuente java

4.5.1、DataSourceConfig.java

package com.crwl.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.crwl.model._MappingKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;

import javax.sql.DataSource;
/**
 * @author teamo
 * @Package com.crwl.config
 * @Description:
 * @date 2022-8-17
 */
@Configuration
public class DataSourceConfig {
    
    
    @Primary
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druidDataSource() {
    
    
        return new DruidDataSource();
    }

    /**
     * 设置数据源代理
     */
    @Bean
    public TransactionAwareDataSourceProxy transactionAwareDataSourceProxy() {
    
    
        TransactionAwareDataSourceProxy transactionAwareDataSourceProxy = new TransactionAwareDataSourceProxy();
        transactionAwareDataSourceProxy.setTargetDataSource(druidDataSource());
        return transactionAwareDataSourceProxy;
    }

    /**
     * 设置ActiveRecord
     */
    @Bean
    public ActiveRecordPlugin activeRecordPlugin() {
    
    
        ActiveRecordPlugin arp = new ActiveRecordPlugin(transactionAwareDataSourceProxy());
        arp.setDialect(new MysqlDialect());
        arp.setContainerFactory(new CaseInsensitiveContainerFactory(true));//忽略大小写
        arp.setShowSql(true);
        arp.getEngine().setToClassPathSourceFactory();
        //arp.addSqlTemplate("sql/all.sql");
        _MappingKit.mapping(arp);
        arp.start();
        System.out.println("调用Jfinal ActiveRecordPlugin 成功");
        return arp;
    }
}

Esta clase se usa principalmente para inicializar el enlace de la base de datos y Jfinal de acuerdo con el archivo de configuración.
Si los usuarios no saben mucho sobre JFinal, pueden aprender por sí mismos en Baidu. JFinal es un marco de desarrollo web extremadamente rápido basado en el lenguaje Java. Sus principales objetivos de diseño son un desarrollo rápido, menos código, fácil aprendizaje, funciones potentes, ligero, de fácil expansión y tranquilo. La demostración actual utiliza principalmente las funciones de la base de datos de Jfinal.

4.5.2, clase de modelo Report.java,BaseReport.java,_MappingKit.java

El modelo es la clase de objeto de entidad de jfinal, que se utiliza principalmente para la relación de mapeo orm con la tabla de datos.

package com.crwl.model;

import com.crwl.model.base.BaseReport;
/**
 * Generated by JFinal.
 */
@SuppressWarnings("serial")
public class Report extends BaseReport<Report> {
    
    
	public static final Report dao = new Report().dao();
}

BaseReport.java

package com.crwl.model.base;

import com.jfinal.plugin.activerecord.IBean;
import com.jfinal.plugin.activerecord.Model;

import java.util.Date;

/**
 * Generated by JFinal, do not modify this file.
 */
@SuppressWarnings({
    
    "serial", "unchecked"})
public abstract class BaseReport<M extends BaseReport<M>> extends Model<M> implements IBean {
    
    
	public M setId(Integer id) {
    
    
		set("id", id);
		return (M)this;
	}
	public Integer getId() {
    
    
		return getInt("id");
	}
	public M setRptCode(String rptCode) {
    
    
		set("rpt_code", rptCode);
		return (M)this;
	}
	public String getRptCode() {
    
    
		return getStr("rpt_code");
	}
	public M setRptName(String rptName) {
    
    
		set("rpt_name", rptName);
		return (M)this;
	}
	public String getRptName() {
    
    
		return getStr("rpt_name");
	}
	public M setRptType(Integer rptType) {
    
    
		set("rpt_type", rptType);
		return (M)this;
	}
	public Integer getRptType() {
    
    
		return getInt("rpt_type");
	}
	public M setUreportName(String ureportName) {
    
    
		set("ureport_name", ureportName);
		return (M)this;
	}
	public String getUreportName() {
    
    
		return getStr("ureport_name");
	}
	public M setRptUrl(String rptUrl) {
    
    
		set("rpt_url", rptUrl);
		return (M)this;
	}
	public String getRptUrl() {
    
    
		return getStr("rpt_url");
	}
	public M setRemark(String remark) {
    
    
		set("remark", remark);
		return (M)this;
	}
	public String getRemark() {
    
    
		return getStr("remark");
	}
	public M setSort(Integer sort) {
    
    
		set("sort", sort);
		return (M)this;
	}
	public Integer getSort() {
    
    
		return getInt("sort");
	}
	public M setStatus(Integer status) {
    
    
		set("status", status);
		return (M)this;
	}
	public Integer getStatus() {
    
    
		return getInt("status");
	}
	public M setCreateUser(String createUser) {
    
    
		set("create_user", createUser);
		return (M)this;
	}
	public String getCreateUser() {
    
    
		return getStr("create_user");
	}
	public M setCreateDate(Date createDate) {
    
    
		set("create_date", createDate);
		return (M)this;
	}
	public Date getCreateDate() {
    
    
		return getDate("create_date");
	}
	public M setUpdateUser(String updateUser) {
    
    
		set("update_user", updateUser);
		return (M)this;
	}
	public String getUpdateUser() {
    
    
		return getStr("update_user");
	}
	public M setUpdateDate(Date updateDate) {
    
    
		set("update_date", updateDate);
		return (M)this;
	}
	public Date getUpdateDate() {
    
    
		return getDate("update_date");
	}
}

_MappingKit.java

package com.crwl.model;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
public class _MappingKit {
    
    
	public static void mapping(ActiveRecordPlugin arp) {
    
    
		arp.addMapping("ur_report", "id", Report.class);
	}
}

4.5.3, Clase de controlador

ReportController.java, clase de controlador de informe

package com.crwl;

import com.bstek.ureport.console.UReportServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * 入口类
 */
@SpringBootApplication()
@EnableTransactionManagement
@ImportResource("classpath:config/context.xml")
@ComponentScan(basePackages = {
    
    "com.crwl.*"})
public class UreportApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(UreportApplication.class, args);
    }
    //ureport报表
    @Bean
    public ServletRegistrationBean buildUReprtServlet(){
    
    
        return new ServletRegistrationBean(new UReportServlet(),"/ureport/*");
    }
}

4.5.4, Clase de servicio ReportService.java, ReportServiceImpl.java

ReportService.java

package com.crwl.service;
import com.crwl.model.Report;
import com.jfinal.plugin.activerecord.Page;

public interface ReportService {
    
    
    /***
     * 获取表格数据
     * @param currentPage
     * @param pageSize
     * @param rptName
     * @param rptType
     * @return
     */
    Page<Report> getPageList(Integer currentPage, Integer pageSize, String rptName, String rptType);
}

ReportServiceImpl.java

package com.crwl.service.impl;

import com.crwl.model.Report;
import com.crwl.service.ReportService;
import com.jfinal.plugin.activerecord.Page;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

@Service
public class ReportServiceImpl implements ReportService {
    
    
    private final String table = "ur_report";

    @Override
    public Page<Report> getPageList(Integer currentPage, Integer pageSize, String rptName, String rptType) {
    
    
        StringBuilder sql = new StringBuilder();
        sql.append(" from "+ table + " t where 1=1 ");
        if(StringUtils.isNotEmpty(rptName)){
    
    
            sql.append(" and instr(t.rpt_name,'"+rptName +"')>0 ");
        }
        if(StringUtils.isNotEmpty(rptType)){
    
    
            sql.append(" and t.rpt_type="+rptType);
        }
        sql.append(" order by t.sort desc ");
        Page<Report> pageList = Report.dao.paginate(currentPage,pageSize,"select t.* ",sql.toString());
        return pageList;
    }
}

4.5.4, Clase de proveedor

La clase de proveedor es una clase de interfaz abierta por UReport para que la implemente el sistema comercial. Los usuarios pueden implementar diferentes clases de proveedor al mismo tiempo para satisfacer las necesidades comerciales del usuario desde el nivel del código.
DsProvider.java : a través de la interfaz BuildingDatasource, los usuarios pueden proporcionar fuentes de datos a nivel de interfaz para la interfaz de diseño de informes.
Una vez que se implementa la interfaz actual, el enlace de la base de datos actual se puede usar directamente en la interfaz de diseño de informes.
inserte la descripción de la imagen aquíinserte la descripción de la imagen aquí

package com.crwl.provider;

import com.bstek.ureport.definition.datasource.BuildinDatasource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

//提供ureport 内置数据源连接
@Component("dsScoreSys")
public class DsProvider implements BuildinDatasource {
    
    
    @Autowired
    private DataSource dataSource;

    @Override
    public String name() {
    
    
        return "scoreSys";
    }
    @Override
    public Connection getConnection() {
    
    
        try {
    
    
            return dataSource.getConnection();
        } catch (SQLException e) {
    
    
            e.printStackTrace();
            return null;
        }
    }
}

FileToDatabaserProvider.java : al implementar la interfaz ReportProvider, los usuarios pueden agregar métodos de almacenamiento de informes que satisfagan sus propias necesidades (UReport2 mismo ha implementado el método de almacenamiento de informes de almacenamiento de sistema de archivos puro). Al implementar la interfaz actual, el autor se da cuenta del uso de la base de datos para almacenar la información básica del informe, el sistema de archivos para almacenar el archivo del informe y la base de datos para registrar la dirección del informe. Es decir, puede usar tablas de datos mysql para administrar archivos de informes.

package com.crwl.provider;

import com.bstek.ureport.exception.ReportException;
import com.bstek.ureport.provider.report.ReportFile;
import com.bstek.ureport.provider.report.ReportProvider;
import com.crwl.model.Report;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.util.*;

public class FileToDatabaserProvider implements ReportProvider {
    
    
    private String prefix="fileToDb:";
    private String fileStoreDir;
    private String disabled;

    @Override
    public InputStream loadReport(String file) {
    
    
        if(StringUtils.isNotEmpty(file)){
    
    
            String[] arr = file.split("@");
            Report report = null;
            if(null != arr && arr.length==2){
    
    
                report = Report.dao.findById(Integer.parseInt(arr[1]));
                file = report.getUreportName();
            }else{
    
    
                report = Report.dao.findFirst(" select * from ur_report t where t.ureport_name=?", file);
            }
            if(null != report) {
    
    
                if (file.startsWith(prefix)) {
    
    
                    file = file.substring(prefix.length(), file.length());
                }
                String fullPath = fileStoreDir + "/" + file;
                try {
    
    
                    return new FileInputStream(fullPath);
                } catch (FileNotFoundException e) {
    
    
                    throw new ReportException(e);
                }
            }else{
    
    
                throw new ReportException("报表文件不存在");
            }
        }else{
    
    
            throw new ReportException("报表文件不存在");
        }
    }

    @Override
    public void deleteReport(String file) {
    
    
        Report report = Report.dao.findFirst(" select * from ur_report t where t.ureport_name=?",file);
        if(null != report){
    
    
            if(file.startsWith(prefix)){
    
    
                file=file.substring(prefix.length(),file.length());
            }
            String fullPath=fileStoreDir+"/"+file;
            File f=new File(fullPath);
            if(f.exists()){
    
    
                f.delete();
            }
            report.delete();
        }
    }
    @Override
    public List<ReportFile> getReportFiles() {
    
    
        List<Report> reportList = Report.dao.find("select * from ur_report t where t.rpt_type=2 ");
        File file=new File(fileStoreDir);
        List<ReportFile> list=new ArrayList<ReportFile>();
        for(File f:file.listFiles()){
    
    
            Calendar calendar=Calendar.getInstance();
            calendar.setTimeInMillis(f.lastModified());
            Report report = null;
            for(int i=0; i<reportList.size();i++){
    
    
                Report r = reportList.get(i);
                String reportName = r.getUreportName();
                if(StringUtils.isNotEmpty(reportName)){
    
    
                    reportName = reportName.substring(prefix.length(), reportName.length());
                    if(f.getName().equals(reportName)){
    
    
                        report = r;
                    }
                }
            }
            if(null != report){
    
    
                list.add(new ReportFile(report.getId(),f.getName(),calendar.getTime()));
            }
        }
        Collections.sort(list, new Comparator<ReportFile>(){
    
    
            @Override
            public int compare(ReportFile f1, ReportFile f2) {
    
    
                return f2.getUpdateDate().compareTo(f1.getUpdateDate());
            }
        });
        return list;
    }

    @Override
    public void saveReport(String file, String content) {
    
    
        if(StringUtils.isNotEmpty(file)) {
    
    
            String[] arr = file.split("@");
            Report report = null;
            if(null != arr && arr.length==2){
    
    
                report = Report.dao.findById(Integer.parseInt(arr[0]));
                file = arr[1];
            }else{
    
    
                report = Report.dao.findFirst(" select * from ur_report t where t.ureport_name=?", file);
            }
            if (null != report) {
    
    
                report.setUreportName(file);
                report.setRptUrl("ureport/preview?_u=" + file);
                if (file.startsWith(prefix)) {
    
    
                    file = file.substring(prefix.length(), file.length());
                }
                String fullPath = fileStoreDir + "/" + file;
                FileOutputStream outStream = null;
                try {
    
    
                    outStream = new FileOutputStream(new File(fullPath));
                    IOUtils.write(content, outStream, "utf-8");
                } catch (Exception ex) {
    
    
                    throw new ReportException(ex);
                } finally {
    
    
                    if (outStream != null) {
    
    
                        try {
    
    
                            outStream.close();
                        } catch (IOException e) {
    
    
                            e.printStackTrace();
                        }
                    }
                }
                report.setUpdateDate(new Date());
                report.update();
            } else {
    
    
                throw new ReportException("报表文件不存在");
            }
        }else{
    
    
            throw new ReportException("报表文件不存在");
        }
    }
    @Override
    public String getName() {
    
    
        return "数据库文件系统";
    }
    @Override
    public boolean disabled() {
    
    
        return false;
    }
    @Override
    public String getPrefix() {
    
    
        return prefix;
    }
    public void setFileStoreDir(String fileStoreDir) {
    
    
        this.fileStoreDir = fileStoreDir;
    }
    public void setDisabled(String disabled) {
    
    
        this.disabled = disabled;
    }
}

método loadReport : encuentre el archivo de informe de la base de datos a través de los parámetros proporcionados, genere un objeto InputStream de acuerdo con la dirección de la dirección y el diseñador de informes representa el archivo de informe que se está diseñando de acuerdo con el objeto InputStream devuelto

Método deleteReport : Proporcione los parámetros dados para eliminar el archivo de informe. La operación de este método es eliminar primero los registros en la base de datos correspondiente y luego eliminar el archivo de informe físico correspondiente.

Método getReportFiles : carga todos los registros de informes de datos actuales.

Método saveReport : encuentre el registro del informe a través de los parámetros dados, actualice la dirección de vista previa del informe y guarde el archivo del informe físico.

UreportContextProvider.java es una interfaz extendida por el autor para cambiar el parámetro contextPath del informe. Su función es la misma que la del parámetro ureport.contextPath en el archivo config.properties. No se usa aquí, por lo que no se presentará.

4.5.5, clase de inicio springboot

UreportApplication.java
@ImportResource("classpath:config/context.xml") no se puede perder, es el archivo de configuración de primavera que presenta ureport2.
El método buildUReprtServlet es registrar UReport como un Servlet, que es el archivo de entrada para usar UReport, que no puede faltar.

package com.crwl;

import com.bstek.ureport.console.UReportServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * 入口类
 */
@SpringBootApplication()
@EnableTransactionManagement
@ImportResource("classpath:config/context.xml")
@ComponentScan(basePackages = {
    
    "com.crwl.*"})
public class UreportApplication {
    
    

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

    //ureport报表
    @Bean
    public ServletRegistrationBean buildUReprtServlet(){
    
    
        return new ServletRegistrationBean(new UReportServlet(),"/ureport/*");
    }
}

4.5.5, otras clases

Result.java : devuelve la clase Dto de front-end

package com.crwl.dto;
import com.crwl.enums.ResultEnum;
import java.io.Serializable;
/**
 * 返回的对象(统一返回)
 *
 * @author SmallStrong
 */
public class Result implements Serializable {
    
    
    /**
     *
     */
    private static final long serialVersionUID = 3337439376898084639L;
    /**
     * 处理状态
     */
    private Integer code;
    /**
     * 处理信息
     */
    private String msg;
    private String serverID;
    /**
     * 返回值
     */
    private Object data;
    private int total;
    private Object rows;
    /**
     * 成功,传入data(使用最多)
     *
     * @param data
     * @return
     */
    public static Result success(Object data) {
    
    
        return Result.success(data,"请求成功!");
    }
    /**
     * 成功,传入data(使用最多)
     * @param msg
     * @return
     */
    public static Result success(String msg) {
    
    
        Result result = new Result();
        result.setCode(ResultEnum.SUCCESS.getCode());
        result.setMsg(msg);
        return result;
    }
    /**
     * 成功,传入rows和total
     * @param rows
     * @param total
     * @return
     */
    public static Result success(Object rows,int total) {
    
    
        Result result = new Result();
        result.setCode(ResultEnum.SUCCESS.getCode());
        result.setMsg("请求成功!");
        result.setRows(rows);
        result.setTotal(total);
        return result;
    }

    /**
     * 成功,传入data 和 msg
     * @param data
     * @param msg
     * @return
     */
    public static Result success(Object data, String msg) {
    
    
        Result result = new Result();
        result.setCode(ResultEnum.SUCCESS.getCode());
        result.setMsg(msg);
        result.setData(data);
        return result;
    }
    /**
     * 失败
     * @return
     */
    public static Result error() {
    
    
        return Result.error("请求失败!");
    }
    /**
     * 失败 传入 msg
     * @param msg
     * @return
     */
    public static Result error(String msg) {
    
    
        return  Result.error(msg,ResultEnum.FAILURE);
    }

    public static Result error(String msg ,ResultEnum resultEnum){
    
    
        Result result = new Result();
        result.setCode(resultEnum.getCode());
        result.setMsg(msg);
        return result;
    }
    public Integer getCode() {
    
    
        return code;
    }
    public void setCode(Integer code) {
    
    
        this.code = code;
        if(null != this.data && this.data.getClass().getName().equals("com.crwl.commonserver.dto.CurrUser")){
    
    
            this.data = null;
        }
    }
    public String getMsg() {
    
    
        return msg;
    }
    public void setMsg(String msg) {
    
    
        this.msg = msg;
    }
    public String getServerID() {
    
    
        return serverID;
    }
    public void setServerID(String serverID) {
    
    
        this.serverID = serverID;
    }
    public Object getData() {
    
    
        return data;
    }
    public void setData(Object data) {
    
    
        this.data = data;
    }

    public int getTotal() {
    
    
        return total;
    }

    public void setTotal(int total) {
    
    
        this.total = total;
    }

    public Object getRows() {
    
    
        return rows;
    }

    public void setRows(Object rows) {
    
    
        this.rows = rows;
    }
    @Override
    public String toString() {
    
    
        return "Result{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                ", serverID='" + serverID + '\'' +
                ", data=" + data +
                ", total=" + total +
                ", rows=" + rows +
                '}';
    }
}

ResultEnum.java : Devuelve la clase de enumeración de estado de front-end

package com.crwl.enums;
/**
 * 返回状态
 */
public enum ResultEnum {
    
    
    /**
     * 200 OK     //客户端请求成功 
     * 400 Bad Request  //客户端请求有语法错误,不能被服务器所理解 
     * 401 Unauthorized //请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用
     * 403 Forbidden  //服务器收到请求,但是拒绝提供服务 
     * 404 Not Found  //请求资源不存在,eg:输入了错误的 URL 
     * 500 Internal Server Error //服务器发生不可预期的错误 
     * 503 Server Unavailable  //服务器当前不能处理客户端的请求,一段时间后可能恢复正常 
     */
    SUCCESS(200, "操作成功"),ERROR(500,"操作失败"), FAILURE(404, "请求的网页不存在"),INVALID(503,"服务不可用"),LOGINOVERTIME(1000,"登录超时");
    private ResultEnum(Integer code, String data) {
    
    
        this.code = code;
        this.data = data;
    }
    private Integer code;
    private String data;
    public Integer getCode() {
    
    
        return code;
    }
    public void setCode(Integer code) {
    
    
        this.code = code;
    }
    public String getData() {
    
    
        return data;
    }
    public void setData(String data) {
    
    
        this.data = data;
    }
}

Clase de herramienta Tool.java (no utilizada), RecordModelGenerator.java genera automáticamente la clase de archivo de entidad Jfinal, para ahorrar espacio, no se publicará aquí

4.6 Código de front-end

inserte la descripción de la imagen aquí
El front-end se realiza utilizando la forma tradicional de introducir archivos de biblioteca js en archivos html. La tecnología utilizada es jquery, iview. Los archivos front-end incluyen report.html y report.js, y los otros son archivos de biblioteca de clases.
informe.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta http-equiv="content-type" content="text/html; charset=UTF-8">

	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>报表管理</title>
	<!-- CSS -->
	<link rel="stylesheet" type = "text/css" href="../static/lib/iview/css/iview.css?v=1" />
	<script src="../static/js/jquery-1.8.2.min.js"></script>
	<script src="../static/lib/iview/vue.min.js"></script>
	<script src="../static/lib/iview/iview.min.js"></script>
	<script src="../static/js/common.js"></script>
	<script src="./js/report.js"></script>
	<style>
		#searchForm .ivu-form-item{
      
      
			margin-bottom:0px;
		}
		.clearfix{
      
      clear:both;}
		#searchForm .ivu-col{
      
      padding:10px 0;}
		.valCss{
      
      color:#515a6e!important;}
		.ivu-table-body{
      
      overflow-y:auto;overflow-x:hidden;}
		.ivu-input[disabled], fieldset[disabled]{
      
      
			color:#515a6e;
		}
		.ivu-form-item-content .ivu-form-item-error-tip{
      
      
			top:80%;
		}
		#reportDesignerIframe,#reportPreviewIframe{
      
      border:0;}
		#reportDesingerWin .ivu-modal-footer,#reportPreviewWin .ivu-modal-footer{
      
      display:none;}
		#reportDesingerWin .ivu-modal-body,#reportPreviewWin .ivu-modal-body{
      
      bottom:0}
	</style>
</head>
<body  scroll="no" style="overflow-y:hidden;scrollbar-width: none;">
<Layout id="app" style="overflow-y:hidden;">
	<div style="height:54px;">
		<i-row id="searchForm">
			<i-form :label-width="120">
				<i-col span="4">
					<form-item label="报表名称" prop="rptName">
						<i-input :size="styleSize" v-model="searchForm.rptName"></i-input>
					</form-item>
				</i-col>
				<i-col span="3">
					<i-Button :size="styleSize" type="primary" icon="ios-search" style="margin-left:15px;" @click="searchFunc">查询</i-Button>
				</i-col>
			</i-form>
			<div class="clearfix"></div>
		</i-row>
	</div>
	<i-row style="text-align:left;padding:5px;background:#fff;">
		<i-Button :size="styleSize" type="primary" icon="ios-add" @click="openEdit(1)">新增</i-Button>
		<i-Button :size="styleSize" type="primary" icon="ios-create" @click="openEdit(2)">修改</i-Button>
		<i-Button :size="styleSize" type="primary" icon="ios-remove" @click="deleteFunc()">删除</i-Button>
	</i-row>
	<Content>
		<i-Table :size="styleSize" row-key="id"  border :columns="columns" :data="tableDataList" ref="table" @on-row-click="selectRow" :height="tableHeight" :loading="loading" highlight-row style="overflow-y:auto;"></i-Table>
		<Page :total="dataCount" :page-size="pageSize" :page-size-opts="pageOptions"  show-sizer class="paging" @on-change="changepage" @on-page-size-change="pagesize"></Page>
	</Content>
	<Modal v-model="editModal"
		   :title="editFlag=='add'?'新增':'修改'"
		   width="800px"
	>
		<i-form ref="editValidate" :model="formData" :rules="editRuleValidate" :label-width="120" style="padding:5px 50px;">
			<i-col span="12">
				<form-item label="报表编码" prop="rptCode">
					<i-input :size="styleSize" v-model="formData.rptCode"  ></i-input>
				</form-item>
			</i-col>
			<i-col span="12">
				<form-item label="报表名称" prop="rptName">
					<i-input :size="styleSize" v-model="formData.rptName"  ></i-input>
				</form-item>
			</i-col>
			<i-col span="12">
				<form-item label="排序号" prop="sort">
					<i-input :size="styleSize" type="number" v-model="formData.sort"  ></i-input>
				</form-item>
			</i-col>
			<i-col span="12">
				<form-item label="状态" prop="status">
					<i-switch :size="styleSize" v-model="formData.status" true-value="1" false-value="0" :width="100" size="large">
						<span slot="open">启用</span>
						<span slot="close">禁用</span>
					</i-switch>
				</form-item>
			</i-col>
			<i-col span="24">
				<form-item label="备注" prop="remark">
					<i-input :size="styleSize"  type="textarea":rows="2" v-model="formData.remark" placeholder="请输入备注信息" style="width:100%"></i-input>
				</form-item>
			</i-col>
		</i-form>
		<div class="clearfix"></div>
		<div slot="footer">
			<i-Button :size="styleSize" type="primary" @click="submitFunc">保存</i-Button>
			<i-Button :size="styleSize" type="warning" @click="cancelFunc">取消</i-Button>
		</div>
	</Modal>

	<Modal id="reportDesingerWin" v-model="reportDesignerModal" title="报表设计" fullscreen="true">
		<iframe id="reportDesignerIframe" style="width:100%;height:100%;"></iframe>
	</Modal>
	<Modal id="reportPreviewWin" v-model="reportPreviewModal" title="报表预览"  fullscreen="true">
		<iframe id="reportPreviewIframe" style="width:100%;height:100%;"></iframe>
	</Modal>
</Layout>
</body>
</html>

informe.js

$(function() {
    
    
    var height = $(window).height()-160;
    var vue = new Vue({
    
    
        el: '#app',
        data: {
    
    
            styleSize:constants.styleSize,
            editModal:false,
            editFlag:'add',
            tableHeight:height,
            loading:true,
            reportDesignerModal:false,
            reportPreviewModal:false,
            ureportPre:'fileToDb:',
            ureportSuffix:'.ureport.xml',
            columns :[
                {
    
    type:'selection',key: '',width:'60'},
                {
    
    title: '报表代码',width:'100',key: 'rptCode'},
                {
    
    title: '报表名称',width:'200',key: 'rptName'},
                //{title: '报表文件名',width:'200',key: 'ureportName'},
                {
    
    title: '预览地址',width:'280',key: 'rptUrl'},
                {
    
    title: '备注',width:'220',key: 'remark'},
                {
    
    title: '排序号',width:'80',key: 'sort'},
                {
    
    title: '状态',width:'80',key: 'status',render(h,column){
    
    
                    if(column.row.status==0){
    
    
                        return h('div', {
    
    
                            style: {
    
    
                                color: 'red'
                            },
                        }, '禁用');
                    }else {
    
    
                        return h('div',{
    
    style:{
    
    color:'green'}},'启用');
                    }
                }},
                {
    
    title: '创建日期',width:'160',key: 'createDate',render(h,column){
    
    
                    if(column.row.createDate != null && column.row.createDate != ""){
    
    
                        return commonFunc.formatDate(column.row.createDate,'date','date');
                    }
                }},
                {
    
    title: '操作',width:'200',render(h,column) {
    
    
                    var designBtn = h('Button',
                    {
    
    
                        props: {
    
    
                            type: 'primary',
                            size: 'small'
                        },
                        style: {
    
    
                            marginRight: '5px'
                        },
                        on: {
    
    
                            click: () => {
    
    
                                vue.openDesigner(column.row);
                            }
                        }
                    }, '报表设计');
                    var previewBtn = h('Button',
                    {
    
    
                        props: {
    
    
                            type: 'info',
                            size: 'small'
                        },
                        style: {
    
    
                            marginRight: '5px'
                        },
                        on: {
    
    
                            click: () => {
    
    
                                vue.openPreview(column.row);
                            }
                        }
                    }, '预览');
                    return h('div',[designBtn,previewBtn]);
                }

                }
            ],
            searchForm:{
    
    
                rptName:'',
                rptType:''
            },
            formData: {
    
    
                rptCode:'',
                rptName:'',
                //rptType:1,
                rptUrl:'',
                sort:1,
                status:'1',
                remark:''
            },
            editValidate: {
    
    

            },
            editRuleValidate: {
    
    
                rptCode:{
    
    required:true,message:'请输入报表编码',trigger: 'blur'},
                rptName:{
    
    required:true,message:'请输入报表名称',trigger: 'blur'},
                //rptUrl:{required:true,message:'请输入报表地址',trigger: 'blur'},
                //ureportName:{required:true,message:'请输入报表文件名称',trigger: 'blur'},
                sort:{
    
    required:true,message:'请输入排序号',trigger: 'blur'}
            },
            tableDataList:[],
            dataCount:0,
            // 每页显示多少条
            pageSize:20,
            // 当前页码
            currentPage:1,
            pageOptions:[20,40,60,80,100]
        },
        created:function(){
    
    
            this.initPage();
            var _this = this;
        },
        mounted :function(){
    
    
            //this.tableHeight = window.innerHeight - this.$refs.table.$el.offsetTop - 160
            var _this =this;
            window.onresize = () => {
    
    
                return (() => {
    
    
                    var height = $(window).height()-160;
                    _this.tableHeight = height;
                })()
            }
            //关闭弹窗
            $(".ivu-icon-ios-close").on("click",function(){
    
    
                _this.queryFunc();
            });
        },
        methods: {
    
    
            queryFunc(params){
    
    
                var _this = this ;
                _this.loading = true;
                var searchParam = this.searchForm;
                searchParam.currentPage = this.currentPage;
                searchParam.pageSize = this.pageSize;
                if(null != params){
    
    
                    for(var i in params){
    
    
                        searchParam[i] = params[i];
                    }
                }
                commonFunc.submit("/report/getTableList","post",searchParam,function(data){
    
    
                    _this.tableDataList = data.rows;
                    _this.dataCount = data.total;
                    _this.loading = false;
                },function(){
    
    });
            },
            initPage(){
    
    
                this.currentPage = 1;
                this.queryFunc();
            },
            changepage(index){
    
    
                this.pageFunc(index);
            },
            pagesize(index){
    
    
                this.pageFunc(index);
            },
            pageFunc(index){
    
    
                this.currentPage = index;
                this.queryFunc();
            },
            searchFunc(){
    
    
                this.currentPage = 1;
                this.queryFunc();
            },
            selectRow(data, index) {
    
    
                this.$refs.table.toggleSelect(index);
            },
            openEdit(flag){
    
    
                var _this = this;
                if(flag=="1"){
    
    
                    this.formData= {
    
    
                        rptCode:'',
                        rptName:'',
                        //ureportName:'',
                        sort:0,
                        status:'1',
                        remark:''
                    };
                    this.editFlag="add";
                    if(null != this.$refs.editValidate) {
    
    
                        this.$refs.editValidate.resetFields();
                    }
                }else{
    
    
                    var selRecList = this.$refs.table.getSelection();
                    if(selRecList.length==0 || selRecList.length>1){
    
    
                        this.$Message.error('请选择一条报表记录');
                        return;
                    }
                    if(null != this.$refs.editValidate) {
    
    
                        this.$refs.editValidate.resetFields();
                    }
                    var rec = selRecList[0];
                    this.formData=commonFunc.deepClone(rec);
                    this.formData.sort = rec.sort+'';
                    //this.formData.ureportName = this.formData.ureportName.replace(this.ureportPre,"");
                    //this.formData.ureportName = this.formData.ureportName.replace(this.ureportSuffix,"");
                    this.editFlag="update";

                }
                this.editModal = true;
            },
            submitFunc(){
    
    
                var _this = this;
                this.$refs['editValidate'].validate((valid) => {
    
    
                    if(valid) {
    
    
                        var submitUrl = "/report/save";
                        var param = commonFunc.deepClone(_this.formData);
                        //param.ureportName = _this.ureportPre+param.ureportName+_this.ureportSuffix;
                        commonFunc.submit(submitUrl,"post",param,function(data){
    
    
                            _this.$Message.success(data.msg);
                            _this.editModal = false;
                            _this.searchFunc();
                        },function(data){
    
    
                            _this.$Message.error(data.msg);
                        },'obj');
                    }
                });
            },
            deleteFunc(){
    
    
                var _this = this;
                var selRecList = this.$refs.table.getSelection();
                if(selRecList.length==0 ){
    
    
                    this.$Message.error('请选择报表记录');
                    return;
                }
                _this.$Modal.confirm({
    
    
                    title: '你确定删除选中的报表记录吗?',
                    okText: '确定',
                    cancelText: '取消',
                    onOk: function () {
    
    
                        commonFunc.submit("/report/delete","post",selRecList,function(data){
    
    
                            _this.$Message.success(data.msg);
                            _this.searchFunc();
                        },function(data){
    
    
                            _this.$Message.error(data.msg);
                        },'obj');
                    }
                });
            },
            cancelFunc(){
    
    
                this.editModal = false;
            },
            changeReportType(){
    
    

            },
            openDesigner(row){
    
    
                var src = "";
                if(null != row.ureportName && '' != row.ureportName){
    
    
                    src = "/pro/ureport/designer?_u="+row.ureportName+"&_rId="+row.id;
                }else{
    
    
                    src = "/pro/ureport/designer?_rId="+row.id;
                }
                var parent = $("#reportDesignerIframe").parent();
                var iframeHtml = '<iframe id="reportDesignerIframe" src="'+ src +'" style="width:100%;height:100%;"></iframe>';
                parent.html(iframeHtml);
                this.reportDesignerModal = true;
            },
            openPreview(row){
    
    
                var src = null;
                if(null != row.rptUrl && "" != row.rptUrl){
    
    
                    src = "/pro/"+row.rptUrl+"&reportId="+row.id;
                }else{
    
    
                    this.$Message.error("请先设计报表");
                    return;
                }
                var parent = $("#reportPreviewIframe").parent();
                var iframeHtml = '<iframe id="reportPreviewIframe" src="'+ src +'" style="width:100%;height:100%;"></iframe>';
                parent.html(iframeHtml);
                this.reportPreviewModal=true;
            }
        }
    });
});

5. El funcionamiento del programa

Haga clic con el botón derecho en el archivo de inicio (UreportApplication.java) y haga clic en el menú Ejecutar UreportApplication.java en el menú emergente para iniciar el sistema.
inserte la descripción de la imagen aquíDespués de que el inicio sea exitoso, abra el navegador, ingrese http://localhost:9090/pro/views/report.html para ingresar a la página de administración de informes, haga clic en el botón [Agregar], aparecerá un nuevo formulario de informe, complete
inserte la descripción de la imagen aquíel información básica del formulario, haga clic en el botón [Guardar] para enviar el nuevo registro del informe.
inserte la descripción de la imagen aquíSeleccione el registro de informe recién agregado en la lista de informes y haga clic en el botón [Diseño de informe] para ingresar al diseñador de informes. En
inserte la descripción de la imagen aquíinserte la descripción de la imagen aquí
este punto, puede usar el diseñador de informes para diseñar informes de acuerdo con sus necesidades comerciales. Una vez completado el diseño, puede hacer clic en el botón del icono de vista previa para obtener una vista previa del informe.

Si desea aprender a diseñar informes, puede ingresar aquí para aprender.Este documento de aprendizaje puede ayudar a los usuarios a diseñar más informes que satisfagan sus necesidades comerciales.

En este punto, el uso compartido del informe UReport2 integrado de Springboot ha terminado.

Si necesita el código fuente para aprender, haga clic [aquí]

Supongo que te gusta

Origin blog.csdn.net/teamo_m/article/details/126423770
Recomendado
Clasificación