打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
SpringBoot+AngularJS+Jaspersoft Studio实现多张报表打印控制

报表在JavaWeb中是个非常常用的技术,本文介绍使用SpringBoot+AngularJS+Jaspersoft Studio对报表打印进行实现
一.使用Jaspersoft Studio进行报表的绘制后,存放在src/main/resources/reports文件夹下。
二.实现多张报表生成后台代码详解
此方法应用了JasperReport和JRAbstractExporter包对报表进行无脑化编译。

     @RestController     @RequestMapping(LevyDetailController.BASE_URL)      public class LevyDetailController {    public static Logger LOGGER = LoggerFactory.getLogger(LevyDetailController.class);    /** 根路径 */    public final static String BASE_URL = "/reports/levy";    /** 报表打印服务接口类 */    @Resource    private LevyDetailService levyDetailService;    @SuppressWarnings("unchecked")    @RequestMapping(method = RequestMethod.GET)    public void printReport(@RequestParam("format") String format, @RequestParam("companyId") Long companyId,            @RequestParam(required = false) Long issue, @RequestParam(required = false) Long pageIndex,            HttpServletRequest request, HttpServletResponse response) {        String requestFullUri = request.getRequestURI() + "?" + request.getQueryString();        OrganizationApplyService organizationApplyService = (OrganizationApplyService) SpringContextUtils                .getApplicationContext().getBean("organizationApplyServiceImpl");        OrganizationApply company = organizationApplyService.findByOrgId(companyId);        // 获取报表数据        CompanyLevyListDTO result = levyDetailService.getLevyDetail(company, issue);        // result.setList(null);测试空报表        // 打印控制获取上下文        ApplicationContext ctx = SpringContextUtils.getApplicationContext();        org.springframework.core.io.Resource resource = null;        if (result.getList() == null) {            // 生成空白报表            resource = ctx.getResource("classpath:/reports/rptEmpty.jrxml");        } else {            resource = ctx.getResource("classpath:/reports/rptLevyDetailx.jrxml");        }        InputStream inputStream;        try {            // 译为输入流            inputStream = resource.getInputStream();            // 编译报表            JasperReport jasperReport = JasperCompileManager.compileReport(inputStream);            JRAbstractExporter exporter = new JRPdfExporter();            List<JasperPrint> list = new ArrayList<>();            // 多张报表打印实现            if (result.getList() != null) {                for (CompanyLevyDTO dto : result.getList()) {                    // 获取报表数据map源                    JasperPrint jasperprint = JasperFillManager.fillReport(jasperReport,                            LevyDetaiFactorySolitary.getReportData(format, requestFullUri, dto, issue,                                    company.getName(), company.getCompanyNumber()),                            LevyDetaiFactorySolitary.mapData(dto.getLevyBodyListDTO()));                    list.add(jasperprint);                }            } else {                JasperPrint jasperprint = JasperFillManager.fillReport(jasperReport,                        (Map<String, Object>) DefaultEmptyFactory.getReportData(format, requestFullUri),                        DefaultEmptyFactory.mapData());                list.add(jasperprint);            }            // 设置前台编译格式            ServletOutputStream baos = response.getOutputStream();            exporter.setParameter(JRExporterParameter.JASPER_PRINT_LIST, list);            exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, baos);            exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");            exporter.exportReport();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (JRException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

三.单张报表生成后台代码详解
此方法使用最基本SpringBooot response传入字节数组方式生成报表,代码如下:

 @RestController @RequestMapping(LevyDetailController.BASE_URL) public class LevyDetailController {public static Logger LOGGER = LoggerFactory.getLogger(LevyDetailController.class);/** 根路径 */public final static String BASE_URL = "/reports/levy";/** 报表打印服务接口类 */@Resourceprivate LevyDetailService levyDetailService;@Autowiredprivate PileStamperClient pileStamperClient;@RequestMapping(method = RequestMethod.GET)public void printReport(@RequestParam("format") String format, @RequestParam("companyId") Long companyId,        @RequestParam(required = false) Long issue, @RequestParam(required = false) Long pageIndex,        HttpServletRequest request, HttpServletResponse response) throws JSONException {    String requestFullUri = request.getRequestURI() + "?" + request.getQueryString();    OrganizationApplyService organizationApplyService = (OrganizationApplyService) SpringContextUtils            .getApplicationContext().getBean("organizationApplyServiceImpl");    OrganizationApply company = organizationApplyService.findByOrgId(companyId);    // 获取报表数据    CompanyLevyListDTO result = levyDetailService.getLevyDetail(company, issue);    // result.setList(null);测试空报表    // 打印控制获取上下文    ApplicationContext ctx = SpringContextUtils.getApplicationContext();    org.springframework.core.io.Resource resource = null;    if (result.getList() == null) {        // 生成空白报表        resource = ctx.getResource("classpath:/reports/rptEmpty.jrxml");    } else {        resource = ctx.getResource("classpath:/reports/rptLevyDetailx.jrxml");    }    InputStream inputStream;    try {        byte[] bytesPdf = null;        // 译为输入流        inputStream = resource.getInputStream();        // 编译报表        JasperReport jasperReport = JasperCompileManager.compileReport(inputStream);        // 单张报表打印实现        if (result.getList() != null) {            for (int t = 0; t < result.getList().size(); t++) {                CompanyLevyDTO dto = result.getList().get(t);                bytesPdf = JasperRunManager.runReportToPdf(jasperReport,                        LevyDetaiFactorySolitary.getReportData(format, requestFullUri, dto, issue,                                company.getName(), company.getCompanyNumber()),                        LevyDetaiFactorySolitary.mapData(dto.getLevyBodyListDTO()));            }        } else {            bytesPdf = JasperRunManager.runReportToPdf(jasperReport,                    DefaultEmptyFactory.getReportData(format, requestFullUri), DefaultEmptyFactory.mapData());        }        ByteArrayInputStream stream = new ByteArrayInputStream(bytesPdf);        int length = stream.available();        if (length != -1) {            byte[] buffer3 = new byte[1024];            int readCount = 0;            ServletOutputStream sos = response.getOutputStream();            while ((readCount = stream.read(buffer3)) > 0) {                sos.write(buffer3, 0, readCount);            }        }    } catch (IOException e) {        // TODO Auto-generated catch block        e.printStackTrace();    } catch (JRException e) {        // TODO Auto-generated catch block        e.printStackTrace();    }}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84

五.使用PDFMergerUtility进行PDF字节流合成导出
mvn引入jar包

    <dependency>            <groupId>org.apache.pdfbox</groupId>            <artifactId>pdfbox-app</artifactId>            <version>1.8.13</version>    </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
@RestController@RequestMapping(LevyDetailController.BASE_URL)public class LevyDetailController {    public static Logger LOGGER = LoggerFactory.getLogger(LevyDetailController.class);    /** 根路径 */    public final static String BASE_URL = "/reports/levy";    /** 报表打印服务接口类 */    @Resource    private LevyDetailService levyDetailService;    @RequestMapping(method = RequestMethod.GET)    public void printReport(@RequestParam("format") String format, @RequestParam("companyId") Long companyId,            @RequestParam(required = false) Long issue, @RequestParam(required = false) Long pageIndex,            HttpServletRequest request, HttpServletResponse response) {        String requestFullUri = request.getRequestURI() + "?" + request.getQueryString();        OrganizationApplyService organizationApplyService = (OrganizationApplyService) SpringContextUtils                .getApplicationContext().getBean("organizationApplyServiceImpl");        OrganizationApply company = organizationApplyService.findByOrgId(companyId);        // 获取报表数据        CompanyLevyListDTO result = levyDetailService.getLevyDetail(company, issue);        // result.setList(null);测试空报表        // 打印控制获取上下文        ApplicationContext ctx = SpringContextUtils.getApplicationContext();        org.springframework.core.io.Resource resource = null;        if (result.getList() == null) {            // 生成空白报表            resource = ctx.getResource("classpath:/reports/rptEmpty.jrxml");        } else {            resource = ctx.getResource("classpath:/reports/rptLevyDetailx.jrxml");        }        InputStream inputStream;        try {            byte[] bytesPdf = null;            // 译为输入流            inputStream = resource.getInputStream();            // 编译报表            JasperReport jasperReport = JasperCompileManager.compileReport(inputStream);            // 多张报表打印实现            if (result.getList() != null) {                List<byte[]> list = new ArrayList<byte[]>();                for (CompanyLevyDTO dto : result.getList()) {                    // 获取报表数据map源                    bytesPdf = JasperRunManager.runReportToPdf(jasperReport,                            LevyDetaiFactorySolitary.getReportData(format, requestFullUri, dto, issue,                                    company.getName(), company.getCompanyNumber()),                            LevyDetaiFactorySolitary.mapData(dto.getLevyBodyListDTO()));                    list.add(bytesPdf);                }                if (result.getList().size() > 1) {                    // 多张表单拼接实现                    PDFMergerUtility mergePdf = new PDFMergerUtility();                    for (int i = 0; i < list.size(); i++) {                        byte[] content = list.get(i);                        ByteArrayInputStream in = new ByteArrayInputStream(content);                        mergePdf.addSource(in);                    }                    // 多个pdf流合成处理                    mergePdf.setDestinationStream(new ByteArrayOutputStream());                    try {                        mergePdf.mergeDocuments();                    } catch (COSVisitorException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                    // 获取合成后的OutputStream流                    ByteArrayOutputStream outputStream = (ByteArrayOutputStream) mergePdf.getDestinationStream();                    bytesPdf = outputStream.toByteArray();                }            } else {                bytesPdf = JasperRunManager.runReportToPdf(jasperReport,                        DefaultEmptyFactory.getReportData(format, requestFullUri), DefaultEmptyFactory.mapData());            }            ByteArrayInputStream stream = new ByteArrayInputStream(bytesPdf);            // 返回从输入流中读取的字节数,若无字节 返回0            int length = stream.available();            if (length != -1) {                byte[] buffer3 = new byte[1024];                int readCount = 0;                ServletOutputStream sos = response.getOutputStream();                while ((readCount = stream.read(buffer3)) > 0) {                    // 从buffer3中读取0-readCount的数据                    sos.write(buffer3, 0, readCount);                }            }        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (JRException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104

四.LevyDetaiFactorySolitary实现,代码如下

public class LevyDetaiFactorySolitary {    private LevyDetaiFactorySolitary() {    }    public static final String LEVY_REPORT_NAME = "rptLevyDetailx";    public static final String LEVY_FULL_URI = "request_full_uri";    public static String getReportName() {        return LEVY_REPORT_NAME;    }    /**     * 获取报表数据     *      * @param format     * @param requestFullUri     * @param dto     * @return     */    public static Map<String, Object> getReportData(String format, String requestFullUri, CompanyLevyDTO dto,            Long issue, String name, String companyNumber) {        Map<String, Object> model = new HashMap<String, Object>();        model.put(JasperReportsMultiFormatView.DEFAULT_FORMAT_KEY, format);        model.put(LEVY_FULL_URI, requestFullUri);        model.put("name", "名称:" + name);        ...//这里面放不是循环的参数        return model;    }    /**     * 获取报表DataSource数据     *      * @param format     * @param requestFullUri     * @param dto     * @return     */    public static JRMapCollectionDataSource mapData(List<LevyBodyDTO> list) {        Collection<Map<String, ?>> collection = new ArrayList<Map<String, ?>>();        for (int i = 0; i < list.size(); i++) {            Map<String, Object> map = new HashMap<String, Object>();            LevyBodyDTO dto = list.get(i);            map.put("insuranceCode", dto.getInsuranceCode());    ...//这里面放循环的数据            collection.add(map);        }        return new JRMapCollectionDataSource(collection);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

五.也可以使用直接返回前台ModelAndView的形式进行实现
代码入下:

 ModelAndView module = null;        if (listDimissionDTO.size() == 0) {            // 生成报表            module = new ModelAndView(DefaultEmptyFactory.getReportName(),                    DefaultEmptyFactory.getReportData(format, requestFullUri));        } else {            // 生成报表            module = new ModelAndView(LevyDetaiFactorySolitary .getReportName(),                    LevyDetaiFactorySolitary .getReportData(reportPageIndex, format, requestFullUri, listDimissionDTO, issue,                            company.getName(), company.getCompanyNumber(), reviewedStatus, submitType));        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

五.前端angularJS显示方案
目前市面上多种浏览器对报表的支持程度不一,最优解决方案如下:
ie十以上支持下载,谷歌火狐浏览器可在线预览
html:

<div class="form-group" style="margin-left:90px">        <input class="btn btn-success" type="button" style="width:100px;" value="打印报表"               ng-click="report()"/>      </div>
  • 1
  • 2
  • 3
  • 4

js

$scope.report = function () {        if (window.navigator && window.navigator.msSaveOrOpenBlob) {          $http({            url: $scope.URL + '?format=pdf&companyId=' + $scope.companyId + '&issue=' + $scope.issue,            method: 'GET',            responseType: 'arraybuffer'          }).success(function (response) {            var file = new Blob([response], {type: 'application/pdf'});            var fileURL = URL.createObjectURL(file);            window.navigator.msSaveOrOpenBlob(file);          });        } else {          var reportOption = {};          reportOption.pdfName = $scope.title;          reportOption.method = 'GET';          reportOption.url = $scope.URL + '?format=pdf&companyId=' + $scope.companyId + '&issue=' + $scope.issue;          reportOption.headers = {Accept: '*/*'};          reportHelper.showReport(reportOption);        }      };  **五.从ftp服务器获取方案**   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

@RestController
@RequestMapping(ApplyPrintController.BASE_URL)
public class ApplyPrintController {

/** 根路径 */public final static String BASE_URL = "/reports/applyReport";@RequestMapping(method = RequestMethod.GET)public void printReport(@RequestParam("format") String format,        @RequestParam(value = "companyId", required = true) String companyId,        @RequestParam(value = "issue", required = false) Long issue, @RequestParam("buzzType") String buzzType,        @RequestParam("submitType") String submitType,        @RequestParam(value = "reviewedStatus", required = false) String reviewedStatus,        @RequestParam(required = false) Long pageIndex, HttpServletRequest request, HttpServletResponse response) {    String host = "10.154.227.46";// 设置服务器地址    int port = 21; // 设置服务器端口号    String username = "ftp2012";// 设置服务器访问用户    String password = "dfca@123";// 设置服务器密码    String remoteDir = "/ftpuser"; // 切换报表所在路径    /** 文件路径通配符 */    String regEx = "A20170020062.pdf";    String encoding = System.getProperty("file.encoding"); // 设置编码    FTPClient client = new FTPClient();    // 设置超时时间    client.setConnectTimeout(30000);    try {        // 1、连接服务器        if (!client.isConnected()) {            // 如果采用默认端口,可以使用client.connect(host)的方式直接连接FTP服务器            client.connect(host, port);            // 登录            client.login(username, password);            // 获取ftp登录应答码            int reply = client.getReplyCode();            // 验证是否登陆成功            if (!FTPReply.isPositiveCompletion(reply)) {                client.disconnect();                throw new RuntimeException("未连接到FTP,用户名或密码错误。");            } else {                System.out.println("FTP连接成功。IP:" + host + "PORT:" + port);            }            // 2、设置连接属性            client.setControlEncoding(encoding);            // 设置以二进制方式传输            client.setFileType(FTPClient.BINARY_FILE_TYPE);            client.enterLocalPassiveMode();        }    } catch (SocketException e) {        try {            client.disconnect();        } catch (IOException e1) {        }        throw new RuntimeException("连接FTP服务器失败" + e.getMessage());    } catch (IOException e) {    }    InputStream stream = null;    try {        // 1、设置远程FTP目录        client.changeWorkingDirectory(remoteDir);        System.out.println("切换至工作目录【" + remoteDir + "】");        stream = client.retrieveFileStream(regEx);        int length = stream.available();        if (length != -1) {            byte[] buffer3 = new byte[1024];            int readCount = 0;            ServletOutputStream sos = response.getOutputStream();            while ((readCount = stream.read(buffer3)) > 0) {                sos.write(buffer3, 0, readCount);            }        }    } catch (IOException e) {        throw new RuntimeException("读取文件失败" + e.getMessage());    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

}

  • 1
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
ElasticSearch搜索引擎的使用整合SpringMVC
Springmvc与jasperreport结合生成报表的一种方法
图示ireport中使用javabean作数据源开发基于jasperreports报表过程
将输入的字符串逆向输出
java 读取配置文件
三层.业务层
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服