ConnectDB函数中getResourceAsStream()获取init.xml输入流返回null求助
分析与解决:数据库连接函数中
input始终为null的问题 我来帮你拆解下这个问题,你遇到的input一直是null的核心原因是类加载器加载资源的逻辑和你当前的文件路径不匹配,咱们一步步理顺:
核心问题原因
你现在的代码逻辑是先创建了一个本地绝对路径的File对象\\XFiles\\Conf\\init.xml,然后只取文件名nom,再通过类加载器的getResourceAsStream(nom)去加载——但类加载器的这个方法是从项目的classpath根目录查找资源的,你的xml文件在本地绝对路径,根本不在classpath里,自然找不到,所以input就成了null。
另外你代码里还有几个潜在的小问题,顺便一起提下:
- 静态变量
conn没有初始化,直接判断if(conn==null)会有风险; - 密码加密后得到
mdpCrypte,但实际连接还是用了原密码password,等于加密逻辑白写了; - 硬编码了驱动类
com.microsoft.sqlserver.jdbc.SQLServerDriver,JDBC4.0+之后不需要手动调用Class.forName,驱动会自动注册; - 异常处理太笼统,直接catch所有
Exception,不利于排查具体问题(比如文件找不到、XML解析错误、数据库连接失败等); - 资源没有关闭,
InputStream用完后没关闭会导致资源泄漏。
针对性解决方法
方法1:把XML放到classpath下(推荐)
如果你的项目是Maven/Gradle结构,把init.xml放到src/main/resources目录(或者src/main/resources/Conf子目录),然后直接用类加载器加载:
// 如果放在resources根目录 InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("init.xml"); // 如果放在resources/Conf目录下 InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("Conf/init.xml");
这样类加载器就能正确找到资源了。
方法2:直接加载本地绝对路径的文件
如果XML确实必须放在本地\\XFiles\\Conf\\init.xml路径下,那不要用类加载器,直接用FileInputStream加载:
// 注意Windows路径的反斜杠要转义,或者用正斜杠更通用 File fichier = new File("\\\\XFiles\\\\Conf\\\\init.xml"); // 或者用正斜杠:new File("/XFiles/Conf/init.xml") InputStream input = new FileInputStream(fichier);
优化后的完整代码示例
结合上面的修复点,给你整理了一份更健壮的代码:
public static Connection ConnectDB() { Connection conn = null; // 用正斜杠兼容多系统,或者根据实际路径调整 File fichier = new File("/XFiles/Conf/init.xml"); // try-with-resources自动关闭输入流,避免资源泄漏 try (InputStream input = new FileInputStream(fichier)) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new InputSource(input)); XPath xpath = XPathFactory.newInstance().newXPath(); String url = (String) xpath.compile("//init//jdbc//url").evaluate(document, XPathConstants.STRING); String driver = (String) xpath.compile("//init//jdbc//driver").evaluate(document, XPathConstants.STRING); String username = (String) xpath.compile("//init//jdbc//username").evaluate(document, XPathConstants.STRING); String password = (String) xpath.compile("//init//jdbc//password").evaluate(document, XPathConstants.STRING); // 如果需要使用加密后的密码,替换下面的password为mdpCrypte Cryptage cipherUtil = new Cryptage(); String mdpCrypte = cipherUtil.encrypt(password); // JDBC4.0+ 驱动会自动注册,可省略Class.forName(driver) conn = DriverManager.getConnection(url + "integratedSecurity=true;", username, password); logger.debug("Connexion Réussite"); } catch (FileNotFoundException e) { logger.error("XML配置文件未找到,请检查路径是否正确", e); } catch (ParserConfigurationException | SAXException | IOException | SQLException e) { logger.error("数据库连接或XML解析失败", e); } return conn; }
内容的提问来源于stack exchange,提问作者harili
相关产品推荐
相关产品推荐

