0


实现Springboot整合UReport2

1、什么是UReport2?

UReport2是一款高性能的架构在Spring之上纯Java报表引擎,通过迭代单元格可以实现任意复杂的中国式报表。该报表由上海锐道信息技术有限公司开发的一款基于Apache-2.0协议开源的中式报表引擎(点击进入gitee源码页面)。当前报表引擎不知是什么原因没有被作者继续维护,但是前期文档还是相对比较详细(点击进入文档页面)。

2、为啥要整合UReport2?

笔者也是处于对报表引擎的实现原理感兴趣,所以download了源码并对部分细节进行调整和优化。建议对报表引擎感兴趣的同学可以下载源码进行研究的个性化调整优化。同时使用springboot+mysql+jfinal+iview+jquery实现了一个简单的报表demo,在此做一个简单的学习记录,并同各位同学分享,希望能同各位一起不断进步和提升个人技术能力。

3、实现结果

先上部分截图展示一下实现结果

3.1、报表列表

在这里插入图片描述

3.2、报表设计器

在这里插入图片描述

3.3、学生平均分报表预览

在这里插入图片描述

3.4、综合成绩报表预览

在这里插入图片描述

3.5、学生成绩单报表预览

在这里插入图片描述

4、实现过程

先放一张系统文件结构图
在这里插入图片描述

4.1、创建一个springboot项目

将项目命名为ureport,并在pom.xml文件中添加需要的maven依赖

<?xml version="1.0" encoding="UTF-8"?><projectxmlns="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>

此处ureport2的jar包依赖为笔者重新修改并编译源码后生成,如果直接采用UReport2官方下载的jar包,针对本demo有可能无法运行,如由用户需要当前jar包可联系笔者。

4.2、添加yml配置信息

applicaiton.yaml

server:port:9090servlet:context-path: /pro
spring:http:encoding:force:trueenabled:truecharset: UTF-8datasource: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=trueusername: root
    password:type: com.alibaba.druid.pool.DruidDataSource
  resources:static-locations: classpath:/,classpath:/static/

4.3、添加引用UReport2的Spring配置文件context.xml

笔者是放在resources/config目录下面

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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"><importresource="classpath:ureport-console-context.xml"/><beanid="propertyConfigurer"parent="ureport.props"><propertyname="locations"><list><value>classpath:config/config.properties</value></list></property></bean><beanid="ureport.fielToDataBaseProvider"class="com.crwl.provider.FileToDatabaserProvider"><propertyname="fileStoreDir"value="${ureport.fileToDbStoreDir}"></property><propertyname="disabled"value="${ureport.disableFileDbProvider}"></property></bean></beans>

4.4、添加property文件

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

UReport2报表引擎默认采用文件系统,其中ureport.fileStoreDir是配置生成的报表文件的物理路径,ureport.disableFileProvider是定义是否禁用用当前报表的文件系统,true为禁用,false为启用。笔者当前的思路是将文件系统同mysql数据库结合起来进行管理,所以配置为禁用。

4.4.2、ureport.fileToDbStoreDir

ureport.fileToDbStoreDir为笔者扩展出来的mysql+文件系统结合的一种方式,此参数同样是配置路径,ureport.disableFileDbProvider配置是否禁用

4.4.3、ureport.contextPath

ureport.contextPath参数为笔者添加的参数,此参数可帮助用户实现业务后台系统同前端分离会出现的报表默认资源路径地址不匹配的情况。当前demo未采用前后端分离,所以此参数可以配置,也可以不配置,不配置默认为application.yaml文件对应的context-path。

4.5、java源码

4.5.1、DataSourceConfig.java

packagecom.crwl.config;importcom.alibaba.druid.pool.DruidDataSource;importcom.crwl.model._MappingKit;importcom.jfinal.plugin.activerecord.ActiveRecordPlugin;importcom.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory;importcom.jfinal.plugin.activerecord.dialect.MysqlDialect;importorg.springframework.boot.context.properties.ConfigurationProperties;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.Primary;importorg.springframework.jdbc.datasource.DataSourceTransactionManager;importorg.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;importjavax.sql.DataSource;/**
 * @author teamo
 * @Package com.crwl.config
 * @Description:
 * @date 2022-8-17
 */@ConfigurationpublicclassDataSourceConfig{@Primary@Bean@ConfigurationProperties(prefix ="spring.datasource")publicDataSourcedruidDataSource(){returnnewDruidDataSource();}/**
     * 设置数据源代理
     */@BeanpublicTransactionAwareDataSourceProxytransactionAwareDataSourceProxy(){TransactionAwareDataSourceProxy transactionAwareDataSourceProxy =newTransactionAwareDataSourceProxy();
        transactionAwareDataSourceProxy.setTargetDataSource(druidDataSource());return transactionAwareDataSourceProxy;}/**
     * 设置ActiveRecord
     */@BeanpublicActiveRecordPluginactiveRecordPlugin(){ActiveRecordPlugin arp =newActiveRecordPlugin(transactionAwareDataSourceProxy());
        arp.setDialect(newMysqlDialect());
        arp.setContainerFactory(newCaseInsensitiveContainerFactory(true));//忽略大小写
        arp.setShowSql(true);
        arp.getEngine().setToClassPathSourceFactory();//arp.addSqlTemplate("sql/all.sql");
        _MappingKit.mapping(arp);
        arp.start();System.out.println("调用Jfinal ActiveRecordPlugin 成功");return arp;}}

此类主要用于根据配置文件对数据库链接以及Jfinal的进行初始化工作。
如用户对JFinal不太了解,可以自行百度学习。JFinal 是基于Java 语言的极速 web 开发框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。当前demo主要使用Jfinal的数据库部分的功能。

4.5.2、model类 Report.java, BaseReport.java,_MappingKit.java

model为jfinal的实体对象类,主要用于同数据表进行orm映射关系。

packagecom.crwl.model;importcom.crwl.model.base.BaseReport;/**
 * Generated by JFinal.
 */@SuppressWarnings("serial")publicclassReportextendsBaseReport<Report>{publicstaticfinalReport dao =newReport().dao();}

BaseReport.java

packagecom.crwl.model.base;importcom.jfinal.plugin.activerecord.IBean;importcom.jfinal.plugin.activerecord.Model;importjava.util.Date;/**
 * Generated by JFinal, do not modify this file.
 */@SuppressWarnings({"serial","unchecked"})publicabstractclassBaseReport<MextendsBaseReport<M>>extendsModel<M>implementsIBean{publicMsetId(Integer id){set("id", id);return(M)this;}publicIntegergetId(){returngetInt("id");}publicMsetRptCode(String rptCode){set("rpt_code", rptCode);return(M)this;}publicStringgetRptCode(){returngetStr("rpt_code");}publicMsetRptName(String rptName){set("rpt_name", rptName);return(M)this;}publicStringgetRptName(){returngetStr("rpt_name");}publicMsetRptType(Integer rptType){set("rpt_type", rptType);return(M)this;}publicIntegergetRptType(){returngetInt("rpt_type");}publicMsetUreportName(String ureportName){set("ureport_name", ureportName);return(M)this;}publicStringgetUreportName(){returngetStr("ureport_name");}publicMsetRptUrl(String rptUrl){set("rpt_url", rptUrl);return(M)this;}publicStringgetRptUrl(){returngetStr("rpt_url");}publicMsetRemark(String remark){set("remark", remark);return(M)this;}publicStringgetRemark(){returngetStr("remark");}publicMsetSort(Integer sort){set("sort", sort);return(M)this;}publicIntegergetSort(){returngetInt("sort");}publicMsetStatus(Integer status){set("status", status);return(M)this;}publicIntegergetStatus(){returngetInt("status");}publicMsetCreateUser(String createUser){set("create_user", createUser);return(M)this;}publicStringgetCreateUser(){returngetStr("create_user");}publicMsetCreateDate(Date createDate){set("create_date", createDate);return(M)this;}publicDategetCreateDate(){returngetDate("create_date");}publicMsetUpdateUser(String updateUser){set("update_user", updateUser);return(M)this;}publicStringgetUpdateUser(){returngetStr("update_user");}publicMsetUpdateDate(Date updateDate){set("update_date", updateDate);return(M)this;}publicDategetUpdateDate(){returngetDate("update_date");}}

_MappingKit.java

packagecom.crwl.model;importcom.jfinal.plugin.activerecord.ActiveRecordPlugin;publicclass _MappingKit {publicstaticvoidmapping(ActiveRecordPlugin arp){
        arp.addMapping("ur_report","id",Report.class);}}

4.5.3、Controller类

ReportController.java,报表Controller类

packagecom.crwl;importcom.bstek.ureport.console.UReportServlet;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.web.servlet.ServletRegistrationBean;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.ImportResource;importorg.springframework.transaction.annotation.EnableTransactionManagement;/**
 * 入口类
 */@SpringBootApplication()@EnableTransactionManagement@ImportResource("classpath:config/context.xml")@ComponentScan(basePackages ={"com.crwl.*"})publicclassUreportApplication{publicstaticvoidmain(String[] args){SpringApplication.run(UreportApplication.class, args);}//ureport报表@BeanpublicServletRegistrationBeanbuildUReprtServlet(){returnnewServletRegistrationBean(newUReportServlet(),"/ureport/*");}}

4.5.4、Service类 ReportService.java, ReportServiceImpl.java

ReportService.java

packagecom.crwl.service;importcom.crwl.model.Report;importcom.jfinal.plugin.activerecord.Page;publicinterfaceReportService{/***
     * 获取表格数据
     * @param currentPage
     * @param pageSize
     * @param rptName
     * @param rptType
     * @return
     */Page<Report>getPageList(Integer currentPage,Integer pageSize,String rptName,String rptType);}

ReportServiceImpl.java

packagecom.crwl.service.impl;importcom.crwl.model.Report;importcom.crwl.service.ReportService;importcom.jfinal.plugin.activerecord.Page;importorg.apache.commons.lang.StringUtils;importorg.springframework.stereotype.Service;@ServicepublicclassReportServiceImplimplementsReportService{privatefinalString table ="ur_report";@OverridepublicPage<Report>getPageList(Integer currentPage,Integer pageSize,String rptName,String rptType){StringBuilder sql =newStringBuilder();
        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、Povider类

Provider类是实现UReport开放出来的供业务系统实现的接口类,用户可以同时实现不同的Provider类从代码层面去实现用户的业务需求。
DsProvider.java:通过事项BuildingDatasource接口,用户可以为报表设计界面提供接口级别的数据源。
实现当前接口后,在报表设计界面可直接使用当前数据库链接。
在这里插入图片描述在这里插入图片描述

packagecom.crwl.provider;importcom.bstek.ureport.definition.datasource.BuildinDatasource;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importjavax.sql.DataSource;importjava.sql.Connection;importjava.sql.SQLException;//提供ureport 内置数据源连接@Component("dsScoreSys")publicclassDsProviderimplementsBuildinDatasource{@AutowiredprivateDataSource dataSource;@OverridepublicStringname(){return"scoreSys";}@OverridepublicConnectiongetConnection(){try{return dataSource.getConnection();}catch(SQLException e){
            e.printStackTrace();returnnull;}}}

FileToDatabaserProvider.java: 通过实现ReportProvider接口,用户可以增加符合用户自身需求的报表储存方式(UReport2自身已经实现了纯文件系统储存报表的存储方式)。笔者通过实现当前接口实现了使用数据库存储报表的基本信息,使用文件系统存储报表文件,数据库记录报表的寻址地址。即可以使用mysql数据表管理报表文件。

packagecom.crwl.provider;importcom.bstek.ureport.exception.ReportException;importcom.bstek.ureport.provider.report.ReportFile;importcom.bstek.ureport.provider.report.ReportProvider;importcom.crwl.model.Report;importorg.apache.commons.io.IOUtils;importorg.apache.commons.lang.StringUtils;importjava.io.*;importjava.util.*;publicclassFileToDatabaserProviderimplementsReportProvider{privateString prefix="fileToDb:";privateString fileStoreDir;privateString disabled;@OverridepublicInputStreamloadReport(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{returnnewFileInputStream(fullPath);}catch(FileNotFoundException e){thrownewReportException(e);}}else{thrownewReportException("报表文件不存在");}}else{thrownewReportException("报表文件不存在");}}@OverridepublicvoiddeleteReport(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=newFile(fullPath);if(f.exists()){
                f.delete();}
            report.delete();}}@OverridepublicList<ReportFile>getReportFiles(){List<Report> reportList =Report.dao.find("select * from ur_report t where t.rpt_type=2 ");File file=newFile(fileStoreDir);List<ReportFile> list=newArrayList<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(newReportFile(report.getId(),f.getName(),calendar.getTime()));}}Collections.sort(list,newComparator<ReportFile>(){@Overridepublicintcompare(ReportFile f1,ReportFile f2){return f2.getUpdateDate().compareTo(f1.getUpdateDate());}});return list;}@OverridepublicvoidsaveReport(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 =newFileOutputStream(newFile(fullPath));IOUtils.write(content, outStream,"utf-8");}catch(Exception ex){thrownewReportException(ex);}finally{if(outStream !=null){try{
                            outStream.close();}catch(IOException e){
                            e.printStackTrace();}}}
                report.setUpdateDate(newDate());
                report.update();}else{thrownewReportException("报表文件不存在");}}else{thrownewReportException("报表文件不存在");}}@OverridepublicStringgetName(){return"数据库文件系统";}@Overridepublicbooleandisabled(){returnfalse;}@OverridepublicStringgetPrefix(){return prefix;}publicvoidsetFileStoreDir(String fileStoreDir){this.fileStoreDir = fileStoreDir;}publicvoidsetDisabled(String disabled){this.disabled = disabled;}}

loadReport方法:通过给定的参数从数据库中找到报表文件,根据寻址地址生成一个InputStream对象,报表设计器根据返回的InputStream对象渲染出正在设计中的报表文件

deleteReport方法:提供过给定的参数删除报表文件,此方法的操作是先删除对应数据库中的记录,在删除对应的物理报表文件

getReportFiles方法:加载当前所有的数据报表记录。

saveReport方法:通过给定的参数找到报表记录,更新报表预览地址并保存物理报表文件。

UreportContextProvider.java是笔者扩展的更改报表contextPath参数的接口,它的作用同config.properties文件中的ureport.contextPath参数一致,此处未使用,故不做介绍了。

4.5.5、springboot启动类

UreportApplication.java
@ImportResource(“classpath:config/context.xml”)不能漏了,它是引入ureport2的spring配置文件。
buildUReprtServlet方法是将UReport注册为一个Servlet,是使用UReport的入口文件,不能缺少。

packagecom.crwl;importcom.bstek.ureport.console.UReportServlet;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.web.servlet.ServletRegistrationBean;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.ImportResource;importorg.springframework.transaction.annotation.EnableTransactionManagement;/**
 * 入口类
 */@SpringBootApplication()@EnableTransactionManagement@ImportResource("classpath:config/context.xml")@ComponentScan(basePackages ={"com.crwl.*"})publicclassUreportApplication{publicstaticvoidmain(String[] args){SpringApplication.run(UreportApplication.class, args);}//ureport报表@BeanpublicServletRegistrationBeanbuildUReprtServlet(){returnnewServletRegistrationBean(newUReportServlet(),"/ureport/*");}}

4.5.5、其它类

Result.java: 返回前端Dto类

packagecom.crwl.dto;importcom.crwl.enums.ResultEnum;importjava.io.Serializable;/**
 * 返回的对象(统一返回)
 *
 * @author SmallStrong
 */publicclassResultimplementsSerializable{/**
     *
     */privatestaticfinallong serialVersionUID =3337439376898084639L;/**
     * 处理状态
     */privateInteger code;/**
     * 处理信息
     */privateString msg;privateString serverID;/**
     * 返回值
     */privateObject data;privateint total;privateObject rows;/**
     * 成功,传入data(使用最多)
     *
     * @param data
     * @return
     */publicstaticResultsuccess(Object data){returnResult.success(data,"请求成功!");}/**
     * 成功,传入data(使用最多)
     * @param msg
     * @return
     */publicstaticResultsuccess(String msg){Result result =newResult();
        result.setCode(ResultEnum.SUCCESS.getCode());
        result.setMsg(msg);return result;}/**
     * 成功,传入rows和total
     * @param rows
     * @param total
     * @return
     */publicstaticResultsuccess(Object rows,int total){Result result =newResult();
        result.setCode(ResultEnum.SUCCESS.getCode());
        result.setMsg("请求成功!");
        result.setRows(rows);
        result.setTotal(total);return result;}/**
     * 成功,传入data 和 msg
     * @param data
     * @param msg
     * @return
     */publicstaticResultsuccess(Object data,String msg){Result result =newResult();
        result.setCode(ResultEnum.SUCCESS.getCode());
        result.setMsg(msg);
        result.setData(data);return result;}/**
     * 失败
     * @return
     */publicstaticResulterror(){returnResult.error("请求失败!");}/**
     * 失败 传入 msg
     * @param msg
     * @return
     */publicstaticResulterror(String msg){returnResult.error(msg,ResultEnum.FAILURE);}publicstaticResulterror(String msg ,ResultEnum resultEnum){Result result =newResult();
        result.setCode(resultEnum.getCode());
        result.setMsg(msg);return result;}publicIntegergetCode(){return code;}publicvoidsetCode(Integer code){this.code = code;if(null!=this.data &&this.data.getClass().getName().equals("com.crwl.commonserver.dto.CurrUser")){this.data =null;}}publicStringgetMsg(){return msg;}publicvoidsetMsg(String msg){this.msg = msg;}publicStringgetServerID(){return serverID;}publicvoidsetServerID(String serverID){this.serverID = serverID;}publicObjectgetData(){return data;}publicvoidsetData(Object data){this.data = data;}publicintgetTotal(){return total;}publicvoidsetTotal(int total){this.total = total;}publicObjectgetRows(){return rows;}publicvoidsetRows(Object rows){this.rows = rows;}@OverridepublicStringtoString(){return"Result{"+"code="+ code +", msg='"+ msg +'\''+", serverID='"+ serverID +'\''+", data="+ data +", total="+ total +", rows="+ rows +'}';}}

ResultEnum.java:返回前端状态枚举类

packagecom.crwl.enums;/**
 * 返回状态
 */publicenumResultEnum{/**
     * 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,"登录超时");privateResultEnum(Integer code,String data){this.code = code;this.data = data;}privateInteger code;privateString data;publicIntegergetCode(){return code;}publicvoidsetCode(Integer code){this.code = code;}publicStringgetData(){return data;}publicvoidsetData(String data){this.data = data;}}

Tool.java工具类(未用到),RecordModelGenerator.java自动生成Jfinal实体文件类,为节省篇幅,此处不贴出来了

4.6、前端代码

在这里插入图片描述
前端使用的是传统的在html文件引入的方式js库文件的方式实现。采用的技术是jquery,iview。前端文件包括一个report.html和report.js,其它都是类库文件。
report.html

<!DOCTYPEhtml><htmllang="en"><head><metahttp-equiv="content-type"content="text/html; charset=UTF-8"><metacharset="utf-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1"><title>报表管理</title><!-- CSS --><linkrel="stylesheet"type="text/css"href="../static/lib/iview/css/iview.css?v=1"/><scriptsrc="../static/js/jquery-1.8.2.min.js"></script><scriptsrc="../static/lib/iview/vue.min.js"></script><scriptsrc="../static/lib/iview/iview.min.js"></script><scriptsrc="../static/js/common.js"></script><scriptsrc="./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><bodyscroll="no"style="overflow-y:hidden;scrollbar-width: none;"><Layoutid="app"style="overflow-y:hidden;"><divstyle="height:54px;"><i-rowid="searchForm"><i-form:label-width="120"><i-colspan="4"><form-itemlabel="报表名称"prop="rptName"><i-input:size="styleSize"v-model="searchForm.rptName"></i-input></form-item></i-col><i-colspan="3"><i-Button:size="styleSize"type="primary"icon="ios-search"style="margin-left:15px;"@click="searchFunc">查询</i-Button></i-col></i-form><divclass="clearfix"></div></i-row></div><i-rowstyle="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-rowstyle="overflow-y:auto;"></i-Table><Page:total="dataCount":page-size="pageSize":page-size-opts="pageOptions"show-sizerclass="paging"@on-change="changepage"@on-page-size-change="pagesize"></Page></Content><Modalv-model="editModal":title="editFlag=='add'?'新增':'修改'"width="800px"><i-formref="editValidate":model="formData":rules="editRuleValidate":label-width="120"style="padding:5px 50px;"><i-colspan="12"><form-itemlabel="报表编码"prop="rptCode"><i-input:size="styleSize"v-model="formData.rptCode"></i-input></form-item></i-col><i-colspan="12"><form-itemlabel="报表名称"prop="rptName"><i-input:size="styleSize"v-model="formData.rptName"></i-input></form-item></i-col><i-colspan="12"><form-itemlabel="排序号"prop="sort"><i-input:size="styleSize"type="number"v-model="formData.sort"></i-input></form-item></i-col><i-colspan="12"><form-itemlabel="状态"prop="status"><i-switch:size="styleSize"v-model="formData.status"true-value="1"false-value="0":width="100"size="large"><spanslot="open">启用</span><spanslot="close">禁用</span></i-switch></form-item></i-col><i-colspan="24"><form-itemlabel="备注"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><divclass="clearfix"></div><divslot="footer"><i-Button:size="styleSize"type="primary"@click="submitFunc">保存</i-Button><i-Button:size="styleSize"type="warning"@click="cancelFunc">取消</i-Button></div></Modal><Modalid="reportDesingerWin"v-model="reportDesignerModal"title="报表设计"fullscreen="true"><iframeid="reportDesignerIframe"style="width:100%;height:100%;"></iframe></Modal><Modalid="reportPreviewWin"v-model="reportPreviewModal"title="报表预览"fullscreen="true"><iframeid="reportPreviewIframe"style="width:100%;height:100%;"></iframe></Modal></Layout></body></html>

report.js

$(function(){var height =$(window).height()-160;var vue =newVue({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){returnh('div',{style:{color:'red'},},'禁用');}else{returnh('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);}}},'预览');returnh('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 - 160var _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、程序的运行

右键点击启动文件(UreportApplication.java),在弹出的菜单中点击Run UreportApplication.java菜单启动系统。
在这里插入图片描述启动成功后,打开浏览器,输入http://localhost:9090/pro/views/report.html即可进入报表管理页面
在这里插入图片描述点击【新增】按钮,弹出新增报表表单,完善表单基本信息,点击【保存】按钮提交新增报表记录。
在这里插入图片描述在报表列表中选中新增的报表记录,点击【报表设计】按钮,进入报表设计器
在这里插入图片描述在这里插入图片描述
到此就可以使用报表设计器设计器根据自己的业务需要进行报表设计了。设计完成后,可以点击预览图标按钮进行报表预览。

如需学习如何设计报表,可以进入这里进行学习,该学习文档可帮助用户设计出更多符合用户业务需求的报表。

到此,Springboot整合UReport2报表分享结束。


本文转载自: https://blog.csdn.net/teamo_m/article/details/126423770
版权归原作者 teamo_m 所有, 如有侵权,请联系我们删除。

“实现Springboot整合UReport2”的评论:

还没有评论