You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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上下文的资源加载特性,适合快速验证场景。

额外优化建议

  1. 调整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>
  1. 检查资源路径:确保config和reports目录放在src/main/resources下,这样打包后资源会被放到classpath中,ResourceLoader才能正确找到。

内容的提问来源于stack exchange,提问作者rshah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:26:25