|
@@ -4,9 +4,13 @@ import java.io.BufferedReader;
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
|
import java.io.File;
|
|
import java.io.File;
|
|
|
import java.io.FileReader;
|
|
import java.io.FileReader;
|
|
|
|
|
+import java.io.FileWriter;
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
import java.io.OutputStream;
|
|
import java.io.OutputStream;
|
|
|
import java.sql.Connection;
|
|
import java.sql.Connection;
|
|
|
|
|
+import java.sql.PreparedStatement;
|
|
|
|
|
+import java.sql.ResultSet;
|
|
|
|
|
+import java.sql.ResultSetMetaData;
|
|
|
import java.sql.SQLException;
|
|
import java.sql.SQLException;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
@@ -17,6 +21,11 @@ import javax.sql.DataSource;
|
|
|
|
|
|
|
|
import org.apache.commons.lang.ArrayUtils;
|
|
import org.apache.commons.lang.ArrayUtils;
|
|
|
import org.apache.log4j.Logger;
|
|
import org.apache.log4j.Logger;
|
|
|
|
|
+import org.dom4j.Document;
|
|
|
|
|
+import org.dom4j.DocumentException;
|
|
|
|
|
+import org.dom4j.Element;
|
|
|
|
|
+import org.dom4j.io.SAXReader;
|
|
|
|
|
+import org.dom4j.io.XMLWriter;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
import org.springframework.util.CollectionUtils;
|
|
@@ -115,7 +124,6 @@ public class PrintServiceImpl implements PrintService {
|
|
|
|
|
|
|
|
userName = processMasterOfB2B(userName, reportName);
|
|
userName = processMasterOfB2B(userName, reportName);
|
|
|
String jrxmlFilePath = fileService.getJrxmlFilePath(userName, reportName);
|
|
String jrxmlFilePath = fileService.getJrxmlFilePath(userName, reportName);
|
|
|
- String jasperFilePath = maybeCompileJrxmlFile(jrxmlFilePath);
|
|
|
|
|
|
|
|
|
|
// 向报表模板传递参数:报表路径、where条件、其他参数
|
|
// 向报表模板传递参数:报表路径、where条件、其他参数
|
|
|
Map<String, Object> parameters = new HashMap<>();
|
|
Map<String, Object> parameters = new HashMap<>();
|
|
@@ -135,6 +143,8 @@ public class PrintServiceImpl implements PrintService {
|
|
|
connection = dataSource.getConnection();
|
|
connection = dataSource.getConnection();
|
|
|
logger.info("dataSource.getConnection done..." + userName);
|
|
logger.info("dataSource.getConnection done..." + userName);
|
|
|
|
|
|
|
|
|
|
+ String jasperFilePath = maybeCompileJrxmlFile(jrxmlFilePath, connection);
|
|
|
|
|
+
|
|
|
Map<String, Object> result = new HashMap<>();
|
|
Map<String, Object> result = new HashMap<>();
|
|
|
byte[] data = null;
|
|
byte[] data = null;
|
|
|
// 从数据库获取数据填充报表
|
|
// 从数据库获取数据填充报表
|
|
@@ -213,7 +223,7 @@ public class PrintServiceImpl implements PrintService {
|
|
|
* 报表模板文件
|
|
* 报表模板文件
|
|
|
* @return 编译后的jasper文件路径
|
|
* @return 编译后的jasper文件路径
|
|
|
*/
|
|
*/
|
|
|
- private String maybeCompileJrxmlFile(String jrxmlFilePath) {
|
|
|
|
|
|
|
+ private String maybeCompileJrxmlFile(String jrxmlFilePath, Connection connection) {
|
|
|
if (StringUtils.isEmpty(jrxmlFilePath)) {
|
|
if (StringUtils.isEmpty(jrxmlFilePath)) {
|
|
|
logger.error("参数不能为空:" + jrxmlFilePath);
|
|
logger.error("参数不能为空:" + jrxmlFilePath);
|
|
|
return null;
|
|
return null;
|
|
@@ -254,7 +264,7 @@ public class PrintServiceImpl implements PrintService {
|
|
|
}
|
|
}
|
|
|
bufferedReader.close();
|
|
bufferedReader.close();
|
|
|
for (String subJrxmlFilePath : subJrxmlFilePaths) {
|
|
for (String subJrxmlFilePath : subJrxmlFilePaths) {
|
|
|
- maybeCompileJrxmlFile(subJrxmlFilePath);
|
|
|
|
|
|
|
+ maybeCompileJrxmlFile(subJrxmlFilePath, connection);
|
|
|
}
|
|
}
|
|
|
} catch (IOException e) {
|
|
} catch (IOException e) {
|
|
|
throw new ReportException(e).setDetailedMessage(e);
|
|
throw new ReportException(e).setDetailedMessage(e);
|
|
@@ -267,14 +277,12 @@ public class PrintServiceImpl implements PrintService {
|
|
|
// 报表模板未编译过
|
|
// 报表模板未编译过
|
|
|
if (!jasperFile.exists()) {
|
|
if (!jasperFile.exists()) {
|
|
|
logger.info("正在编译报表模板... " + jrxmlFilePath);
|
|
logger.info("正在编译报表模板... " + jrxmlFilePath);
|
|
|
- JasperDesign jasperDesign = JRXmlLoader.load(jrxmlFile);
|
|
|
|
|
- JasperCompileManager.compileReportToFile(jasperDesign, jasperFilePath);
|
|
|
|
|
|
|
+ compileReportToFile(jrxmlFilePath, jasperFilePath, connection);
|
|
|
} else {
|
|
} else {
|
|
|
// 如果在编译之后,报表模板有更改过 ,重新编译
|
|
// 如果在编译之后,报表模板有更改过 ,重新编译
|
|
|
if (jrxmlFile.lastModified() > jasperFile.lastModified()) {
|
|
if (jrxmlFile.lastModified() > jasperFile.lastModified()) {
|
|
|
logger.info("正在重新编译报表模板... " + jrxmlFilePath);
|
|
logger.info("正在重新编译报表模板... " + jrxmlFilePath);
|
|
|
- JasperDesign jasperDesign = JRXmlLoader.load(jrxmlFile);
|
|
|
|
|
- JasperCompileManager.compileReportToFile(jasperDesign, jasperFilePath);
|
|
|
|
|
|
|
+ compileReportToFile(jrxmlFilePath, jasperFilePath, connection);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
} catch (JRException e) {
|
|
} catch (JRException e) {
|
|
@@ -284,6 +292,107 @@ public class PrintServiceImpl implements PrintService {
|
|
|
return jasperFilePath;
|
|
return jasperFilePath;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 编译jrxml报表模板为jasper文件
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param jrxmlFilePath
|
|
|
|
|
+ * 模板文件
|
|
|
|
|
+ * @param jasperFilePath
|
|
|
|
|
+ * 编译后的文件
|
|
|
|
|
+ * @param connection
|
|
|
|
|
+ * 数据库连接
|
|
|
|
|
+ * @throws JRException
|
|
|
|
|
+ */
|
|
|
|
|
+ private void compileReportToFile(String jrxmlFilePath, String jasperFilePath, Connection connection)
|
|
|
|
|
+ throws JRException {
|
|
|
|
|
+ processFields(jrxmlFilePath, connection);
|
|
|
|
|
+ JasperCompileManager.compileReportToFile(jrxmlFilePath, jasperFilePath);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 处理模板中的field
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param jrxmlFilePath
|
|
|
|
|
+ * @param connection
|
|
|
|
|
+ */
|
|
|
|
|
+ private void processFields(String jrxmlFilePath, Connection connection) {
|
|
|
|
|
+ SAXReader saxReader = new SAXReader();
|
|
|
|
|
+ Document document;
|
|
|
|
|
+ XMLWriter xmlWriter = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ document = saxReader.read(new File(jrxmlFilePath));
|
|
|
|
|
+ Element rootElement = document.getRootElement();
|
|
|
|
|
+ // 查询语句
|
|
|
|
|
+ Element queryStringElement = rootElement.element("queryString");
|
|
|
|
|
+ String queryString = queryStringElement.getText();
|
|
|
|
|
+ logger.info(queryString);
|
|
|
|
|
+ // 如果查询语句中含有WHERE_CONDITION参数,需将其替换掉
|
|
|
|
|
+ if (queryString.contains("$P!{WHERE_CONDITION}")) {
|
|
|
|
|
+ queryString = queryString.substring(0, queryString.indexOf("$P!{WHERE_CONDITION}"))
|
|
|
|
|
+ + "where rownum = 1";
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果查询语句中含有where条件,则可能有用到一些参数,需将其替换掉
|
|
|
|
|
+ else if (queryString.toUpperCase().contains("WHERE")) {
|
|
|
|
|
+ queryString = queryString.substring(0, queryString.indexOf("WHERE")) + "where rownum = 1";
|
|
|
|
|
+ }
|
|
|
|
|
+ logger.info(queryString);
|
|
|
|
|
+ List<String> columnNames = getColumnNames(connection, queryString);
|
|
|
|
|
+ if (CollectionUtils.isEmpty(columnNames)) {
|
|
|
|
|
+ throw new ReportException("未查询到任何列:" + queryString);
|
|
|
|
|
+ }
|
|
|
|
|
+ logger.info(columnNames);
|
|
|
|
|
+ // 指定的field
|
|
|
|
|
+ @SuppressWarnings("rawtypes")
|
|
|
|
|
+ List fieldElements = rootElement.elements("field");
|
|
|
|
|
+ boolean needModifying = false;
|
|
|
|
|
+ for (int i = 0; i < fieldElements.size(); i++) {
|
|
|
|
|
+ Element element = (Element) fieldElements.get(i);
|
|
|
|
|
+ String columnName = element.attribute("name").getText();
|
|
|
|
|
+ // 如果指定的Field在当前帐套的表中不存在,则删除该Field
|
|
|
|
|
+ if (!columnNames.contains(columnName.toUpperCase())) {
|
|
|
|
|
+ needModifying = true;
|
|
|
|
|
+ rootElement.remove(element);
|
|
|
|
|
+ logger.info("Removed... " + columnName);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果需要修改,则重新写入模板文件
|
|
|
|
|
+ if (needModifying) {
|
|
|
|
|
+ xmlWriter = new XMLWriter(new FileWriter(jrxmlFilePath));
|
|
|
|
|
+ xmlWriter.write(document);
|
|
|
|
|
+ xmlWriter.flush();
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (DocumentException | SQLException | IOException e) {
|
|
|
|
|
+ throw new ReportException(e).setDetailedMessage(e);
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ if (xmlWriter != null) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ xmlWriter.close();
|
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
|
+ throw new ReportException(e).setDetailedMessage(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取列名
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param connection
|
|
|
|
|
+ * @param sql
|
|
|
|
|
+ * @return
|
|
|
|
|
+ * @throws SQLException
|
|
|
|
|
+ */
|
|
|
|
|
+ private List<String> getColumnNames(Connection connection, String sql) throws SQLException {
|
|
|
|
|
+ List<String> result = new ArrayList<>();
|
|
|
|
|
+ PreparedStatement preparedStatement = connection.prepareStatement(sql);
|
|
|
|
|
+ ResultSet resultSet = preparedStatement.executeQuery();
|
|
|
|
|
+ ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
|
|
|
|
|
+ for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
|
|
|
|
|
+ result.add(resultSetMetaData.getColumnName(i).toUpperCase());
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 以xls的格式导出报表
|
|
* 以xls的格式导出报表
|
|
|
*
|
|
*
|