java110 4 år sedan
förälder
incheckning
f9de2fc8e2

+ 3 - 0
java110-bean/src/main/java/com/java110/dto/reportCustomComponent/ReportCustomComponentDto.java

@@ -15,6 +15,9 @@ import java.util.Date;
  **/
 public class ReportCustomComponentDto extends PageDto implements Serializable {
 
+    public static final String QUERY_MODEL_SQL = "1";
+    public static final String QUERY_MODEL_JAVA = "2";
+
     private String componentType;
     private String componentId;
     private String javaScript;

+ 9 - 0
java110-db/src/main/java/com/java110/db/dao/IQueryServiceDAO.java

@@ -19,6 +19,15 @@ public interface IQueryServiceDAO {
      */
     public List<Map<String,Object>> executeSql(String sql,Object []params);
 
+    /**
+     * 防止sql注入 改造成直接用prepareStatement 预处理sql
+     *
+     * @param sql
+     * @param params
+     * @return
+     */
+    public List<Map<String, Object>> executeSql(String sql, Object[] params, List<String> columns);
+
     public int updateSql(String sql,Object[] params);
 
     /**

+ 20 - 7
java110-db/src/main/java/com/java110/db/dao/impl/QueryServiceDAOImpl.java

@@ -1,20 +1,16 @@
 package com.java110.db.dao.impl;
 
-import com.java110.utils.util.StringUtil;
 import com.java110.core.base.dao.BaseServiceDao;
+import com.java110.db.dao.IQueryServiceDAO;
 import com.java110.entity.order.ServiceBusiness;
 import com.java110.entity.service.ServiceSql;
-import com.java110.db.dao.IQueryServiceDAO;
+import com.java110.utils.util.StringUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
+import java.sql.*;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -39,6 +35,18 @@ public class QueryServiceDAOImpl extends BaseServiceDao implements IQueryService
      */
     @Override
     public List<Map<String, Object>> executeSql(String sql, Object[] params) {
+        return executeSql(sql, params, null);
+    }
+
+    /**
+     * 防止sql注入 改造成直接用prepareStatement 预处理sql
+     *
+     * @param sql
+     * @param params
+     * @return
+     */
+    @Override
+    public List<Map<String, Object>> executeSql(String sql, Object[] params, List<String> columns) {
         logger.debug("----【queryServiceDAOImpl.executeSql】入参 : " + sql + " params= " + params);
         Connection conn = null;
         ResultSet rs = null;
@@ -55,6 +63,11 @@ public class QueryServiceDAOImpl extends BaseServiceDao implements IQueryService
             rs = ps.executeQuery();
             //精髓的地方就在这里,类ResultSet有getMetaData()会返回数据的列和对应的值的信息,然后我们将列名和对应的值作为map的键值存入map对象之中...
             ResultSetMetaData rsmd = rs.getMetaData();
+            if (columns != null) {
+                for (int i = 1; i < rsmd.getColumnCount(); ++i) {
+                    columns.add(rsmd.getColumnLabel(i));
+                }
+            }
             while (rs.next()) {
                 Map<String, Object> map = new HashMap<String, Object>();
                 for (int i = 0; i < rsmd.getColumnCount(); i++) {

+ 8 - 2
java110-db/src/main/resources/mapper/report/ReportCustomComponentRelV1ServiceDaoImplMapper.xml

@@ -19,14 +19,17 @@
     <select id="getReportCustomComponentRelInfo" parameterType="Map" resultType="Map">
         select t.rel_id,t.rel_id relId,t.component_id,t.component_id componentId,t.status_cd,t.status_cd
         statusCd,t.custom_id,t.custom_id customId,t.seq,cc.`name` componentName,t.create_time createTime,
-        cc.component_type componentType,cc.java_script javaScript,cc.component_group
-        componentGroup,cc.query_model queryModel,cc.component_sql componentSql
+        cc.component_type componentType,cc.component_group
+        componentGroup,cc.query_model queryModel
         from report_custom_component_rel t
         left join report_custom_component cc on t.component_id = cc.component_id and cc.status_cd = '0'
         where 1 =1
         <if test="relId !=null and relId != ''">
             and t.rel_id= #{relId}
         </if>
+        <if test="componentType !=null and componentType != ''">
+            and t.component_type= #{componentType}
+        </if>
         <if test="componentId !=null and componentId != ''">
             and t.component_id= #{componentId}
         </if>
@@ -77,6 +80,9 @@
         <if test="relId !=null and relId != ''">
             and t.rel_id= #{relId}
         </if>
+        <if test="componentType !=null and componentType != ''">
+            and t.component_type= #{componentType}
+        </if>
         <if test="componentId !=null and componentId != ''">
             and t.component_id= #{componentId}
         </if>

+ 13 - 0
java110-service/src/main/java/com/java110/service/smo/IQueryServiceSMO.java

@@ -1,5 +1,7 @@
 package com.java110.service.smo;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.java110.utils.exception.BusinessException;
 import com.java110.service.context.DataQuery;
 import org.springframework.http.ResponseEntity;
@@ -35,4 +37,15 @@ public interface IQueryServiceSMO {
      * @throws BusinessException
      */
     public ResponseEntity<String> fallBack(String fallBackInfo) throws BusinessException;
+
+    /**
+     * 执行查询sql
+     * @param param
+     * @param sql
+     * @return {
+     *     th:[],
+     *     td:[{}]
+     * }
+     */
+    JSONObject execQuerySql(JSONObject param, String sql) throws BusinessException;
 }

+ 54 - 1
java110-service/src/main/java/com/java110/service/smo/impl/QueryServiceSMOImpl.java

@@ -136,6 +136,7 @@ public class QueryServiceSMOImpl extends LoggerEngine implements IQueryServiceSM
 
     }
 
+
     /**
      * {"PARAM:"{
      * "param1": "$.a.#A#Object",
@@ -340,6 +341,59 @@ public class QueryServiceSMOImpl extends LoggerEngine implements IQueryServiceSM
         }
     }
 
+    @Override
+    public JSONObject execQuerySql(JSONObject params, String currentSql) throws BusinessException {
+        List<Map<String, Object>> results = null;
+        List<String> columns = new ArrayList<>();
+        try {
+            List<Object> currentParams = new ArrayList<Object>();
+            //处理 if 判断
+            logger.debug("dealSqlIf开始处理sql中的<if>节点 " + currentSql + " 入参:" + params.toJSONString());
+            currentSql = dealSqlIf(currentSql, params);
+            logger.debug("dealSqlIf处理完成sql中的<if>节点 " + currentSql + " 入参:" + params.toJSONString());
+            String[] sqls = currentSql.split("#");
+            String currentSqlNew = "";
+            for (int sqlIndex = 0; sqlIndex < sqls.length; sqlIndex++) {
+                if (sqlIndex % 2 == 0) {
+                    currentSqlNew += sqls[sqlIndex];
+                    continue;
+                }
+                currentSqlNew += "?";
+                Object param = params.getString(sqls[sqlIndex]);
+                if (params.get(sqls[sqlIndex]) instanceof Integer) {
+                    param = params.getInteger(sqls[sqlIndex]);
+                }
+                //这里对 page 和 rows 特殊处理 ,目前没有想到其他的办法
+                if (StringUtils.isNumeric(param.toString()) && "page,rows,row".contains(sqls[sqlIndex])) {
+                    param = Integer.parseInt(param.toString());
+                }
+                currentParams.add(param);
+            }
+            results = queryServiceDAOImpl.executeSql(currentSqlNew, currentParams.toArray(), columns);
+        } catch (Exception e) {
+            logger.error("解析sql 异常", e);
+            throw new BusinessException("1999", e.getLocalizedMessage());
+        }
+        JSONArray data = null;
+        if (results == null || results.size() < 1) {
+            data = new JSONArray();
+        } else {
+            data = JSONArray.parseArray(JSONArray.toJSONString(results));
+        }
+        JSONArray th = null;
+        if (columns.size() < 1) {
+            th = new JSONArray();
+        } else {
+            th = JSONArray.parseArray(JSONArray.toJSONString(columns));
+        }
+
+
+        JSONObject paramOut = new JSONObject();
+        paramOut.put("th", th);
+        paramOut.put("td", data);
+        return paramOut;
+    }
+
     /**
      * 处理SQL语句
      *
@@ -357,7 +411,6 @@ public class QueryServiceSMOImpl extends LoggerEngine implements IQueryServiceSM
         if (!oldSql.contains("<if")) {
             return oldSql;
         }
-
         String[] oSqls = oldSql.split("</if>");
         for (String oSql : oSqls) {
             logger.debug("处理if 节点,当前处理的oSql=" + oSql + "总的oSqls = " + oSqls);

+ 116 - 0
service-report/src/main/java/com/java110/report/cmd/reportCustomComponent/ListReportCustomComponentDataCmd.java

@@ -0,0 +1,116 @@
+/*
+ * Copyright 2017-2020 吴学文 and java110 team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.java110.report.cmd.reportCustomComponent;
+
+import com.alibaba.fastjson.JSONObject;
+import com.java110.core.annotation.Java110Cmd;
+import com.java110.core.context.ICmdDataFlowContext;
+import com.java110.core.event.cmd.AbstractServiceCmdListener;
+import com.java110.core.event.cmd.CmdEvent;
+import com.java110.dto.PageDto;
+import com.java110.dto.reportCustomComponent.ReportCustomComponentDto;
+import com.java110.intf.report.IReportCustomComponentV1InnerServiceSMO;
+import com.java110.service.smo.IQueryServiceSMO;
+import com.java110.utils.exception.CmdException;
+import com.java110.utils.util.Assert;
+import com.java110.vo.ResultVo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import java.util.List;
+
+
+/**
+ * 类表述:查询
+ * 服务编码:reportCustomComponent.listReportCustomComponentData
+ * 请求路劲:/app/reportCustomComponent.listReportCustomComponentData
+ * add by 吴学文 at 2021-11-09 13:18:41 mail: 928255095@qq.com
+ * open source address: https://gitee.com/wuxw7/MicroCommunity
+ * 官网:http://www.homecommunity.cn
+ * 温馨提示:如果您对此文件进行修改 请不要删除原有作者及注释信息,请补充您的 修改的原因以及联系邮箱如下
+ * // modify by 张三 at 2021-09-12 第10行在某种场景下存在某种bug 需要修复,注释10至20行 加入 20行至30行
+ */
+@Java110Cmd(serviceCode = "reportCustomComponent.listReportCustomComponentData")
+public class ListReportCustomComponentDataCmd extends AbstractServiceCmdListener {
+
+    private static Logger logger = LoggerFactory.getLogger(ListReportCustomComponentDataCmd.class);
+    @Autowired
+    private IReportCustomComponentV1InnerServiceSMO reportCustomComponentV1InnerServiceSMOImpl;
+
+    @Autowired
+    private IQueryServiceSMO queryServiceSMOImpl;
+
+    @Override
+    public void validate(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) {
+        super.validatePageInfo(reqJson);
+        Assert.hasKeyAndValue(reqJson, "componentId", "未包含组件ID");
+    }
+
+    @Override
+    public void doCmd(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) throws CmdException {
+
+        //查询组件是否存在
+        ReportCustomComponentDto reportCustomComponentDto = new ReportCustomComponentDto();
+        reportCustomComponentDto.setComponentId(reqJson.getString("componentId"));
+        List<ReportCustomComponentDto> reportCustomComponentDtos = reportCustomComponentV1InnerServiceSMOImpl.queryReportCustomComponents(reportCustomComponentDto);
+        Assert.listOnlyOne(reportCustomComponentDtos, "组件不存在,请联系开发人员");
+
+        reportCustomComponentDto = reportCustomComponentDtos.get(0);
+
+        if (ReportCustomComponentDto.QUERY_MODEL_SQL.equals(reportCustomComponentDto.getQueryModel())) {
+            doDealSql(reqJson, reportCustomComponentDto, cmdDataFlowContext);
+        } else if (ReportCustomComponentDto.QUERY_MODEL_JAVA.equals(reportCustomComponentDto.getQueryModel())) {
+            doDealJava(reqJson, reportCustomComponentDto, cmdDataFlowContext);
+        } else {
+            throw new CmdException("组件实现方式不支持,请联系开发人员");
+        }
+    }
+
+    private void doDealJava(JSONObject reqJson, ReportCustomComponentDto reportCustomComponentDto, ICmdDataFlowContext cmdDataFlowContext) {
+
+
+    }
+
+    private void doDealSql(JSONObject reqJson, ReportCustomComponentDto reportCustomComponentDto, ICmdDataFlowContext cmdDataFlowContext) {
+        //校验是否传了 分页信息
+        String sql = reportCustomComponentDto.getComponentSql();
+        long total = reqJson.getIntValue("row");
+        if (sql.trim().contains("test=\"count")) { // 如果包含 count(1) 求总数
+            JSONObject reqJsonCount = new JSONObject();
+            for (String key : reqJson.keySet()) {
+                if ("row".equals(key) || "page".equals(key)) {
+                    continue;
+                }
+                reqJsonCount.put(key, reqJson.get(key));
+            }
+            reqJsonCount.put("count", "1");
+            JSONObject data = queryServiceSMOImpl.execQuerySql(reqJsonCount, sql);
+            total = data.getJSONArray("data").getJSONObject(0).getIntValue("total");
+        }
+        reqJson.put("count", "0");
+        int page = reqJson.getInteger("page");
+        if (page != PageDto.DEFAULT_PAGE) {
+            reqJson.put("page", (page - 1) * reqJson.getIntValue("row"));
+        }
+        JSONObject data = queryServiceSMOImpl.execQuerySql(reqJson, sql);
+        ResultVo resultVo = new ResultVo((int) Math.ceil((double) total / (double) reqJson.getInteger("row")), total, data);
+        ResponseEntity<String> responseEntity = new ResponseEntity<String>(resultVo.toString(), HttpStatus.OK);
+        cmdDataFlowContext.setResponseEntity(responseEntity);
+    }
+}