jaspersoft studio實踐 --實現網頁版打印小票(模板一)

由於項目業務需要,需要開發一個打印票據的需求。於是前面找了一堆資料來簡單學習了下,就開始自己動手開發起來了,下面直接細說。
首先小票模板的設計就用到了Jaspersoft Studio這個軟件(如果需要可以聯繫我或者官網上能下載到: https://community.jaspersoft.com/community-download)。

1.模板設計。

在這裏插入圖片描述
設計模板的步驟就不一一細說了,前面轉載的文章也有提到,可以去看看。直接上已經做好的模板,如下圖:在這裏插入圖片描述
數據來源是 json數據源,先寫一個json文件並且類型、名稱要對應與之連接。
在這裏插入圖片描述
而兩者連接需要xml文件,再新建一個xml文件。
在這裏插入圖片描述
**加粗樣式**
最後進行連接匹配,如下圖:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
最後將其生成的.jasper文件放到項目中去,如圖:
在這裏插入圖片描述
在這裏插入圖片描述

2.工具類。

到此,模板就設計完成了,下面就是利用java代碼進行賦值並且連接打印機打印了。
給出jasperReport的工具類,代碼如下:

package com.yd.wb.report.jasperReport;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRPrintPage;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.export.HtmlExporter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
import net.sf.jasperreports.engine.query.JsonQueryExecuterFactory;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleHtmlExporterOutput;
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput;
import net.sf.jasperreports.export.SimpleXlsxReportConfiguration;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;

import util.JCDFJsonUtil;

/**
 * @Description 打印PDF格式報表的工具類
 * 使用步驟:
 * 1.通過spring mvc生成json格式的業務數據
 * 2.將上一步生成的json數據保存成文件(調用exportJasperReport時將ReportType設置成JSON)
 * 3.在Jaspersoft@Studio創建DataAdapter, 類型爲JSON File, 將上一步生成的文件作爲數據源
 * 4.在Jaspersoft@Studio創建Jasper Report
 * 5.將編譯好的jasper複製到WEB-INF下的report目錄下
 * 6.調整Controller將輸出的ReportType調整成真實的類型, 運行輸出
 * 注意: 
 * 	 在Jasper Report創建時一定要增加一個 SUBREPORT_DIR 用於存儲子報表路徑
 * 
 */
@Component
public class JasperResolver {
	private Logger logger = Logger.getLogger(JasperResolver.class);
	@Autowired
	private ResourceLoader resourceLoader;
	
	/**
	 * @Description 將JSON填充到JasperReport格式化輸出
	 * @param data 單報表輸出的數據 Map<String, Object>
	 * @param reportFileName 報表文件名
	 * @param reportType 報表類型
	 * @return void
	 * 
	 */
	public void exportJasperReport(Map<String, Object> data, String reportFileName, ReportType reportType, 
			HttpServletRequest request, HttpServletResponse response) throws Exception{
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		list.add(data);
		exportJasperReport(list, reportFileName, reportType, request, response);
	}

	/**
	 * @Description 將JSON填充到JasperReport格式化輸出, 支持連打, 每一個List下的Item爲一個Report
	 * @param data 多報表輸出 List<Map<String, Object>>
	 * @param reportFileName 報表文件名
	 * @param reportType 報表類型
	 * @return void
	 * 
	 */
	public void exportJasperReport(List<Map<String, Object>> data, String reportFileName, ReportType reportType, 
			HttpServletRequest request, HttpServletResponse response) throws Exception{
		exportJasperReport(data, "/WEB-INF/report/", reportFileName, reportType, request, response);
	}

	/**
	 * @Description 具體的實現方法
	 * @param data 要打印的數據
	 * @param reportPath jasper文件所在的路徑
	 * @param reportFileName 報表文件名
	 * @param reportType 報表類型
	 * @return void
	 * 
	 */
	private void exportJasperReport(List<Map<String, Object>> data, String reportPath, String reportFileName, ReportType reportType, 
			HttpServletRequest request, HttpServletResponse response) throws Exception{
		OutputStream os = null;
		JasperPrint jasperPrint = null;
		try {
			//JSON直接輸出
			if(reportType == ReportType.JSON){ 
				response.setContentType("text/html;charset=UTF-8");
				response.setHeader("Pragma", "no-cache");
				response.setHeader("Cache-Control", "no-cache, must-revalidate");
				response.setHeader("Pragma", "no-cache");
				try {
					response.getWriter().write(JCDFJsonUtil.fromObjctToJson(data, null));
					response.getWriter().flush();
					response.getWriter().close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				return;
			}
			//獲取頁面輸出流
			os = response.getOutputStream(); 
			//設置頁面類型及編碼
			response.setContentType(reportType.getMimeType() + "; charset=utf-8"); 
			//清除頁面緩存
			response.setDateHeader("Expires", 0); 
			//設置文件名
			response.setHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(UUID.randomUUID() + reportType.getSuffix(), "utf-8"));
			
			JasperReport report = (JasperReport)JRLoader.loadObject(resourceLoader.getResource(reportPath + reportFileName + ".jasper").getInputStream());
			
			//創建HashMap來添加報表參數
			Map<String, Object> parameters = new HashMap<String, Object>();
			//添加標題參數, 確保密鑰與JasPrar報表中命名參數的名稱相同
			String classesPath = this.getClass().getClassLoader().getResource("").getPath();
			String servletContextRealPath = classesPath.substring(0, classesPath.lastIndexOf("WEB-INF"));
			parameters.put("SUBREPORT_DIR", servletContextRealPath + reportPath);
			
			for(Map<String, Object> item : data){
				String json = JCDFJsonUtil.fromObjctToJson(item, null);
				//將JSON字符串轉換爲字節數組,從JSON流創建JSON數據源
				ByteArrayInputStream jsonDataStream = new ByteArrayInputStream(json.getBytes("utf-8"));
				parameters.put(JsonQueryExecuterFactory.JSON_INPUT_STREAM, jsonDataStream);
				
				if(null == jasperPrint){
					jasperPrint = JasperFillManager.fillReport(report, parameters);
				} else { //連打
					JasperPrint jasperPrintTemp = JasperFillManager.fillReport(report, parameters);
					List<JRPrintPage> pages = jasperPrintTemp.getPages();
					for (JRPrintPage page : pages) {
						jasperPrint.addPage(page);
					}
				}
			}
			
			switch(reportType){
				case PDF:
					JRPdfExporter pdfExporter = new JRPdfExporter();
					pdfExporter.setExporterInput(new SimpleExporterInput(jasperPrint));
					pdfExporter.setExporterOutput(new SimpleOutputStreamExporterOutput(os));
					pdfExporter.exportReport();
					break;
					
				case XLSX:
					Map<String, String> dateFormats = new HashMap<String, String>();
					dateFormats.put("EEE, MMM d, yyyy", "ddd, mmm d, yyyy");
					
					JRXlsxExporter xlsxExporter = new JRXlsxExporter();
					SimpleXlsxReportConfiguration configuration = new SimpleXlsxReportConfiguration();
					xlsxExporter.setExporterInput(new SimpleExporterInput(jasperPrint));
					xlsxExporter.setExporterOutput(new SimpleOutputStreamExporterOutput(os));
					configuration.setDetectCellType(Boolean.TRUE);
					configuration.setFormatPatternsMap(dateFormats);
					xlsxExporter.setConfiguration(configuration);
					xlsxExporter.exportReport();
					break;
					
				default:
					HtmlExporter htmlExporter = new HtmlExporter();
					htmlExporter.setExporterInput(new SimpleExporterInput(jasperPrint));
					htmlExporter.setExporterOutput(new SimpleHtmlExporterOutput(os));
					htmlExporter.exportReport();
					break;
			}	 
			
			if(null != os){
				os.flush();
			}
		} finally {
			if(null != os){
				try {
					os.close();
				} catch (Exception e) {
					logger.error(e);
				}
				
			}
		}
		
	}
}
package com.yd.wb.report.jasperReport;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description 打印PDF格式報表的類型的枚舉類
 * 
 */
public enum ReportType {
	PDF(".pdf",1,"application/pdf"),
    XLSX(".xlsx",2,"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
    HTML(".html",4,"text/html"),
    JSON(".json",4,"application/json");
	
	/**後綴*/
	private String suffix;
	
	/**枚舉值*/
	private int value;
	
	/**頁面類型*/
	private String mimeType;
	
	private ReportType(String suffix, int value, String mimeType){
		this.suffix = suffix;
		this.value = value;
		this.mimeType = mimeType;
	}
	
	//在枚舉類型上實現fromString方法
	private static final Map<String, ReportType> stringToEnum = new HashMap<String, ReportType>();
	
	static {
		//從常量名初始化映射到enum常量
		for(ReportType item : values()){
			stringToEnum.put(item.toString(), item);
		}
	}
	
	//返回字符串的BLAH,如果字符串無效,則爲nul
	public static ReportType fromString(String name){
		return stringToEnum.get(name);
	}

	public String getSuffix() {
		return suffix;
	}

	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}

	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		this.value = value;
	}

	public String getMimeType() {
		return mimeType;
	}

	public void setMimeType(String mimeType) {
		this.mimeType = mimeType;
	}
	
}

3.java代碼獲取值

controller層代碼:

……………………………………………………………有關別的項目的代碼就不顯示了。
@Autowired
	private JasperResolver jasperResolver;
    private static final String C_ACTION_PRINT = "printTickets";
	
	/**
	 * 打印小票
	 */
	@RequestMapping(value="/printTickets")
    public CIPResponseMsg print(HttpServletRequest request,HttpServletResponse response,String serial_no,String trans_doc_id,String gross_weight,String net_weight){
		CIPResponseMsg msg = new CIPResponseMsg();
		//String trans_doc_id = request.getParameter("trans_doc_id");
		//Integer gross_weight = Integer.parseInt(request.getParameter("gross_weight"));
		Integer grossWeight = Integer.parseInt(gross_weight);
    	try {
    		   /*1、模板一:網點車未過磅小票。
    		                         網點車未過磅判斷邏輯:【毛重KG】字段爲0,發車憑證300開頭*/
    		if(grossWeight == 0 && trans_doc_id.startsWith("300")){
    		   List<Map<String, Object>> data = dataService.queryData(serial_no);
			   jasperResolver.exportJasperReport(data, "TICKETS_NETPOINT_CARS1", ReportType.PDF, request, response);
    		}else if(grossWeight > 0 && trans_doc_id.startsWith("300")){
    			/*2、模板二:網點車已過磅小票。
                                                           網點車車已過磅判斷邏輯:【毛重KG】字段爲大於0,發車憑證300開頭*/
    		   List<Map<String, Object>> data = dataService.queryOverweight(serial_no);
 			   jasperResolver.exportJasperReport(data, "TICKETS_NETPOINT_CARS2", ReportType.PDF, request, response);
    		}else if(trans_doc_id.startsWith("68")){
    			/*3、模板三:網絡車小票       網絡車判斷邏輯:發車憑證68開頭。*/
    		   List<Map<String, Object>> data = dataService.query(serial_no,trans_doc_id,net_weight);
    		   jasperResolver.exportJasperReport(data, "TICKETS_NETPOINT_CARS3", ReportType.PDF, request, response);
    		}
    	} catch (CIPServiceException e) {
			CIPErrorCode error = e.getErrorCode();
			msg.errorCode = error.code;
			msg.msg = error.name;
		} catch (CIPDaoException e) {
			CIPErrorCode error = e.getErrorCode();
			msg.errorCode = error.code;
			msg.msg = error.name;
		} catch (CIPRuntimeException e) {
			CIPErrorCode error = e.getErrorCode();
			msg.errorCode = error.code;
			msg.msg = error.name;
		} catch (Exception e) {
			log.error(e);
		}
    	return msg;
    }

service層代碼:

/**
	 * 打印
	 * 模板一:網點車未過磅小票。
	 */
	@Override
	public List<Map<String, Object>> queryData(String ids) {
		//定義一個list,封裝結果集
		List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
		//將傳過來的id字符串轉成id數組
		String[] idArr = ids.split(",");
		for (String serial_no : idArr) {
			//定義一個paraMap,封裝查詢參數
			Map<String, Object> paraMap = new HashMap<String, Object>();
			paraMap.put("serial_no", serial_no);
			//定義一個data,封裝結果
			Map<String, Object> data = new HashMap<String,Object>();
			
			//查詢信息
			Map<String, Object> map = dataDao.queryData(paraMap);
			if(map != null){
				Set<Entry<String, Object>> entrySet = map.entrySet();
				for (Entry<String, Object> entry : entrySet) {
					data.put(entry.getKey(), entry.getValue());
				}
			}
			list.add(data);
		}
		
		return list;
	}

dao層代碼:

/**
	 * 打印功能
	 */
	@Override
	public Map<String, Object> queryData(Map<String, Object> paraMap) {
		Map<String, Object> map = null;
		String sql = "SELECT b.com_name weight_site,DATE_FORMAT(create_time, '%Y-%m-%d %H:%i:%s') create_time,serial_no,b.com_name start_site_name,concat('(', a.start_site, ')') start_site,car_id,trans_doc_id,ifnull(c.emp_name,a.operator) operator,SYSDATE() FROM wb_busi_gross_weight a "
                     + " LEFT JOIN wb_base_com b ON a.weight_site = b.com_bm LEFT JOIN wb_base_emp c on a.operator = c.emp_id WHERE a.serial_no = ?";
		//Object[] obj = {trans_doc_id};
		Object serial_no = paraMap.get("serial_no");
		try {
			map = jdbcTemplate.queryForMap(sql,serial_no);
			return map;
		} catch (Exception e) {
			log.error(e);
			return map;
		}
	}

sql語句,注意:查詢後的字段要求與json文件的key相對應。

SELECT
	b.com_name weight_site,
	DATE_FORMAT(
		create_time,
		'%Y-%m-%d %H:%i:%s'
	) create_time,
	serial_no,
	b.com_name start_site_name,
	concat('(', a.start_site, ')') start_site,
	car_id,
	trans_doc_id,
	ifnull(c.emp_name, '') operator,
	SYSDATE()
FROM
	wb_busi_gross_weight a
LEFT JOIN wb_base_com b ON a.weight_site = b.com_bm
LEFT JOIN wb_base_emp c ON a.operator = c.emp_id
WHERE
	a.serial_no = '?'

html頁面部分代碼:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
最後的效果如下圖:在這裏插入圖片描述在這裏插入圖片描述

當然打印機驅動是我自己安裝的,這個看公司用的什麼打印機,這裏我就不介紹打印機配置的步驟了。
僅此記錄下來,歡迎各位大佬指教。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章