Browse Source

预览出错时,支持查看详细信息

sunyj 9 years ago
parent
commit
5ebd748455

+ 10 - 10
src/main/java/com/uas/report/controller/PrintController.java

@@ -19,7 +19,7 @@ import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 
-import com.uas.report.core.exception.SystemError;
+import com.uas.report.core.exception.ReportException;
 import com.uas.report.service.PrintService;
 import com.uas.report.util.PathUtils;
 import com.uas.report.util.ReportConstants;
@@ -72,7 +72,7 @@ public class PrintController {
 			try {
 				request.getRequestDispatcher("preview").forward(request, response);
 			} catch (IOException | ServletException e) {
-				throw new SystemError(e);
+				throw new ReportException(e).setDetailedMessage(e);
 			}
 		}
 		// 下载pdf、纯数据excel
@@ -81,7 +81,7 @@ public class PrintController {
 		} else if (printType.equals(ReportConstants.EXCEL_PRINT_TYPE)) {
 			export(userName, reportName, whereCondition, otherParameters, "xls_with_only_data", response);
 		} else {
-			throw new SystemError("printType不合法");
+			throw new ReportException("printType不合法");
 		}
 	}
 
@@ -126,7 +126,7 @@ public class PrintController {
 		if (!printService.isFileValid(file.getPath())) {
 			data = printService.export(userName, reportName, whereCondition, otherParameters, exportFileType);
 			if (ArrayUtils.isEmpty(data)) {
-				throw new SystemError("报表导出失败:" + reportName);
+				throw new ReportException("报表导出失败:" + reportName);
 			}
 			printService.writeDataToFile(file.getPath(), data);
 		} else {
@@ -136,13 +136,13 @@ public class PrintController {
 				data = new byte[fileInputStream.available()];
 				fileInputStream.read(data);
 			} catch (IOException e) {
-				throw new SystemError(e);
+				throw new ReportException(e).setDetailedMessage(e);
 			} finally {
 				if (fileInputStream != null) {
 					try {
 						fileInputStream.close();
 					} catch (IOException e) {
-						throw new SystemError(e);
+						throw new ReportException(e).setDetailedMessage(e);
 					}
 				}
 			}
@@ -214,7 +214,7 @@ public class PrintController {
 					data = (byte[]) result.remove("data");
 				}
 				if (data == null) {
-					throw new SystemError("获取预览数据失败");
+					throw new ReportException("获取预览数据失败");
 				}
 				printService.writeDataToFile(file.getPath(), data);
 				// 同时生成分页的pdf
@@ -264,7 +264,7 @@ public class PrintController {
 			result.put("valid", printService.isFileValid(file.getPath()));
 			result.put("size", file.length());
 		} else {
-			throw new SystemError("pdfOrXls只能为pdf或xls");
+			throw new ReportException("pdfOrXls只能为pdf或xls");
 		}
 		return result;
 	}
@@ -279,10 +279,10 @@ public class PrintController {
 	 */
 	private void checkParameters(String userName, String reportName) {
 		if (StringUtils.isEmpty(userName)) {
-			throw new SystemError("未传入当前账套用户名!");
+			throw new ReportException("未传入当前账套用户名!");
 		}
 		if (StringUtils.isEmpty(reportName)) {
-			throw new SystemError("未传入报表名称!");
+			throw new ReportException("未传入报表名称!");
 		}
 	}
 }

+ 14 - 6
src/main/java/com/uas/report/core/advice/ExceptionHandlerAdvice.java

@@ -9,10 +9,11 @@ import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.ui.ModelMap;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 
-import com.uas.report.core.exception.SystemError;
+import com.uas.report.core.exception.ReportException;
 
 /**
  * <p>
@@ -87,18 +88,25 @@ public class ExceptionHandlerAdvice {
 	/**
 	 * 处理已捕获异常,明确传达给客户端错误码、错误信息
 	 * 
-	 * @see SystemError
+	 * @see ReportException
 	 * @param ex
 	 * @return
 	 */
-	@ExceptionHandler(SystemError.class)
-	public ResponseEntity<ModelMap> handleSystemError(SystemError ex) {
-		logger.error(ex.getMessage());
+	@ExceptionHandler(ReportException.class)
+	public ResponseEntity<ModelMap> handleSystemError(ReportException ex) {
 		HttpHeaders headers = new HttpHeaders();
 		headers.add("Content-Type", "application/json; charset=utf-8");
 		ModelMap map = new ModelMap();
 		map.put("success", false);
-		map.put("message", ex.getMessage());
+		// 将换行符、Tab空格替换为前端的表示
+		map.put("message", ex.getMessage().replaceAll("\n", "<br/>").replaceAll("\t", "&nbsp;&nbsp;&nbsp;&nbsp;"));
+		if (!StringUtils.isEmpty(ex.getDetailedMessage())) {
+			logger.error(ex.getDetailedMessage());
+			map.put("detailedMessage",
+					ex.getDetailedMessage().replaceAll("\n", "<br/>").replaceAll("\t", "&nbsp;&nbsp;&nbsp;&nbsp;"));
+		} else {
+			logger.error(ex.getMessage());
+		}
 		return new ResponseEntity<ModelMap>(map, headers, HttpStatus.BAD_REQUEST);
 	}
 

+ 90 - 0
src/main/java/com/uas/report/core/exception/ReportException.java

@@ -0,0 +1,90 @@
+package com.uas.report.core.exception;
+
+/**
+ * 将失败原因以成功的请求返回
+ * 
+ * @author sunyj
+ * @since 2016年10月19日 上午8:52:17
+ */
+public class ReportException extends RuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+	private String message;
+
+	/**
+	 * 详细信息
+	 */
+	private String detailedMessage;
+
+	public ReportException(String message) {
+		this.message = message;
+	}
+
+	public ReportException(Throwable e) {
+		this.message = getMessage(e);
+	}
+
+	/**
+	 * 获取异常及其Cause拼接成的字符串
+	 * 
+	 * @param e
+	 *            异常
+	 * @return 拼接后的结果
+	 */
+	public String getMessage(Throwable e) {
+		StringBuilder sb = new StringBuilder(e.toString());
+		if (e.getCause() != null) {
+			sb.append("\nCaused by: ").append(getMessage(e.getCause()));
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 获取异常及其Cause的StackTrace拼接成的字符串
+	 * 
+	 * @param e
+	 *            异常
+	 * @return 拼接后的结果
+	 */
+	public String getDetailedMessage(Throwable e) {
+		StringBuilder sb = new StringBuilder(e.toString());
+		StackTraceElement[] stackTraceElements = e.getStackTrace();
+		for (StackTraceElement stackTraceElement : stackTraceElements) {
+			sb.append("\n\t").append(stackTraceElement.toString());
+		}
+		if (e.getCause() != null) {
+			sb.append("\nCaused by: ").append(getDetailedMessage(e.getCause()));
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 获取异常及其Cause的StackTrace用以设置详细信息
+	 * 
+	 * @param e
+	 *            异常
+	 * @return 本SearchException对象
+	 */
+	public ReportException setDetailedMessage(Throwable e) {
+		this.detailedMessage = getDetailedMessage(e);
+		return this;
+	}
+
+	public String getMessage() {
+		return message;
+	}
+
+	public void setMessage(String message) {
+		this.message = message;
+	}
+
+	public String getDetailedMessage() {
+		return detailedMessage;
+	}
+
+	public void setDetailedMessage(String detailedMessage) {
+		this.detailedMessage = detailedMessage;
+	}
+
+}

+ 0 - 49
src/main/java/com/uas/report/core/exception/SystemError.java

@@ -1,49 +0,0 @@
-package com.uas.report.core.exception;
-
-/**
- * 需要把失败原因以成功的请求返回给客户端
- * 
- * @author suntg
- * @since 2016年8月30日上午9:36:10
- */
-public class SystemError extends RuntimeException {
-
-	/**
-	 * 序列号
-	 */
-	private static final long serialVersionUID = 1L;
-
-	private String message;
-
-	public SystemError(Throwable e) {
-		this.message = getMessage(e);
-	}
-
-	/**
-	 * 获取异常及其Cause拼接成的字符串
-	 * 
-	 * @param e
-	 *            异常
-	 * @return 拼接后的结果
-	 */
-	private String getMessage(Throwable e) {
-		StringBuilder sb = new StringBuilder(e.toString());
-		if (e.getCause() != null) {
-			sb.append("\nCaused by: ").append(getMessage(e.getCause()));
-		}
-		return sb.toString();
-	}
-
-	public String getMessage() {
-		return message;
-	}
-
-	public void setMessage(String message) {
-		this.message = message;
-	}
-
-	public SystemError(String message) {
-		this.message = message;
-	}
-
-}

+ 16 - 16
src/main/java/com/uas/report/service/impl/PrintServiceImpl.java

@@ -31,7 +31,7 @@ import com.itextpdf.text.Document;
 import com.itextpdf.text.DocumentException;
 import com.itextpdf.text.pdf.PdfCopy;
 import com.itextpdf.text.pdf.PdfReader;
-import com.uas.report.core.exception.SystemError;
+import com.uas.report.core.exception.ReportException;
 import com.uas.report.service.PrintService;
 import com.uas.report.service.ResourceService;
 import com.uas.report.support.JasperserverRestAPIConf;
@@ -112,7 +112,7 @@ public class PrintServiceImpl implements PrintService {
 				if (!isFileValid(file.getPath())) {
 					byte[] data = export(userName, reportName, whereCondition, otherParameters, "xls_with_only_data");
 					if (ArrayUtils.isEmpty(data)) {
-						throw new SystemError("报表导出失败:" + reportName);
+						throw new ReportException("报表导出失败:" + reportName);
 					}
 					writeDataToFile(file.getPath(), data);
 				}
@@ -144,7 +144,7 @@ public class PrintServiceImpl implements PrintService {
 			pageSize = (Integer) result.remove("pageSize");
 		}
 		if (data == null || pageSize == null) {
-			throw new SystemError("获取预览数据失败");
+			throw new ReportException("获取预览数据失败");
 		}
 		writeDataToFile(file.getPath(), data);
 		return pageSize;
@@ -163,7 +163,7 @@ public class PrintServiceImpl implements PrintService {
 			logger.info("Writed file..." + file.getPath());
 			fos.close();
 		} catch (IOException e) {
-			throw new SystemError(e);
+			throw new ReportException(e).setDetailedMessage(e);
 		}
 	}
 
@@ -185,7 +185,7 @@ public class PrintServiceImpl implements PrintService {
 			}
 			pdfReader.close();
 		} catch (IOException | DocumentException e) {
-			throw new SystemError(e);
+			throw new ReportException(e).setDetailedMessage(e);
 		}
 	}
 
@@ -194,7 +194,7 @@ public class PrintServiceImpl implements PrintService {
 		try {
 			return new PdfReader(pdfFilePath).getNumberOfPages();
 		} catch (IOException e) {
-			throw new SystemError(e);
+			throw new ReportException(e).setDetailedMessage(e);
 		}
 	}
 
@@ -247,7 +247,7 @@ public class PrintServiceImpl implements PrintService {
 		try {
 			resourceService.syncResources(userName);
 		} catch (URISyntaxException | IOException e) {
-			throw new SystemError(e);
+			throw new ReportException(e).setDetailedMessage(e);
 		}
 
 		// 报表路径为报表根路径REPORT_DIR + 当前账套用户名userName
@@ -258,7 +258,7 @@ public class PrintServiceImpl implements PrintService {
 		// 报表模板不存在
 		if (!jrxmlFile.exists()) {
 			// 替换windows下路径中的双反斜杠为单斜杠
-			throw new SystemError("未发现模板文件:" + jrxmlFile.getPath().replaceAll("\\\\", "/"));
+			throw new ReportException("未发现模板文件:" + jrxmlFile.getPath().replaceAll("\\\\", "/"));
 		}
 
 		String jasperFilePath = jrxmlFile.getPath().replace(".jrxml", ".jasper");
@@ -280,7 +280,7 @@ public class PrintServiceImpl implements PrintService {
 			}
 		} catch (JRException e) {
 			logger.error(e);
-			throw new SystemError("编译报表模板失败:" + e.getMessage());
+			throw new ReportException("编译报表模板失败:" + e.getMessage()).setDetailedMessage(e);
 		}
 
 		// 向报表模板传递参数:报表路径、where条件、其他参数
@@ -300,7 +300,7 @@ public class PrintServiceImpl implements PrintService {
 			// 获取数据源
 			DataSource dataSource = getDataSource(userName);
 			if (dataSource == null) {
-				throw new SystemError("获取数据源失败");
+				throw new ReportException("获取数据源失败");
 			}
 
 			connection = dataSource.getConnection();
@@ -359,13 +359,13 @@ public class PrintServiceImpl implements PrintService {
 				return result;
 			}
 		} catch (SQLException | JRException | IOException e) {
-			throw new SystemError(e);
+			throw new ReportException(e).setDetailedMessage(e);
 		} finally {
 			if (connection != null) {
 				try {
 					connection.close();
 				} catch (SQLException e) {
-					throw new SystemError(e);
+					throw new ReportException(e).setDetailedMessage(e);
 				}
 			}
 		}
@@ -418,7 +418,7 @@ public class PrintServiceImpl implements PrintService {
 				}
 			}
 		} catch (Exception e) {
-			throw new SystemError(e);
+			throw new ReportException(e).setDetailedMessage(e);
 		} finally {
 			try {
 				if (resultSet != null) {
@@ -439,7 +439,7 @@ public class PrintServiceImpl implements PrintService {
 					connection.close();
 				}
 			} catch (SQLException e) {
-				throw new SystemError(e);
+				throw new ReportException(e).setDetailedMessage(e);
 			}
 		}
 		return null;
@@ -459,10 +459,10 @@ public class PrintServiceImpl implements PrintService {
 			} else if (exportFileType.equals("xls")) {
 				exportReportToXls(jasperPrint, outputStream);
 			} else {
-				throw new SystemError("不支持导出为 " + exportFileType + "格式!");
+				throw new ReportException("不支持导出为 " + exportFileType + "格式!");
 			}
 		} catch (JRException e) {
-			throw new SystemError(e);
+			throw new ReportException(e).setDetailedMessage(e);
 		}
 	}
 

+ 16 - 9
src/main/webapp/WEB-INF/views/preview2.html

@@ -10,10 +10,10 @@
 <body>
 	<div id="toolbarContainer">
 		<div id="toolbarViewerLeft">
-			<button id="zoomOut" title="缩小">
+			<button id="zoomOut" class="toolbarButton" title="缩小">
 				<i class="fa fa-minus fa-lg" aria-hidden="true"></i>
 			</button>
-			<button id="zoomIn" title="放大">
+			<button id="zoomIn" class="toolbarButton" title="放大">
 				<i class="fa fa-plus fa-lg" aria-hidden="true"></i>
 			</button>
 			<label class="select"> <select id="scaleSelect">
@@ -34,24 +34,25 @@
 		</div>
 
 		<div id="toobarViewerCenter">
-			<button id="prev" title="上页">
+			<button id="prev" class="toolbarButton" title="上页">
 				<i class="fa fa-arrow-left fa-lg" aria-hidden="true"></i>
 			</button>
-			<span>Page: <input id="pageIndex" type="text" /> / <span
-				id="pageSize"></span></span>
-			<button id="next" title="下页">
+			<span><input id="pageIndex" type="text" /> / <span
+				id="pageSize">0</span></span>
+			<button id="next" class="toolbarButton" title="下页">
 				<i class="fa fa-arrow-right fa-lg" aria-hidden="true"></i>
 			</button>
 		</div>
 
 		<div id="toolbarViewerRight">
-			<button id="print" title="打印">
+			<button id="print" class="toolbarButton" title="打印">
 				<i class="fa fa-print fa-lg" aria-hidden="true"></i>
 			</button>
-			<button id="downloadPdf" title="下载PDF">
+			<button id="downloadPdf" class="toolbarButton" title="下载PDF">
 				<i class="fa fa-file-pdf-o fa-lg" aria-hidden="true"></i>
 			</button>
-			<button id="downloadExcelWithOnlyData" title="下载Excel(仅数据)">
+			<button id="downloadExcelWithOnlyData" class="toolbarButton"
+				title="下载Excel(仅数据)">
 				<i class="fa fa-file-excel-o fa-lg" aria-hidden="true"></i>
 			</button>
 		</div>
@@ -60,6 +61,12 @@
 	<div id="viewerContainer">
 		<canvas id="theCanvas"></canvas>
 	</div>
+	<div id="errorMessageContainer" hidden="true">
+		<p id="message"></p>
+		<button id="detailedMessageButton" class="viewerContainerButton"
+			title="获取更多错误信息">更多信息</button>
+		<p id="detailedMessage" hidden="true"></p>
+	</div>
 
 	<iframe id="hiddenFrame" hidden='true'></iframe>
 </body>

+ 24 - 4
src/main/webapp/resources/css/preview2.css

@@ -4,7 +4,7 @@ body {
 	font-family: courier;
 }
 
-button, .select, #toolbarContainer, #scaleSelect {
+.select, #toolbarContainer, #scaleSelect {
 	background-color: #404040;
 	color: #fff;
 }
@@ -15,12 +15,17 @@ button {
 	outline: none;
 }
 
+button.toolbarButton {
+	background-color: #404040;
+	color: #fff;
+}
+
 #toolbarContainer {
 	position: fixed;
 	width: 100%;
-	height: 40px;
+	height: 50px;
 	top: 0;
-	line-height: 40px;
+	line-height: 50px;
 }
 
 #toolbarViewerLeft, #toobarViewerCenter, #toolbarViewerRight {
@@ -86,6 +91,21 @@ select::-ms-expand {
 
 #viewerContainer {
 	text-align: center;
-	margin-top: 50px;
+	margin-top: 60px;
 	margin-bottom: 10px;
+}
+
+#errorMessageContainer {
+	padding: 0px 40px 0px 40px;
+}
+
+#errorMessageContainer>p {
+	color: #fff;
+	word-wrap: break-world;
+	word-break: break-all;
+}
+
+button.viewerContainerButton {
+	border-radius: 10%;
+	height: 25px;
 }

+ 19 - 9
src/main/webapp/resources/js/preview2/app.js

@@ -107,7 +107,7 @@ $("#downloadPdf").click(
 			}
 			// 检查文件状态,直到其可用
 			var valid = getGeneratedPdfOrXlsInformation('pdf').valid;
-			// 文件除了要保证有效(存在并且未过有效期),还要确保hiddenFrameLoaded不能为真
+			// 文件除了要保证有效(存在并且未过有效期),还要确保hiddenFrameLoaded不能为真,因为存在下列情况
 			// 1.hiddenFrameLoaded不为真,即此时刚进入页面,文档尚未生成,需要等待其生成;
 			// 2.hiddenFrameLoaded为真,页面加载成功后并未关闭,闲置了一段时间,再次点击打印,
 			// 此时文件可能已经过期,需要立即请求下载(后台此时会重新生成),不能处于等待状态;
@@ -302,15 +302,25 @@ function loadData() {
 			// console.log(renderTask._internalRenderTask.running);
 		},
 		error : function(XMLHttpRequest) {
-			var viewerContainer = document.getElementById("viewerContainer");
-			viewerContainer.removeChild(document.getElementById("theCanvas"));
-			var p = document.createElement("p");
-			p.style.color = "#fff";
-			p.style.textAlign = "left";
-			p.style.marginLeft = "20px";
+			$("#theCanvas").remove();
+			$("#errorMessageContainer").removeAttr("hidden");
+			
+			//处理后台传输的自定义的换行标志
+			var result = JSON.parse(XMLHttpRequest.responseText);
+			var message = result.message;
+			console.log(message);
+			$("#message").html(message);
+			$("#detailedMessageButton").click(function(){
+				$("#detailedMessage").html(result.detailedMessage);
+				$("#detailedMessage").removeAttr("hidden");
+			});
+//			var p = document.createElement("p");
+//			p.style.color = "#fff";
+//			p.style.textAlign = "left";
+//			p.style.marginLeft = "20px";
 			// 将返回的错误信息显示在页面上
-			p.textContent = XMLHttpRequest.responseText;
-			viewerContainer.appendChild(p);
+//			p.textContent = XMLHttpRequest.responseText;
+//			viewerContainer.appendChild(p);
 		}
 	});
 };