关于使用ResourceBundle.getBundle(filename)

本文分享了在尝试使用JDBC连接PostgreSQL数据库时遇到的问题及解决方案。主要原因是未能正确读取本地配置文件db.properties。通过调整ResourceConfig类中获取资源束的方法解决了此问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


今天在做postgresql的jdbc连接碰到问题,数据库始终连接不上,根据报错信息发现是因为没有读取到本地配置文件db.properties的信息。

原读取db.properties方法

public class ResourceConfig {
	public static ResourceBundle getResourceBunder(String resouceName)
	{
		return ResourceBundle.getBundle(resouceName);
	}
}

虽然db.properties就放在classes下,但是无法读取到,经百度发现,应该这么写

public class ResourceConfig {
	public static ResourceBundle getResourceBunder(String resouceName)
	{
		Locale locale = Locale.getDefault();
		return ResourceBundle.getBundle(resouceName,locale);
	}
}




<think>好的,用户现在问的是Java中使用占位符的常用方法。之前他们问了关于MySQL根据主表字段关联不同表查询的问题,我给出了几种解决方案,包括动态SQL和程序层处理,比如Python的例子。现在用户转向Java,可能是在开发中遇到了参数化查询的需求,想要避免SQL注入,或者提高代码的可读性和维护性。 首先,我需要明确用户的问题范围。占位符在Java中通常出现在字符串格式化、日志记录、SQL预处理语句等场景。用户提到的是Java使用占位符,可能指的是这些不同的应用场景,但结合之前的MySQL问题,很可能他们关注的是SQL查询中的占位符,比如PreparedStatement的使用。不过,为了全面回答,我应该涵盖常见的几种情况,比如String.format(), MessageFormat,日志库如SLF4J的占位符,以及JDBC中的预处理语句。 接下来,我需要整理每种占位符的使用方法、语法和示例。比如,String.format()使用%s这样的格式符,而MessageFormat使用{0}这样的数字占位符。日志库比如Log4j或SLF4J使用{}作为占位符。在JDBC中,PreparedStatement使用问号?作为参数占位符。这些都是Java中常见的占位符类型。 然后,我需要考虑用户可能的深层需求。用户可能希望了解不同占位符的优缺点,以及适用场景。例如,String.format()适合简单的字符串替换,而MessageFormat支持更复杂的格式化和国际化。预处理语句的占位符主要用于防止SQL注入,提高安全性。日志占位符则有助于延迟字符串拼接,提升性能。 同时,用户可能想知道最佳实践,比如为什么推荐使用预处理语句而不是字符串拼接,或者为什么在日志中使用占位符而不是直接拼接字符串。需要解释这些占位符如何避免安全问题,提高代码效率,或者增强可读性。 还要注意用户可能的误区,比如在日志中误用字符串拼接导致不必要的性能损耗,或者在SQL中错误地拼接字符串导致注入漏洞。因此,在回答中强调正确使用占位符的重要性,并提供示例说明正确和错误的做法。 最后,总结各种占位符的使用场景,帮助用户根据具体需求选择合适的方法。确保回答结构清晰,分点列出,每种占位符都有示例代码,便于用户理解和应用。</think>在 Java 开发中,使用占位符是处理字符串格式化和参数化查询的重要方式,以下是 6 种典型场景的占位符使用详解: --- ### 一、基础字符串格式化(`String.format()`) **语法**:`%[参数索引$][格式类型]` **特点**:支持类型安全校验,可复用参数 ```java // 基础用法 String result = String.format("用户:%s | 年龄:%d | 余额:%.2f", "张三", 25, 1234.5678); // 带参数索引(复用第一个参数) String template = "%1$s 购买了 %2$d 件 %1$s 型号商品"; System.out.println(String.format(template, "手机", 3)); // 输出:手机 购买了 3 件 手机 型号商品 // 格式类型示例 String hex = String.format("十六进制:%#x", 255); // 0xff String date = String.format("时间:%tF %<tT", new Date()); // 2023-08-10 14:30:45 ``` --- ### 二、消息格式化(`MessageFormat`) **语法**:`{索引[,格式类型[,样式]]}` **优势**:支持复杂格式和国际化 ```java // 基础用法 MessageFormat.format("{0} 在 {1,time,short} 登录失败 {2} 次", "admin", new Date(), 3); // 格式类型扩展 Object[] params = {3500.5, "USD"}; String output = MessageFormat.format("金额:{0,number,currency}", params); // 输出:金额:$3,500.50 // 多语言场景(搭配资源文件使用ResourceBundle bundle = ResourceBundle.getBundle("messages", Locale.US); String pattern = bundle.getString("welcome.msg"); // Welcome, {0}! ``` --- ### 三、SQL 预处理(`PreparedStatement`) **语法**:`?` 占位符 **核心价值**:防止 SQL 注入,提升性能 ```java String sql = "SELECT * FROM users WHERE username = ? AND status = ?"; try (PreparedStatement pstmt = connection.prepareStatement(sql)) { pstmt.setString(1, "test_user"); // 自动处理特殊字符 pstmt.setInt(2, 1); // 类型安全校验 ResultSet rs = pstmt.executeQuery(); } // 批量操作示例 pstmt = conn.prepareStatement("INSERT INTO logs (content) VALUES (?)"); for (String log : logList) { pstmt.setString(1, log); pstmt.addBatch(); // 占位符支持批量重用 } pstmt.executeBatch(); ``` --- ### 四、日志框架占位符 #### SLF4J 规范 **语法**:`{}` + 参数顺序 ```java // 基础用法(避免字符串拼接开销) logger.debug("用户 {} 执行了 {} 操作,耗时 {}ms", userId, actionType, duration); // 异常日志标准写法 try { // ... } catch (Exception e) { logger.error("文件 {} 处理失败,原因:{}", fileName, e.getMessage(), e); } // 避免的常见错误(错误写法会立即拼接字符串) // 错误示例:logger.debug("当前值:" + value); // 即使不输出也会执行拼接 ``` --- ### 五、文本块增强(Java 15+) **语法**:`%[索引$]` 配合 `formatted()` 方法 ```java String jsonTemplate = """ { "user": "%s", "age": %d, "roles": [ "%s", "%s" ] } """.formatted("李四", 28, "admin", "operator"); // 支持链式调用 String html = """ <div class="%s"> %s </div> """.formatted(styleClass) .indent(4); ``` --- ### 六、模版引擎对比 | 方案 | 特点 | 适用场景 | |---------------|-----------------------------------|-------------------------| | **String.format** | 内建支持,简单快速 | 简单字符串组合 | | **MessageFormat** | 支持复杂格式和国际化 | 多语言消息模板 | | **PreparedStatement** | 数据库安全必备 | 所有 SQL 操作 | | **SLF4J** | 零成本占位符(延迟求值) | 日志输出 | | **StringTemplate** (JEP 430) | 类型安全模板(Java 21 预览) | 高安全性需求场景 | --- ### 最佳实践建议: 1. **防御性占位符**:对用户输入内容必须使用 `PreparedStatement` ```java // 危险写法(SQL注入漏洞) String badSql = "SELECT * FROM users WHERE id = " + userInput; // 正确写法 PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?"); pstmt.setString(1, userInput); ``` 2. **性能优化**:高频日志使用参数化写法 ```java // 优化前(产生临时字符串) if (logger.isDebugEnabled()) { logger.debug("ID:" + id + " Data:" + heavyToString()); } // 优化后(延迟求值) logger.debug("ID:{} Data:{}", id, this::heavyToString); ``` 3. **模版复用**:复杂模板建议提取为常量 ```java private static final String SQL_INSERT = """ INSERT INTO orders ( order_id, total_amount, create_time ) VALUES (?, ?, ?) """; ``` 通过合理选择占位符方案,可以显著提升代码安全性、可维护性和运行效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值