SpringBoot中@Value无法读取数据库配置参数导致空值问题
SpringBoot中@Value无法读取数据库配置参数导致空值问题
我看了你遇到的问题,核心原因有几个,咱们一步步拆解解决:
问题根源分析
- 静态变量无法被Spring注入:你在启动类里把
url、user、password定义成了static字段,Spring的@Value注入是针对实例对象的,静态字段属于类级别,Spring不会为它注入值,所以这些变量一直是null。 - 容器初始化前调用业务逻辑:你在
SpringApplication.run()之前就调用了file_1.loadData(),这时候Spring容器还没初始化完成,所有的依赖注入(包括@Value)都还没执行,自然拿不到配置值。 - FileReaderUtility未被Spring管理:这个类没有加
@Component注解,Spring无法识别它为Bean,后续的@Autowired也无法正常注入它的实例。
解决方案步骤
1. 修复启动类的注入问题
把静态变量改成实例变量,并且把加载数据的逻辑放到Spring容器初始化完成后执行,比如用@PostConstruct注解:
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) public class Sql2DataStructureApplication { @Value("${spring.datasource.url}") private String url; @Value("${spring.datasource.username}") private String user; @Value("${spring.datasource.password}") private String password; @Autowired private FileReaderUtility fileReaderUtility; public static void main(String[] args) { // 先启动Spring容器 SpringApplication.run(Sql2DataStructureApplication.class, args); } // 容器初始化完成后自动执行这个方法 @PostConstruct public void loadDataOnStartup() { try { fileReaderUtility.loadData(url, user, password); } catch (Exception ex) { ex.printStackTrace(); } } }
2. 把FileReaderUtility注册为Spring Bean
给这个类加上@Component注解,让Spring管理它的生命周期:
@Component public class FileReaderUtility { // 初始化你的数据结构 private List<String> sql_data_structure = new ArrayList<>(); public void loadData(String url,String user,String password) { String query = "select Name,UseCaseKey from RankedPickList_Stories_Master;"; try { System.out.println("url="+url); System.out.println("user="+user); System.out.println("password="+password); Connection conn = DriverManager.getConnection(url, user, password); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String columnValue1 = rs.getString("Name"); String columnValue2 = rs.getString("UseCaseKey"); String concatenatedValues = columnValue1 + " " + columnValue2; sql_data_structure.add(concatenatedValues); } System.out.println(sql_data_structure); // 记得关闭资源,最好用try-with-resources自动关闭 rs.close(); stmt.close(); conn.close(); } catch (SQLException ex) { System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode()); } } public Map<String,Object> getQueriedSqlData(){ Map<String, Object> response = new HashMap<>(); for(String line_l:sql_data_structure) { String value_1=line_l.substring(0,StringUtils.ordinalIndexOf(line_l, " ", 1)); String value_2=line_l.substring(StringUtils.ordinalIndexOf(line_l, " ", 1)+1,StringUtils.ordinalIndexOf(line_l, " ", 2)); response.put(value_1, value_2); } return response; } }
3. 清理pom.xml的重复依赖
你同时引入了mysql-connector-java和mysql-connector-j,这两个是同一个驱动的不同版本命名,保留一个即可,推荐保留mysql-connector-j(SpringBoot 2.7+官方推荐):
<dependencies> <!-- 其他依赖不变 --> <!-- 移除旧的mysql-connector-java --> <!-- <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.24</version> </dependency> --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> </dependencies>
进阶优化:使用Spring JdbcTemplate代替原生JDBC
原生JDBC需要手动管理连接、关闭资源,容易出错,推荐用Spring提供的JdbcTemplate,它会自动帮你处理这些细节:
- 修改DataConfig,添加JdbcTemplate的Bean:
@Configuration public class DataConfig { @Value("${spring.datasource.username}") private String userName; @Value("${spring.datasource.password}") private String password; @Value("${spring.datasource.url}") private String url; @Value("${spring.datasource.driver-class-name}") private String driverClassName; @Bean DataSource dataSource() { return DataSourceBuilder .create() .username(userName) .password(password) .url(url) .driverClassName(driverClassName) .build(); } @Bean JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } }
- 修改FileReaderUtility,注入JdbcTemplate:
@Component public class FileReaderUtility { private List<String> sql_data_structure = new ArrayList<>(); private final JdbcTemplate jdbcTemplate; // 构造注入(Spring推荐的方式) public FileReaderUtility(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void loadData() { String query = "select Name,UseCaseKey from RankedPickList_Stories_Master;"; // 用JdbcTemplate查询,自动处理连接和资源 jdbcTemplate.query(query, rs -> { String columnValue1 = rs.getString("Name"); String columnValue2 = rs.getString("UseCaseKey"); String concatenatedValues = columnValue1 + " " + columnValue2; sql_data_structure.add(concatenatedValues); }); System.out.println(sql_data_structure); } // 启动类里的loadDataOnStartup改成调用无参的loadData() // public void loadDataOnStartup() { // try { // fileReaderUtility.loadData(); // } catch (Exception ex) { // ex.printStackTrace(); // } // } }
最后检查application.properties配置
确保你的配置文件里的参数正确,比如:
spring.datasource.url=jdbc:mysql://localhost:3306/your_database_name?useSSL=false&serverTimezone=UTC spring.datasource.username=your_db_user spring.datasource.password=your_db_password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
这样修改后,应该就能正常读取配置参数,加载数据库数据了。
备注:内容来源于stack exchange,提问作者Blesson Xavier
相关产品推荐
相关产品推荐

