Spring Boot生产环境无法加载resources下的Google API令牌JSON文件
问题描述
Spring Boot项目中,src/main/resources目录下存放着Google API令牌JSON文件,本地debug模式运行完全正常,但执行java -jar myapp.jar启动打包后的应用时,出现如下错误:
Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [google.service.GoogleDocService]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: no JSON input found at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-5.3.23.jar!/:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1232) ~[spring-beans-5.3.23.jar!/:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.23.jar!/:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar!/:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar!/:5.3.23] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar!/:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar!/:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.23.jar!/:5.3.23] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.23.jar!/:5.3.23] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.23.jar!/:5.3.23] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.23.jar!/:5.3.23] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.5.jar!/:2.7.5] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.5.jar!/:2.7.5] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.5.jar!/:2.7.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.5.jar!/:2.7.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.5.jar!/:2.7.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.5.jar!/:2.7.5] at palexy.deployment.DeploymentApplication.main(DeploymentApplication.java:13) ~[classes!/:0.0.1-SNAPSHOT] at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:578) ~[na:na] at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[deployment-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[deployment-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[deployment-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[deployment-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [google.service.GoogleDocService]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: no JSON input found at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:224) ~[spring-beans-5.3.23.jar!/:5.3.23] at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87) ~[spring-beans-5.3.23.jar!/:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1326) ~[spring-beans-5.3.23.jar!/:5.3.23] ... 23 common frames omitted
相关配置
- application.properties:
app.credentials-oauth2-file-path=/credentials-oauth2.json
- 已修改pom.xml的build配置,添加resources节点包含JSON文件,但问题依旧:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.json</include> </includes> </resource> </resources> </build>
解决方案
1. 修正资源加载方式(核心问题)
打包成jar后,resources目录下的文件会被嵌入jar包中,无法通过磁盘文件路径(如new File())直接读取,必须改用Spring的类路径资源加载方式:
方式一:注入ResourceLoader加载
import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Service; import java.io.InputStream; @Service public class GoogleDocService { private final ResourceLoader resourceLoader; // 构造注入ResourceLoader public GoogleDocService(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } private void loadCredentials() throws Exception { // 加载类路径下的JSON文件 Resource resource = resourceLoader.getResource("classpath:credentials-oauth2.json"); try (InputStream inputStream = resource.getInputStream()) { // 初始化Google凭证逻辑 // GoogleCredentials credentials = GoogleCredentials.fromStream(inputStream); } } }
方式二:直接注入Resource
修改application.properties路径为classpath:credentials-oauth2.json(或去掉开头的/),然后直接注入Resource:
import org.springframework.core.io.Resource; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.InputStream; @Service public class GoogleDocService { private final Resource credentialsResource; public GoogleDocService(@Value("${app.credentials-oauth2-file-path}") Resource credentialsResource) { this.credentialsResource = credentialsResource; } private void loadCredentials() throws Exception { try (InputStream inputStream = credentialsResource.getInputStream()) { // 初始化Google凭证逻辑 } } }
2. 确认JSON文件已被打包进jar
执行命令jar tf myapp.jar,查看输出中是否包含credentials-oauth2.json。如果没有:
- 检查JSON文件是否确实在
src/main/resources根目录下 - 确认pom.xml的resources配置没有被其他exclude规则覆盖
3. 避免在Bean构造器中加载资源
错误栈显示异常发生在Bean构造阶段,建议改用@PostConstruct注解延迟初始化逻辑,更符合Spring生命周期:
import javax.annotation.PostConstruct; import org.springframework.core.io.Resource; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.InputStream; @Service public class GoogleDocService { private final Resource credentialsResource; private Object credentials; // 替换为实际的Google凭证类型 public GoogleDocService(@Value("${app.credentials-oauth2-file-path}") Resource credentialsResource) { this.credentialsResource = credentialsResource; } @PostConstruct public void initCredentials() throws Exception { try (InputStream inputStream = credentialsResource.getInputStream()) { credentials = GoogleCredentials.fromStream(inputStream); } } }
内容的提问来源于stack exchange,提问作者MinhSu - Justin
相关产品推荐
相关产品推荐

