启动应用程序时从 json 加载值

发布于 2025-01-16 20:16:35 字数 3363 浏览 2 评论 0原文

我想在 Spring Boot 应用程序启动时从 json 文件加载值。

我的配置文件代码如下:

@Configuration
@Getter
public class FedexAPIConfig {

    private final static String JSON_FILE = "/static/config/fedex-api-credentials.json";
    private final boolean IS_PRODUCTION = false;
    private FedexAPICred apiCredentials;

    public FedexAPIConfig() {
        try (InputStream in = getClass().getResourceAsStream(JSON_FILE);
                BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
            JSONObject json = new JSONObject();

            // this.apiCredentials = new JSONObject(new JSONTokener(reader));
            
            if (IS_PRODUCTION) {
                json = new JSONObject(new JSONTokener(reader)).getJSONObject("production");
            } else {
                json = new JSONObject(new JSONTokener(reader)).getJSONObject("test");
            }
            System.out.println(json.toString());
            this.apiCredentials = FedexAPICred.builder()
                    .url(json.optString("url"))
                    .apiKey(json.optString("api_key"))
                    .secretKey(json.optString("secret_key"))
                    .build();
        } catch (FileNotFoundException fnfe) {
            fnfe.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这样,当应用程序启动时,值将成功打印在控制台上。启动控制台日志

当我尝试从其他普通类调用这个值时,如下所示:,它什么也没带来,只是抛出 NullPointerException...我的错误是什么,我该怎么办做?

public class FedexOAuthTokenManager extends OAuthToken {
    private static final String VALIDATE_TOKEN_URL = "/oauth/token";
    private static final String GRANT_TYPE_CLIENT = "client_credentials";
    private static final String GRANT_TYPE_CSP = "csp_credentials";

    @Autowired
    private FedexAPIConfig fedexApiConfig;

    @Autowired
    private Token token;

    @Override
    public void validateToken() {
        // This is the part where "fedexApiConfig" is null.
        FedexAPICred fedexApiCred = fedexApiConfig.getApiCredentials();
        Response response = null;
        try {
            RequestBody body = new FormBody.Builder()
                    .add("grant_type", GRANT_TYPE_CLIENT)
                    .add("client_id", fedexApiCred.getApiKey())
                    .add("client_secret", fedexApiCred.getSecretKey())
                    .build();

            response = new HttpClient().post(fedexApiCred.getUrl() + VALIDATE_TOKEN_URL, body);
            
            if (response.code() == 200) {
                JSONObject json = new JSONObject(response.body().string());

                token.setAccessToken(json.optString("access_token"));
                token.setTokenType(json.optString("token_type"));
                token.setExpiredIn(json.optInt("expires_in"));
                token.setExpiredDateTime(LocalDateTime.now().plusSeconds(json.optInt("expires_in")));
                token.setScope(json.optString("scope"));

            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

fedexApiConfg 为空,即使我在调用之前自动连接它。 这个 FedexOAuthTokenManager 是通过 new FedexOAuthTokenManager() 从其他 @Component 类调用的

I want to load the values from json file upon the Spring Boot Application is started.

My code for the Configuration File is like the below:

@Configuration
@Getter
public class FedexAPIConfig {

    private final static String JSON_FILE = "/static/config/fedex-api-credentials.json";
    private final boolean IS_PRODUCTION = false;
    private FedexAPICred apiCredentials;

    public FedexAPIConfig() {
        try (InputStream in = getClass().getResourceAsStream(JSON_FILE);
                BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
            JSONObject json = new JSONObject();

            // this.apiCredentials = new JSONObject(new JSONTokener(reader));
            
            if (IS_PRODUCTION) {
                json = new JSONObject(new JSONTokener(reader)).getJSONObject("production");
            } else {
                json = new JSONObject(new JSONTokener(reader)).getJSONObject("test");
            }
            System.out.println(json.toString());
            this.apiCredentials = FedexAPICred.builder()
                    .url(json.optString("url"))
                    .apiKey(json.optString("api_key"))
                    .secretKey(json.optString("secret_key"))
                    .build();
        } catch (FileNotFoundException fnfe) {
            fnfe.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

and with this, when the application is in progress of startup, values are successfully printed on the console.Startup console log

When I tried to call this value from other ordinary class, like the below:, it brings nothing but just throws NullPointerException... What are my faults and what shall I do?

public class FedexOAuthTokenManager extends OAuthToken {
    private static final String VALIDATE_TOKEN_URL = "/oauth/token";
    private static final String GRANT_TYPE_CLIENT = "client_credentials";
    private static final String GRANT_TYPE_CSP = "csp_credentials";

    @Autowired
    private FedexAPIConfig fedexApiConfig;

    @Autowired
    private Token token;

    @Override
    public void validateToken() {
        // This is the part where "fedexApiConfig" is null.
        FedexAPICred fedexApiCred = fedexApiConfig.getApiCredentials();
        Response response = null;
        try {
            RequestBody body = new FormBody.Builder()
                    .add("grant_type", GRANT_TYPE_CLIENT)
                    .add("client_id", fedexApiCred.getApiKey())
                    .add("client_secret", fedexApiCred.getSecretKey())
                    .build();

            response = new HttpClient().post(fedexApiCred.getUrl() + VALIDATE_TOKEN_URL, body);
            
            if (response.code() == 200) {
                JSONObject json = new JSONObject(response.body().string());

                token.setAccessToken(json.optString("access_token"));
                token.setTokenType(json.optString("token_type"));
                token.setExpiredIn(json.optInt("expires_in"));
                token.setExpiredDateTime(LocalDateTime.now().plusSeconds(json.optInt("expires_in")));
                token.setScope(json.optString("scope"));

            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

fedexApiConfg is null even though I autowired it in prior to call.
And this FedexOAuthTokenManager is called from other @Component class by new FedexOAuthTokenManager()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

緦唸λ蓇 2025-01-23 20:16:35

你有像下面这样尝试过吗?

第 1 步:创建一个如下所示的 Configuration 类

public class DemoConfig implements ApplicationListener<ApplicationPreparedEvent> {

    @Override
    public void onApplicationEvent(ApplicationPreparedEvent event) {
        
        //Load the values from the JSON file and populate the application 
        //properties dynamically 
        ConfigurableEnvironment environment = event.getApplicationContext().getEnvironment();
        Properties props = new Properties();
        props.put("spring.datasource.url", "<my value>");
        //Add more properties
        environment.getPropertySources().addFirst(new PropertiesPropertySource("myProps", props));

    }

要监听上下文事件,bean 应该实现 ApplicationListener 接口,该接口只有一个方法 onApplicationEvent()。ApplicationPreparedEvent 在应用程序生命周期的早期就被调用。 application

第2步:在src/main/resources/META-INF/spring.factories中自定义

org.springframework.context.ApplicationListener=com.example.demo.DemoConfig

第3步:spring boot中的@Value通常用于将配置值注入到spring boot中 应用。根据您的意愿访问属性。

    @Value("${spring.datasource.url}")
    private String valueFromJSon;

首先在本地计算机中尝试此示例,然后相应地修改您的更改。

请参阅 - https://www.baeldung.com/spring-value-annotation

Did you try like below?

Step 1: Create one Configuration class like below

public class DemoConfig implements ApplicationListener<ApplicationPreparedEvent> {

    @Override
    public void onApplicationEvent(ApplicationPreparedEvent event) {
        
        //Load the values from the JSON file and populate the application 
        //properties dynamically 
        ConfigurableEnvironment environment = event.getApplicationContext().getEnvironment();
        Properties props = new Properties();
        props.put("spring.datasource.url", "<my value>");
        //Add more properties
        environment.getPropertySources().addFirst(new PropertiesPropertySource("myProps", props));

    }

To listen to a context event, a bean should implement the ApplicationListener interface which has just one method onApplicationEvent().The ApplicationPreparedEvent is invoked very early in the lifecycle of the application

Step 2: Customize in src/main/resources/META-INF/spring.factories

org.springframework.context.ApplicationListener=com.example.demo.DemoConfig

Step 3: @Value in spring boot is commonly used to inject the configuration values into the spring boot application. Access the properties as per your wish.

    @Value("${spring.datasource.url}")
    private String valueFromJSon;

Try this sample first in your local machine and then modify your changes accordingly.

Refer - https://www.baeldung.com/spring-value-annotation

眼眸 2025-01-23 20:16:35

您可以用以下方式注释该方法:

@EventListener(ContextRefreshedEvent.class)

you can annotate the method with this:

@EventListener(ContextRefreshedEvent.class)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文