Spring Boot Loader资源找不到:resourceLoader实例化问题求助
解决Spring Boot打包后运行Jar出现的ResourceLoader空指针异常
我看你遇到的NullPointerException确实是因为静态变量resourceLoader没有被实例化导致的——在setConfig方法调用它的getResource方法时,它还处于null状态。结合你的Spring Boot项目场景,给你两个可行的解决方案:
方案1:利用Spring Boot依赖注入管理ResourceLoader
既然你用了Spring Boot的打包插件,最规范的方式是让Spring来管理资源加载,把你的类变成Spring组件:
步骤1:创建标准的Spring Boot启动类
替换原来的main方法入口,用@SpringBootApplication标记启动类,通过Spring上下文获取Bean:
package com.ryankshah.pdp.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @SpringBootApplication public class PdpServerApplication { public static void main(String[] args) { // 启动Spring上下文 ApplicationContext context = SpringApplication.run(PdpServerApplication.class, args); // 获取PDP实例并初始化 PDP server = context.getBean(PDP.class); try { server.initialize(args); while(true) { Socket socket = server.getSocket().accept(); new ClientThread(socket, server).start(); } } catch (IOException e) { e.printStackTrace(); } } }
步骤2:改造PDP类为Spring组件
通过构造注入的方式获取ResourceLoader,去掉静态变量:
package com.ryankshah.pdp.server; import org.apache.commons.io.IOUtils; import org.json.JSONObject; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Component; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; @Component public class PDP { protected ServerSocket serverSocket; protected Resource configFile; protected PDPEngine pdpEngine; // 用实例变量替代静态变量,由Spring注入 private final ResourceLoader resourceLoader; // 构造方法注入ResourceLoader public PDP(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } // 初始化方法,处理端口和配置参数 public void initialize(String[] args) throws IOException { final int PORT = Integer.parseInt(args[0]); final String CONFIG = args[1]; setConfig(CONFIG); pdpEngine = new PDPEngine(configFile); System.out.println("Starting PDP Server..."); this.serverSocket = new ServerSocket(PORT); System.out.println("PDP Server Started!"); } public ServerSocket getSocket() { return serverSocket; } private void setConfig(String model) { switch(model) { case "RBIBA": configFile = resourceLoader.getResource("classpath:config/rbiba_pdp_conf.xml"); break; case "BLP": configFile = resourceLoader.getResource("classpath:config/blp_pdp_conf.xml"); break; case "CWall": configFile = resourceLoader.getResource("classpath:config/cwall_pdp_conf.xml"); break; case "RBIBA_BLP": configFile = resourceLoader.getResource("classpath:config/rbiba_blp_pdp_conf.xml"); break; case "RBIBA_CWall": configFile = resourceLoader.getResource("classpath:config/rbiba_cwall_pdp_conf.xml"); break; case "BLP_CWall": configFile = resourceLoader.getResource("classpath:config/blp_cwall_pdp_conf.xml"); break; case "RBIBA_BLP_CWall": configFile = resourceLoader.getResource("classpath:config/rbiba_blp_cwall_pdp_conf.xml"); break; default: throw new IllegalArgumentException("Unsupported config model: " + model); } } // 把静态方法改为实例方法,依赖实例化的resourceLoader public JSONObject readReport(String deviceID) throws IOException { Resource r = resourceLoader.getResource("classpath:reports/"+deviceID+".json"); return new JSONObject(IOUtils.toString(r.getInputStream(), StandardCharsets.UTF_8)); } }
方案2:手动实例化ResourceLoader(快速修复)
如果不想改造Spring Boot组件,也可以直接在PDP类的静态块中手动初始化ResourceLoader:
package com.ryankshah.pdp.server; // 导入DefaultResourceLoader import org.springframework.core.io.DefaultResourceLoader; // ...其他导入 public class PDP { // ...其他变量 protected static ResourceLoader resourceLoader; // 静态块初始化resourceLoader static { resourceLoader = new DefaultResourceLoader(); } // ...原有方法不变 }
这种方式不需要改动项目结构,能快速解决空指针问题,但缺点是无法利用Spring上下文的资源加载特性,适合快速验证场景。
额外优化建议
- 调整pom.xml打包配置:你的pom里同时配置了
maven-jar-plugin和spring-boot-maven-plugin,两者功能重叠会导致冲突,建议删除maven-jar-plugin,并指定Spring Boot启动类:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.1</version> <configuration> <source>11</source> <target>11</target> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.1.5.RELEASE</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> <configuration> <!-- 如果用方案1,这里改成新的启动类 --> <mainClass>com.ryankshah.pdp.server.PdpServerApplication</mainClass> <!-- 如果用方案2,保留原来的主类 --> <!-- <mainClass>com.ryankshah.pdp.server.PDP</mainClass> --> </configuration> </plugin> </plugins> </build>
- 检查资源路径:确保
config和reports目录放在src/main/resources下,这样打包后资源会被放到classpath中,ResourceLoader才能正确找到。
内容的提问来源于stack exchange,提问作者rshah
相关产品推荐
相关产品推荐

