如何在API的SQL查询中使用getSites()返回的字符串值
解决方法:调用getSites()填充SQL查询并修复潜在问题
咱们一步步来解决你的问题,同时顺便修复代码里的几个小隐患:
1. 调用getSites()获取站点列表
因为getSites()是ReadCSVFile类的静态方法,你可以直接在GFNSService的getRigStatistics方法里调用它。首先要确保你已经导入了ReadCSVFile类(如果它不在com.gds.service包下的话):
// 替换成ReadCSVFile实际所在的包路径 import your.package.ReadCSVFile;
然后在构建SQL查询前,获取站点字符串:
@GET @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @Path("/getRigStatistics") public List getRigStatistics(@HeaderParam("authorization") String authString) { logger.info("API method getRigStatistics invoked."); if (!isAppDynamicsUserAuthenticatedRigStatistics(authString)) { throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).build()); } List rigList = new ArrayList<>(); // 关键:调用getSites()获取CSV中的站点列表 String sites = ReadCSVFile.getSites(); // 接下来构建SQL查询...
2. 安全构建SQL查询(重点!)
你原来的SQL拼接方式有两个问题:
- 语法错误:
Site_Name是字符串类型,IN子句里的每个值需要用单引号包裹 - 严重的SQL注入风险:如果CSV里的站点名称包含特殊字符(比如
'),会导致SQL语法错误,甚至被恶意利用
推荐方案:使用PreparedStatement(完全避免注入)
这是最安全的做法,动态生成参数占位符:
// 将逗号分隔的字符串转为站点列表 List<String> siteList = Arrays.asList(sites.split(",")); // 构建带占位符的SQL语句 StringBuilder queryBuilder = new StringBuilder("SELECT NodeID, Site_Name FROM csproperties WHERE Site_Name IN ("); for (int i = 0; i < siteList.size(); i++) { if (i > 0) { queryBuilder.append(", "); } queryBuilder.append("?"); // 占位符 } queryBuilder.append(") ORDER BY Site_Name"); // 假设你已经获取了数据库连接connection PreparedStatement pstmt = connection.prepareStatement(queryBuilder.toString()); // 给每个占位符设置参数 for (int i = 0; i < siteList.size(); i++) { pstmt.setString(i + 1, siteList.get(i).trim()); // 去除站点名称前后的空格 } // 执行查询并处理结果 ResultSet rs = pstmt.executeQuery(); // ... 这里写你的结果映射代码,把rs的数据转成rigList
备选方案:手动拼接(仅当确定站点内容绝对安全时使用)
如果你能保证CSV里的站点名称不会包含单引号等特殊字符,可以手动给每个值加单引号:
// 给每个站点名称添加单引号,并用逗号分隔 String formattedSites = Arrays.stream(sites.split(",")) .map(site -> "'" + site.trim() + "'") .collect(Collectors.joining(",")); // 构建最终的SQL查询 String query = "SELECT NodeID, Site_Name FROM csproperties WHERE Site_Name IN (" + formattedSites + ") ORDER BY Site_Name";
3. 修复getSites()方法的潜在bug
你的getSites()方法有个问题:如果CSV文件为空,sites.substring(0, sites.length() - 1)会抛出StringIndexOutOfBoundsException。另外,用字符串拼接效率很低,建议改成StringBuilder:
public class ReadCSVFile { public static String getSites() { String csvFile = "C:\\data.csv"; BufferedReader br = null; String line = ""; StringBuilder sitesBuilder = new StringBuilder(); // 用StringBuilder更高效 try { br = new BufferedReader(new FileReader(csvFile)); while ((line = br.readLine()) != null) { String trimmedLine = line.trim(); if (trimmedLine.isEmpty()) { continue; // 跳过空行 } if (sitesBuilder.length() > 0) { sitesBuilder.append(","); } sitesBuilder.append(trimmedLine); } } catch (FileNotFoundException e) { e.printStackTrace(); return ""; // 或者抛出自定义异常,让上层处理 } catch (IOException e) { e.printStackTrace(); return ""; } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } return sitesBuilder.toString(); } }
这样既避免了空文件的异常,又提升了字符串拼接的效率。
内容的提问来源于stack exchange,提问作者Manu
相关产品推荐
相关产品推荐

