diff --git a/JSD-8235-需求确认书V1.2(1).docx b/JSD-8235-需求确认书V1.2(1).docx new file mode 100644 index 0000000..b29e3f6 Binary files /dev/null and b/JSD-8235-需求确认书V1.2(1).docx differ diff --git a/README.md b/README.md index e68c960..1f0c759 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # open-JSD-8235 -JSD-8235 开源任务材料 \ No newline at end of file +JSD-8235 开源任务材料\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 \ No newline at end of file diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..047a94d --- /dev/null +++ b/plugin.xml @@ -0,0 +1,20 @@ + + com.fr.plugin.jh.export + + yes + 1.0.2 + 10.0 + 2018-07-31 + fr.open + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/JHHandlerProvider.java b/src/main/java/com/fr/plugin/JHHandlerProvider.java new file mode 100644 index 0000000..f72e0d2 --- /dev/null +++ b/src/main/java/com/fr/plugin/JHHandlerProvider.java @@ -0,0 +1,23 @@ +package com.fr.plugin; + +import com.fr.decision.fun.HttpHandler; +import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; +import com.fr.plugin.api.DataTableExport; +import com.fr.plugin.api.SQLQueryApi; +import com.fr.plugin.api.SQLUpdateApi; +import com.fr.plugin.transform.ExecuteFunctionRecord; +import com.fr.plugin.transform.FunctionRecorder; + +@FunctionRecorder +public class JHHandlerProvider extends AbstractHttpHandlerProvider { + @Override + @ExecuteFunctionRecord + public HttpHandler[] registerHandlers() { + return new HttpHandler[]{ + new DataTableExport(), + new SQLQueryApi(), + new SQLUpdateApi() + }; + } + +} diff --git a/src/main/java/com/fr/plugin/JHURLAliasBridge.java b/src/main/java/com/fr/plugin/JHURLAliasBridge.java new file mode 100644 index 0000000..78dc82b --- /dev/null +++ b/src/main/java/com/fr/plugin/JHURLAliasBridge.java @@ -0,0 +1,29 @@ +package com.fr.plugin; + +import com.fr.decision.fun.impl.AbstractURLAliasProvider; +import com.fr.decision.webservice.url.alias.URLAlias; +import com.fr.decision.webservice.url.alias.URLAliasFactory; +import com.fr.general.IOUtils; +import com.fr.stable.StringUtils; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Scanner; +import java.util.Set; + +public class JHURLAliasBridge extends AbstractURLAliasProvider { + + @Override + public URLAlias[] registerAlias() { + return new URLAlias[]{ + URLAliasFactory.createPluginAlias("/dynamic/dataresource/api/update", "/update", false), + URLAliasFactory.createPluginAlias("/dynamic/dataresource/api/query", "/query", false), + URLAliasFactory.createPluginAlias("/dynamic/dataresource/api/output", "/output", false), + }; + } + + +} diff --git a/src/main/java/com/fr/plugin/api/DataTableExport.java b/src/main/java/com/fr/plugin/api/DataTableExport.java new file mode 100644 index 0000000..cfff48e --- /dev/null +++ b/src/main/java/com/fr/plugin/api/DataTableExport.java @@ -0,0 +1,165 @@ +package com.fr.plugin.api; + +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.utils.AesUtils; +import com.fr.plugin.utils.DbUtils; +import com.fr.plugin.utils.RespUtils; +import com.fr.third.org.apache.commons.lang3.time.DateFormatUtils; +import com.fr.third.springframework.util.StringUtils; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.utils.WebUtils; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedWriter; +import java.io.OutputStreamWriter; +import java.util.*; + + +public class DataTableExport extends BaseHttpHandler { + + @Override + public RequestMethod getMethod() { + return RequestMethod.POST; + } + + @Override + public String getPath() { + return "/output"; + } + + + @Override + public boolean isPublic() { + return false; + } + + @Override + public void handle(HttpServletRequest request, HttpServletResponse httpServletResponse) throws Exception { + //获取参数 + List keys = new ArrayList<>(); + keys.add("table_name"); + keys.add("where"); + keys.add("field_break"); + keys.add("fields"); + keys.add("need_title"); + keys.add("line_break"); + keys.add("m_flag"); + + Map params = new HashMap<>(); + FineLoggerFactory.getLogger().info("加密fine_user为:{}", AesUtils.encryptPassword("find_user")); + FineLoggerFactory.getLogger().info("加密后在解密测试:{}", AesUtils.decryptPassword(AesUtils.encryptPassword("find_user"))); + for (String key : keys) { + String value = WebUtils.getHTTPRequestParameter(request, key); + if (StringUtils.isEmpty(value)) { + FineLoggerFactory.getLogger().info("导出接口:传入的{}为空", key); + httpServletResponse.setStatus(500); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-100, "未提供" + key + "参数")); + return; + } + try { + FineLoggerFactory.getLogger().info("导出接口:待解密{}:{}", key, value); + String temp = AesUtils.decryptPassword(value); + if (temp == null) { + temp = ""; + } + FineLoggerFactory.getLogger().info("导出接口:解密{} 之后为:{}", key, temp); + params.put(key, temp); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("导出接口:解密SQL异常 ", e); + httpServletResponse.setStatus(500); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-102, "解密query参数失败")); + return; + } + } + + + try { + String tableName = params.get("table_name"); + DbUtils dbUtils = new DbUtils(); + if (StringUtils.isEmpty(tableName) || !dbUtils.checkTableExit(tableName)) { + FineLoggerFactory.getLogger().error("导出接口:传过来的表不存在{} ", tableName); + httpServletResponse.setStatus(500); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-103, "表不存在:" + tableName)); + return; + } + String where = params.get("where"); + String countSql = String.format("select count(1) from %s %s", tableName, where); + int rowCount = dbUtils.countRows(countSql); + int pageSize = 2000; + int totalPage = rowCount % pageSize == 0 ? rowCount / pageSize : (rowCount / pageSize) + 1; + String fields = params.get("fields"); + String m_flag = params.get("m_flag"); + //获取一个写出的流 + String date = DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"); + httpServletResponse.setHeader("file_name", String.format("{%s}__%s__%s__%d.dat", m_flag, tableName, date, rowCount)); + ServletOutputStream outputStream = httpServletResponse.getOutputStream(); + BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); + String line_break = params.get("line_break"); + if (StringUtils.isEmpty(line_break)) { + line_break = "\n"; + } + String field_break = params.get("field_break"); + if (StringUtils.isEmpty(field_break)) { + field_break = "|@|"; + } + String need_title = params.get("need_title"); + boolean needTitle = com.fr.stable.StringUtils.equals(need_title, "true"); + //如果需要标题,先做一次预查寻,把表头查出来 + + if (needTitle) { + String preSql = String.format("select %s from %s %s limit 1",fields,tableName,where); + List lists = dbUtils.getQueryFields(preSql); + StringBuilder builder = new StringBuilder(); + boolean isFirst = true; + for (String name : lists) { + String temp = StringUtils.trimAllWhitespace(name); + if (isFirst) { + isFirst = false; + }else{ + builder.append(field_break); + } + builder.append(temp); + } + builder.append(line_break); + bufferedWriter.write(builder.toString()); + } + + for (int i = 0; i < totalPage; i++) { + List dataByPage = getDataByPage(tableName, fields, where, i, pageSize, dbUtils, line_break, field_break); + for (String line : dataByPage) { + bufferedWriter.write(line); + } + } + bufferedWriter.flush(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("导出接口:执行SQL异常 ", e); + httpServletResponse.setStatus(500); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-103, "SQL执行失败:" + RespUtils.Exception2String(e))); + } + } + + private List getDataByPage(String tableName, String fields, String where, int page, int pageSize, DbUtils dbUtils, String line_break, String field_break) throws Exception { + String sql = String.format("select %s from %s %s limit %d,%d", fields, tableName, where, page, pageSize); + return dbUtils.query(sql, line_break, field_break); + } + + public static void main(String[] args) { +// String table_name = AesUtils.encryptPassword("fine_user"); +// String where = AesUtils.encryptPassword("where id>100"); +// String fields = AesUtils.encryptPassword("id,name,xxxxx,xxx"); +// String field_break = AesUtils.encryptPassword("xxx"); +// //以及剩下的 +// StringBuilder builder = new StringBuilder(); +// builder.append("table_name=").append(table_name) +// .append("&where=").append(where) +// .append("&fields=").append(fields) +// .append("&field_break=").append(field_break); +// //以及剩下的,按照这种格式弄 +// String params = builder.toString(); +// HttpUtils.doPostToFile("/output", params, null, "xxx地址"); + } + +} diff --git a/src/main/java/com/fr/plugin/api/SQLQueryApi.java b/src/main/java/com/fr/plugin/api/SQLQueryApi.java new file mode 100644 index 0000000..209cece --- /dev/null +++ b/src/main/java/com/fr/plugin/api/SQLQueryApi.java @@ -0,0 +1,67 @@ +package com.fr.plugin.api; + +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.json.JSONArray; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.utils.AesUtils; +import com.fr.plugin.utils.DbUtils; +import com.fr.plugin.utils.RespUtils; +import com.fr.stable.StringUtils; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +public class SQLQueryApi extends BaseHttpHandler { + + @Override + public RequestMethod getMethod() { + return RequestMethod.POST; + } + + @Override + public String getPath() { + return "/query"; + } + + @Override + public boolean isPublic() { + return false; + } + + @Override + public void handle(HttpServletRequest request, HttpServletResponse httpServletResponse) throws Exception { + //获取参数 + String query = WebUtils.getHTTPRequestParameter(request, "query"); + if (StringUtils.isBlank(query)) { + FineLoggerFactory.getLogger().info("查询接口:传入的sql为空"); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-100, "未提供query参数")); + return; + } + String sql = ""; + try { + FineLoggerFactory.getLogger().info("查询接口:待解密query:{}", query); + sql = AesUtils.decryptPassword(query); + FineLoggerFactory.getLogger().info("查询接口:解密之后为:{}", sql); + if (StringUtils.isBlank(sql)) { + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-101, "解密之后的SQL为空")); + return; + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error("查询接口:解密SQL异常 ", e); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-102, "解密query参数失败")); + return; + } + try { + DbUtils dbUtils = new DbUtils(); + JSONArray jsonArray = dbUtils.exQuery(sql); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildSuccess(jsonArray)); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("查询接口:执行SQL异常 ", e); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-103, "SQL执行失败:" + RespUtils.Exception2String(e))); + return; + } + } +} diff --git a/src/main/java/com/fr/plugin/api/SQLUpdateApi.java b/src/main/java/com/fr/plugin/api/SQLUpdateApi.java new file mode 100644 index 0000000..378d4cb --- /dev/null +++ b/src/main/java/com/fr/plugin/api/SQLUpdateApi.java @@ -0,0 +1,71 @@ +package com.fr.plugin.api; + +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.utils.AesUtils; +import com.fr.plugin.utils.DbUtils; +import com.fr.plugin.utils.RespUtils; +import com.fr.stable.StringUtils; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +public class SQLUpdateApi extends BaseHttpHandler { + + @Override + public RequestMethod getMethod() { + return RequestMethod.POST; + } + + @Override + public String getPath() { + return "/update"; + } + + + @Override + public boolean isPublic() { + return false; + } + + @Override + public void handle(HttpServletRequest request, HttpServletResponse httpServletResponse) throws Exception { + //获取参数 + String query = WebUtils.getHTTPRequestParameter(request, "query"); + if (StringUtils.isBlank(query)) { + FineLoggerFactory.getLogger().info("更新接口:传入的sql为空"); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-100, "未提供query参数")); + return; + } + String sql = ""; + try { + FineLoggerFactory.getLogger().info("更新接口:待解密query:{}", query); + sql = AesUtils.decryptPassword(query); + FineLoggerFactory.getLogger().info("更新接口:解密之后为:{}", sql); + if (StringUtils.isBlank(sql)) { + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-101, "解密之后的SQL为空")); + return; + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error("更新接口:解密SQL异常 ", e); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-102, "解密query参数失败")); + return; + } + try { + DbUtils dbUtils = new DbUtils(); + int rows = dbUtils.exSqlUpdate(sql); + JSONObject resp=new JSONObject(); + resp.put("rows", rows); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildSuccess(resp)); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("更新接口:执行SQL异常 ", e); + WebUtils.printAsJSON(httpServletResponse, RespUtils.buildError(-103, "SQL执行失败:" + RespUtils.Exception2String(e))); + return; + } + } +} diff --git a/src/main/java/com/fr/plugin/utils/AesUtils.java b/src/main/java/com/fr/plugin/utils/AesUtils.java new file mode 100644 index 0000000..c35761b --- /dev/null +++ b/src/main/java/com/fr/plugin/utils/AesUtils.java @@ -0,0 +1,89 @@ +package com.fr.plugin.utils; + + +import com.fr.log.FineLoggerFactory; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +public class AesUtils { + public static String encrypt(byte[] byteContent, String keyPass) { + try { + SecretKeySpec secretKey = new SecretKeySpec(keyPass.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES");// 创建密码器 + cipher.init(Cipher.ENCRYPT_MODE, secretKey);// 初始化 + byte[] result = cipher.doFinal(byteContent); + return Base64.getUrlEncoder().encodeToString(result); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String encrypt(String keyPass, String content) { + try { + SecretKeySpec secretKey = new SecretKeySpec(keyPass.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES");// 创建密码器 + byte[] byteContent = content.getBytes(Charset.forName("UTF-8")); + cipher.init(Cipher.ENCRYPT_MODE, secretKey);// 初始化 + byte[] result = cipher.doFinal(byteContent); + return Base64.getUrlEncoder().encodeToString(result); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String decrypt(byte[] content, String keyPass) { + try { + SecretKeySpec secretKey = new SecretKeySpec(keyPass.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES");// 创建密码器 + cipher.init(Cipher.DECRYPT_MODE, secretKey);// 初始化 + byte[] result = cipher.doFinal(content); + return new String(result, StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static String decrypt(String keyPass, String source) { + byte[] content = Base64.getUrlDecoder().decode(source); + + try { + SecretKeySpec secretKey = new SecretKeySpec(keyPass.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance("AES");// 创建密码器 + cipher.init(Cipher.DECRYPT_MODE, secretKey);// 初始化 + byte[] result = cipher.doFinal(content); + + return new String(result, StandardCharsets.UTF_8); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("解密数据出错,"); + printException2Frlog(e); + } + return null; + } + + public static void printException2Frlog(Exception e) { + StringWriter writer = new StringWriter(); + e.printStackTrace(new PrintWriter(writer)); + String s = writer.toString(); + FineLoggerFactory.getLogger().error("错误:{}", s); + } + public static String decryptPassword(String source) { + return decrypt("xxxxx", source); + } + + public static String encryptPassword(String source) { + return encrypt("xxxxx", source); + } + + public static void main(String[] args) { + System.out.println(encryptPassword("fine_user")); + System.out.println(decryptPassword(encryptPassword("fine_user"))); + } + +} diff --git a/src/main/java/com/fr/plugin/utils/DbUtils.java b/src/main/java/com/fr/plugin/utils/DbUtils.java new file mode 100644 index 0000000..38516b7 --- /dev/null +++ b/src/main/java/com/fr/plugin/utils/DbUtils.java @@ -0,0 +1,212 @@ +package com.fr.plugin.utils; + +import com.fr.file.ConnectionConfig; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.log.FineLoggerProvider; +import com.fr.third.springframework.util.StringUtils; + +import java.sql.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class DbUtils { + String db_name = "finedb"; + + FineLoggerProvider logger = FineLoggerFactory.getLogger(); + + + public com.fr.data.impl.Connection getDbConnect() { + return ConnectionConfig.getInstance().getConnection(db_name); + } + + public JSONArray select(String sql, Object... params) { + logger.info("query data by sql:" + sql + Arrays.toString(params)); + try { + com.fr.data.impl.Connection dbConnect = getDbConnect(); + + Connection con = dbConnect.createConnection(); + PreparedStatement preparedStatement = con.prepareStatement(sql); + setParams(preparedStatement, params); + ResultSet rs = preparedStatement.executeQuery(sql); + // 获得记录的详细信息,然后获得总列数 + ResultSetMetaData resMetaData = rs.getMetaData(); + int colNum = resMetaData.getColumnCount(); + // 用对象保存数据 + String name = ""; + String value = ""; + JSONArray list = new JSONArray(); + while (rs.next()) { + JSONObject cells = new JSONObject(); + for (int i = 0; i < colNum; i++) { + name = resMetaData.getColumnLabel(i); + if (cells.get(name) != null) { + name = resMetaData.getColumnLabel(i); + } + if (rs.getObject(i) != null && resMetaData.getColumnTypeName(i).equals("DATETIME") || resMetaData.getColumnTypeName(i).equals("TIMESTAMP")) { + value = rs.getObject(i).toString(); + cells.put(name, value.substring(0, value.length() - 2)); + } else { + cells.put(name, rs.getString(i)); + } + } + list.add(cells); + } + // 释放数据库资源 + rs.close(); + preparedStatement.close(); + con.close(); + return list; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public JSONObject findOneRow(String sql, Object... params) { + JSONArray select = select(sql, params); + if (select != null) { + if (!select.isEmpty()) { + return select.getJSONObject(0); + } + } + return null; + } + + public int countRows(String sql, Object... params) throws Exception { + PreparedStatement pstmt = getDbConnect().createConnection().prepareStatement(sql); + setParams(pstmt, params); + ResultSet resultSet = pstmt.executeQuery(); + if (resultSet.next()) { + return resultSet.getInt(1); + } + return 0; + } + + public boolean checkExist(String sql, Object... params) throws Exception { + PreparedStatement pstmt = getDbConnect().createConnection().prepareStatement(sql); + setParams(pstmt, params); + ResultSet resultSet = pstmt.executeQuery(); + if (resultSet.next()) { + return resultSet.getInt(1) > 0; + } + return false; + } + + public boolean checkTableExit(String tableName) throws Exception { + String sql = "SELECT\n" + + "\tcount(1) \n" + + "FROM\n" + + "\t" + tableName + " \n"; + return checkExist(sql); + } + + private void setParams(PreparedStatement pstmt, Object... params) throws SQLException { + if (params.length > 0) { + int length = params.length; + for (int i = 1; i <= length; i++) { + pstmt.setObject(i, params[i - 1]); + } + } + } + + public int exSqlUpdate(String sql, Object... params) throws Exception { + logger.info("update data by sql:" + sql + " params " + Arrays.toString(params)); + com.fr.data.impl.Connection dbConnect = getDbConnect(); + Connection connection = dbConnect.createConnection(); + PreparedStatement pstmt = connection.prepareStatement(sql); + setParams(pstmt, params); + int i = pstmt.executeUpdate(); + pstmt.close(); + connection.close(); + return i; + } + + /** + * 取查询结果集字段 + * + * @param sql + * @param params + * @return + * @throws Exception + */ + public JSONArray exQuery(String sql, Object... params) throws Exception { + logger.info("query data by sql:" + sql + " params " + Arrays.toString(params)); + com.fr.data.impl.Connection dbConnect = getDbConnect(); + Connection connection = dbConnect.createConnection(); + PreparedStatement pstmt = connection.prepareStatement(sql); + setParams(pstmt, params); + ResultSet resultSet = pstmt.executeQuery(); + ResultSetMetaData resMetaData = resultSet.getMetaData(); + int columnCount = resMetaData.getColumnCount(); + JSONArray arrs = new JSONArray(); + while (resultSet.next()) { + String name; + String value; + JSONObject one = new JSONObject(); + for (int i = 1; i <= columnCount; i++) { + name = resMetaData.getColumnLabel(i); + if (one.get(name) != null) { + name = resMetaData.getColumnLabel(i); + } + if (resultSet.getObject(i) != null && resMetaData.getColumnTypeName(i).equals("DATETIME") || resMetaData.getColumnTypeName(i).equals("TIMESTAMP")) { + value = resultSet.getObject(i).toString(); + one.put(name, value.substring(0, value.length() - 2)); + } else { + one.put(name, resultSet.getString(i)); + } + } + arrs.add(one); + } + + pstmt.close(); + connection.close(); + logger.info("查询结果:" + arrs); + return arrs; + } + + public List query(String sql,String line_break,String field_break) throws Exception { + com.fr.data.impl.Connection dbConnect = getDbConnect(); + Connection connection = dbConnect.createConnection(); + PreparedStatement pstmt = connection.prepareStatement(sql); + ResultSet resultSet = pstmt.executeQuery(); + ResultSetMetaData resMetaData = resultSet.getMetaData(); + int columnCount = resMetaData.getColumnCount(); + List arrs = new ArrayList<>(); + while (resultSet.next()) { + StringBuilder builder = new StringBuilder(); + for (int i = 1; i <= columnCount; i++) { + if(i !=1 ){ + builder.append(field_break); + } + String data = resultSet.getString(i); + builder.append(StringUtils.trimAllWhitespace(data)); + } + builder.append(line_break); + arrs.add(builder.toString()); + } + pstmt.close(); + connection.close(); + return arrs; + } + + public List getQueryFields(String preSql, Object... params) throws Exception { + com.fr.data.impl.Connection dbConnect = getDbConnect(); + Connection connection = dbConnect.createConnection(); + PreparedStatement pstmt = connection.prepareStatement(preSql); + setParams(pstmt, params); + ResultSet resultSet = pstmt.executeQuery(); + ResultSetMetaData resMetaData = resultSet.getMetaData(); + int columnCount = resMetaData.getColumnCount(); + List arrs = new ArrayList<>(); + for (int i = 0; i < columnCount; i++) { + String columnName = resMetaData.getColumnName(i + 1); + arrs.add(columnName); + } + pstmt.close(); + connection.close(); + return arrs; + } +} diff --git a/src/main/java/com/fr/plugin/utils/RespUtils.java b/src/main/java/com/fr/plugin/utils/RespUtils.java new file mode 100644 index 0000000..f479337 --- /dev/null +++ b/src/main/java/com/fr/plugin/utils/RespUtils.java @@ -0,0 +1,34 @@ +package com.fr.plugin.utils; + + +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; + +import java.io.PrintWriter; +import java.io.StringWriter; + +public class RespUtils { + public static JSONObject buildResp(int code, String msg, Object data) { + JSONObject res = new JSONObject(); + res.put("code", code); + res.put("msg", msg); + res.put("data", data); + return res; + } + public static String Exception2String(Throwable e) { + StringWriter writer = new StringWriter(); + e.printStackTrace(new PrintWriter(writer)); + return writer.toString(); + } + public static JSONObject buildError(int code, String msg) { + return buildResp(code, msg, ""); + } + + public static JSONObject buildNormalError(String msg) { + return buildResp(-1, msg, ""); + } + + public static JSONObject buildSuccess(Object data) { + return buildResp(0, "success", data); + } +} diff --git a/src/main/resources/com/fr/plugin/alert.html b/src/main/resources/com/fr/plugin/alert.html new file mode 100644 index 0000000..bfb2ea2 --- /dev/null +++ b/src/main/resources/com/fr/plugin/alert.html @@ -0,0 +1,35 @@ + + + + + alert + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/demo.properties b/src/main/resources/com/fr/plugin/demo.properties new file mode 100644 index 0000000..9bc5f29 --- /dev/null +++ b/src/main/resources/com/fr/plugin/demo.properties @@ -0,0 +1 @@ +Plugin-Test_Function_Abs=Test ABS \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/demo_zh_CN.properties b/src/main/resources/com/fr/plugin/demo_zh_CN.properties new file mode 100644 index 0000000..aa910e8 --- /dev/null +++ b/src/main/resources/com/fr/plugin/demo_zh_CN.properties @@ -0,0 +1 @@ +Plugin-Test_Function_Abs=测试ABS函数 \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/js/print.js b/src/main/resources/com/fr/plugin/js/print.js new file mode 100644 index 0000000..e5965af --- /dev/null +++ b/src/main/resources/com/fr/plugin/js/print.js @@ -0,0 +1,476 @@ +!function (e, t) { + "object" == typeof exports && "object" == typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define([], t) : "object" == typeof exports ? exports.printJS = t() : e.printJS = t() +}(window, function () { + return function (n) { + var r = {}; + + function o(e) { + if (r[e]) return r[e].exports; + var t = r[e] = {i: e, l: !1, exports: {}}; + return n[e].call(t.exports, t, t.exports, o), t.l = !0, t.exports + } + + return o.m = n, o.c = r, o.d = function (e, t, n) { + o.o(e, t) || Object.defineProperty(e, t, {enumerable: !0, get: n}) + }, o.r = function (e) { + "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {value: "Module"}), Object.defineProperty(e, "__esModule", {value: !0}) + }, o.t = function (t, e) { + if (1 & e && (t = o(t)), 8 & e) return t; + if (4 & e && "object" == typeof t && t && t.__esModule) return t; + var n = Object.create(null); + if (o.r(n), Object.defineProperty(n, "default", { + enumerable: !0, + value: t + }), 2 & e && "string" != typeof t) for (var r in t) o.d(n, r, function (e) { + return t[e] + }.bind(null, r)); + return n + }, o.n = function (e) { + var t = e && e.__esModule ? function () { + return e.default + } : function () { + return e + }; + return o.d(t, "a", t), t + }, o.o = function (e, t) { + return Object.prototype.hasOwnProperty.call(e, t) + }, o.p = "", o(o.s = 4) + }([function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = n(2), i = (r = o) && r.__esModule ? r : {default: r}, a = n(1); + var l = { + send: function (r, e) { + document.getElementsByTagName("body")[0].appendChild(e); + var o = document.getElementById(r.frameId); + o.onload = function () { + if ("pdf" !== r.type) { + var e = o.contentWindow || o.contentDocument; + if (e.document && (e = e.document), e.body.appendChild(r.printableElement), "pdf" !== r.type && r.style) { + var t = document.createElement("style"); + t.innerHTML = r.style, e.head.appendChild(t) + } + var n = e.getElementsByTagName("img"); + 0 < n.length ? function (e) { + var t = [], n = !0, r = !1, o = void 0; + try { + for (var i, a = e[Symbol.iterator](); !(n = (i = a.next()).done); n = !0) { + var l = i.value; + t.push(u(l)) + } + } catch (e) { + r = !0, o = e + } finally { + try { + !n && a.return && a.return() + } finally { + if (r) throw o + } + } + return Promise.all(t) + }(n).then(function () { + return d(o, r) + }) : d(o, r) + } else d(o, r) + } + } + }; + + function d(t, n) { + try { + if (t.focus(), i.default.isEdge() || i.default.isIE()) try { + t.contentWindow.document.execCommand("print", !1, null) + } catch (e) { + t.contentWindow.print() + } else t.contentWindow.print() + } catch (e) { + n.onError(e) + } finally { + (0, a.cleanUp)(n) + } + } + + function u(n) { + return new Promise(function (t) { + !function e() { + n && void 0 !== n.naturalWidth && 0 !== n.naturalWidth && n.complete ? t() : setTimeout(e, 500) + }() + }) + } + + t.default = l + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var i = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) { + return typeof e + } : function (e) { + return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e + }; + t.addWrapper = function (e, t) { + return '
' + e + "
" + }, t.capitalizePrint = function (e) { + return e.charAt(0).toUpperCase() + e.slice(1) + }, t.collectStyles = f, t.loopNodesCollectStyles = function e(t, n) { + for (var r = 0; r < t.length; r++) { + var o = t[r]; + if (-1 === n.ignoreElements.indexOf(o.getAttribute("id"))) { + var i = o.tagName; + if ("INPUT" === i || "TEXTAREA" === i || "SELECT" === i) { + var a = f(o, n), l = o.parentNode, + d = "SELECT" === i ? document.createTextNode(o.options[o.selectedIndex].text) : document.createTextNode(o.value), + u = document.createElement("div"); + u.appendChild(d), u.setAttribute("style", a), l.appendChild(u), l.removeChild(o) + } else o.setAttribute("style", f(o, n)); + var c = o.children; + c && c.length && e(c, n) + } else o.parentNode.removeChild(o) + } + }, t.addHeader = function (e, t) { + var n = document.createElement("div"); + if (l(t.header)) n.innerHTML = t.header; else { + var r = document.createElement("h1"), o = document.createTextNode(t.header); + r.appendChild(o), r.setAttribute("style", t.headerStyle), n.appendChild(r) + } + e.insertBefore(n, e.childNodes[0]) + }, t.cleanUp = function (t) { + t.showModal && r.default.close(); + t.onLoadingEnd && t.onLoadingEnd(); + (t.showModal || t.onLoadingStart) && window.URL.revokeObjectURL(t.printable); + if (t.onPrintDialogClose) { + var n = "mouseover"; + (o.default.isChrome() || o.default.isFirefox()) && (n = "focus"); + window.addEventListener(n, function e() { + window.removeEventListener(n, e), t.onPrintDialogClose() + }) + } + }, t.isRawHTML = l; + var r = a(n(3)), o = a(n(2)); + + function a(e) { + return e && e.__esModule ? e : {default: e} + } + + function f(e, t) { + var n = document.defaultView || window, r = "", o = n.getComputedStyle(e, ""); + return Object.keys(o).map(function (e) { + (-1 !== t.targetStyles.indexOf("*") || -1 !== t.targetStyle.indexOf(o[e]) || function (e, t) { + for (var n = 0; n < e.length; n++) if ("object" === (void 0 === t ? "undefined" : i(t)) && -1 !== t.indexOf(e[n])) return !0; + return !1 + }(t.targetStyles, o[e])) && o.getPropertyValue(o[e]) && (r += o[e] + ":" + o.getPropertyValue(o[e]) + ";") + }), r += "max-width: " + t.maxWidth + "px !important;" + t.font_size + " !important;" + } + + function l(e) { + return new RegExp("<([A-Za-z][A-Za-z0-9]*)\\b[^>]*>(.*?)").test(e) + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r = { + isFirefox: function () { + return "undefined" != typeof InstallTrigger + }, isIE: function () { + return -1 !== navigator.userAgent.indexOf("MSIE") || !!document.documentMode + }, isEdge: function () { + return !r.isIE() && !!window.StyleMedia + }, isChrome: function () { + return !!(0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : window).chrome + }, isSafari: function () { + return 0 < Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor") || -1 !== navigator.userAgent.toLowerCase().indexOf("safari") + } + }; + t.default = r + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var a = { + show: function (e) { + var t = document.createElement("div"); + t.setAttribute("style", "font-family:sans-serif; display:table; text-align:center; font-weight:300; font-size:30px; left:0; top:0;position:fixed; z-index: 9990;color: #0460B5; width: 100%; height: 100%; background-color:rgba(255,255,255,.9);transition: opacity .3s ease;"), t.setAttribute("id", "printJS-Modal"); + var n = document.createElement("div"); + n.setAttribute("style", "display:table-cell; vertical-align:middle; padding-bottom:100px;"); + var r = document.createElement("div"); + r.setAttribute("class", "printClose"), r.setAttribute("id", "printClose"), n.appendChild(r); + var o = document.createElement("span"); + o.setAttribute("class", "printSpinner"), n.appendChild(o); + var i = document.createTextNode(e.modalMessage); + n.appendChild(i), t.appendChild(n), document.getElementsByTagName("body")[0].appendChild(t), document.getElementById("printClose").addEventListener("click", function () { + a.close() + }) + }, close: function () { + var e = document.getElementById("printJS-Modal"); + e.parentNode.removeChild(e) + } + }; + t.default = a + }, function (e, t, n) { + e.exports = n(5) + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}), n(6); + var r, o = n(7); + var i = ((r = o) && r.__esModule ? r : {default: r}).default.init; + "undefined" != typeof window && (window.printJS = i), t.default = i + }, function (e, t, n) { + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var i = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) { + return typeof e + } : function (e) { + return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e + }, a = r(n(2)), l = r(n(3)), d = r(n(8)), u = r(n(9)), c = r(n(10)), f = r(n(11)), s = r(n(12)); + + function r(e) { + return e && e.__esModule ? e : {default: e} + } + + var p = ["pdf", "html", "image", "json", "raw-html"]; + t.default = { + init: function () { + var t = { + printable: null, + fallbackPrintable: null, + type: "pdf", + header: null, + headerStyle: "font-weight: 300;", + maxWidth: 800, + font: "TimesNewRoman", + font_size: "12pt", + honorMarginPadding: !0, + honorColor: !1, + properties: null, + gridHeaderStyle: "font-weight: bold; padding: 5px; border: 1px solid #dddddd;", + gridStyle: "border: 1px solid lightgray; margin-bottom: -1px;", + showModal: !1, + onError: function (e) { + throw e + }, + onLoadingStart: null, + onLoadingEnd: null, + onPrintDialogClose: null, + onPdfOpen: null, + onBrowserIncompatible: function () { + return !0 + }, + modalMessage: "Retrieving Document...", + frameId: "printJS", + printableElement: null, + documentTitle: "Document", + targetStyle: ["clear", "display", "width", "min-width", "height", "min-height", "max-height"], + targetStyles: ["border", "box", "break", "text-decoration"], + ignoreElements: [], + imageStyle: "max-width: 100%;", + repeatTableHeader: !0, + css: null, + style: null, + scanStyles: !0, + base64: !1 + }, e = arguments[0]; + if (void 0 === e) throw new Error("printJS expects at least 1 attribute."); + switch (void 0 === e ? "undefined" : i(e)) { + case"string": + t.printable = encodeURI(e), t.fallbackPrintable = t.printable, t.type = arguments[1] || t.type; + break; + case"object": + for (var n in t.printable = e.printable, t.base64 = void 0 !== e.base64, t.fallbackPrintable = void 0 !== e.fallbackPrintable ? e.fallbackPrintable : t.printable, t.fallbackPrintable = t.base64 ? "data:application/pdf;base64," + t.fallbackPrintable : t.fallbackPrintable, t) "printable" !== n && "fallbackPrintable" !== n && "base64" !== n && (t[n] = void 0 !== e[n] ? e[n] : t[n]); + break; + default: + throw new Error('Unexpected argument type! Expected "string" or "object", got ' + (void 0 === e ? "undefined" : i(e))) + } + if (!t.printable) throw new Error("Missing printable information."); + if (!t.type || "string" != typeof t.type || -1 === p.indexOf(t.type.toLowerCase())) throw new Error("Invalid print type. Available types are: pdf, html, image and json."); + t.showModal && l.default.show(t), t.onLoadingStart && t.onLoadingStart(); + var r = document.getElementById(t.frameId); + r && r.parentNode.removeChild(r); + var o = void 0; + switch ((o = document.createElement("iframe")).setAttribute("style", "visibility: hidden; height: 0; width: 0; position: absolute;"), o.setAttribute("id", t.frameId), "pdf" !== t.type && (o.srcdoc = "" + t.documentTitle + "", null !== t.css && (Array.isArray(t.css) || (t.css = [t.css]), t.css.forEach(function (e) { + o.srcdoc += '' + })), o.srcdoc += ""), t.type) { + case"pdf": + if (a.default.isFirefox() || a.default.isEdge() || a.default.isIE()) try { + if (console.info("PrintJS currently doesn't support PDF printing in Firefox, Internet Explorer and Edge."), !0 === t.onBrowserIncompatible()) window.open(t.fallbackPrintable, "_blank").focus(), t.onPdfOpen && t.onPdfOpen() + } catch (e) { + t.onError(e) + } finally { + t.showModal && l.default.close(), t.onLoadingEnd && t.onLoadingEnd() + } else d.default.print(t, o); + break; + case"image": + f.default.print(t, o); + break; + case"html": + u.default.print(t, o); + break; + case"raw-html": + c.default.print(t, o); + break; + case"json": + s.default.print(t, o) + } + } + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = n(0), i = (r = o) && r.__esModule ? r : {default: r}, a = n(1); + + function l(e, t, n) { + var r = new window.Blob([n], {type: "application/pdf"}); + r = window.URL.createObjectURL(r), t.setAttribute("src", r), i.default.send(e, t) + } + + t.default = { + print: function (e, t) { + if (e.base64) { + var n = Uint8Array.from(atob(e.printable), function (e) { + return e.charCodeAt(0) + }); + l(e, t, n) + } else { + e.printable = /^(blob|http)/i.test(e.printable) ? e.printable : window.location.origin + ("/" !== e.printable.charAt(0) ? "/" + e.printable : e.printable); + var r = new window.XMLHttpRequest; + r.responseType = "arraybuffer", r.addEventListener("load", function () { + if (-1 === [200, 201].indexOf(r.status)) return (0, a.cleanUp)(e), void e.onError(r.statusText); + l(e, t, r.response) + }), r.open("GET", e.printable, !0), r.send() + } + } + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = n(1), i = n(0), a = (r = i) && r.__esModule ? r : {default: r}; + t.default = { + print: function (e, t) { + var n = document.getElementById(e.printable); + n ? (e.printableElement = function e(t, n) { + var r = t.cloneNode(); + var o = !0; + var i = !1; + var a = void 0; + try { + for (var l, d = t.childNodes[Symbol.iterator](); !(o = (l = d.next()).done); o = !0) { + var u = l.value; + if (-1 === n.ignoreElements.indexOf(u.id)) { + var c = e(u, n); + r.appendChild(c) + } + } + } catch (e) { + i = !0, a = e + } finally { + try { + !o && d.return && d.return() + } finally { + if (i) throw a + } + } + switch (t.tagName) { + case"SELECT": + r.value = t.value; + break; + case"CANVAS": + r.getContext("2d").drawImage(t, 0, 0) + } + return r + }(n, e), e.header && (0, o.addHeader)(e.printableElement, e), a.default.send(e, t)) : window.console.error("Invalid HTML element id: " + e.printable) + } + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = n(0), i = (r = o) && r.__esModule ? r : {default: r}; + t.default = { + print: function (e, t) { + e.printableElement = document.createElement("div"), e.printableElement.setAttribute("style", "width:100%"), e.printableElement.innerHTML = e.printable, i.default.send(e, t) + } + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = n(1), i = n(0), a = (r = i) && r.__esModule ? r : {default: r}; + t.default = { + print: function (r, e) { + r.printable.constructor !== Array && (r.printable = [r.printable]), r.printableElement = document.createElement("div"), r.printable.forEach(function (e) { + var t = document.createElement("img"); + t.setAttribute("style", r.imageStyle), t.src = e; + var n = document.createElement("div"); + n.appendChild(t), r.printableElement.appendChild(n) + }), r.header && (0, o.addHeader)(r.printableElement, r), a.default.send(r, e) + } + } + }, function (e, t, n) { + "use strict"; + Object.defineProperty(t, "__esModule", {value: !0}); + var r, o = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) { + return typeof e + } : function (e) { + return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e + }, c = n(1), i = n(0), a = (r = i) && r.__esModule ? r : {default: r}; + t.default = { + print: function (t, e) { + if ("object" !== o(t.printable)) throw new Error("Invalid javascript data object (JSON)."); + if ("boolean" != typeof t.repeatTableHeader) throw new Error("Invalid value for repeatTableHeader attribute (JSON)."); + if (!t.properties || !Array.isArray(t.properties)) throw new Error("Invalid properties array for your JSON data."); + t.properties = t.properties.map(function (e) { + return { + field: "object" === (void 0 === e ? "undefined" : o(e)) ? e.field : e, + displayName: "object" === (void 0 === e ? "undefined" : o(e)) ? e.displayName : e, + columnSize: "object" === (void 0 === e ? "undefined" : o(e)) && e.columnSize ? e.columnSize + ";" : 100 / t.properties.length + "%;" + } + }), t.printableElement = document.createElement("div"), t.header && (0, c.addHeader)(t.printableElement, t), t.printableElement.innerHTML += function (e) { + var t = e.printable, n = e.properties, + r = ''; + e.repeatTableHeader && (r += ""); + r += ""; + for (var o = 0; o < n.length; o++) r += '"; + r += "", e.repeatTableHeader && (r += ""); + r += ""; + for (var i = 0; i < t.length; i++) { + r += ""; + for (var a = 0; a < n.length; a++) { + var l = t[i], d = n[a].field.split("."); + if (1 < d.length) for (var u = 0; u < d.length; u++) l = l[d[u]]; else l = l[n[a].field]; + r += '" + } + r += "" + } + return r += "
' + (0, c.capitalizePrint)(n[o].displayName) + "
' + l + "
" + }(t), a.default.send(t, e) + } + } + }]).default +}); + +/** + * 打印图片,传入要打印的图片,相对路径或者绝对路径都可以 + * @param url + */ +function printImage(url) { + printJS(url, 'image') +} + +window.printImage=printImage; +/** + * PDF文件必须与使用的程序在相同的域中。在打印文件之前会使用iframe加载文件,因此受到Same Origin Policy的限制。 + */ +function printPdf(url) { + printJS(url, 'pdf') +} +window.printPdf=printPdf; +/** + * 使用base64封装的pdfdata对象。 + */ +function printPdfBase64(data) { + printJS({printable: data, type: 'pdf', base64: true}) +} +window.printPdfBase64=printPdfBase64; +/** + * 打印dom对象, 传递要打印dom的id 不带#号 + */ +function printDom(nodeId) { + printJS({printable: nodeId, type: 'html'}) +} +window.printDom=printDom; \ No newline at end of file