【问题标题】:Spring boot @Value annotation returning nullSpring boot @Value 注释返回 null
【发布时间】:2019-10-22 22:13:53
【问题描述】:

我有一个 java 类,如下所示,它正在创建一个带有连接和读取超时的休息模板,并且还创建一个重试模板,该模板在发生连接和读取超时时执行重试。我正在从 application.properties 文件中读取值,但由于某种原因,我得到了正在读取的值的空值。我不知道我能做些什么来解决这个问题。对此的任何建议将不胜感激。

public class Retry {

@Value("${read.Timeout.InMilliSeconds:-1}")
private Integer readTimeoutInMilliSeconds;

@Value("${connect.Timeout.InMilliSeconds:-1}")
private Integer connectTimeoutInMilliSeconds;

@Value("${backOff.Period.InMilliSeconds:-1}")
private Integer backOffPeriodInMilliSeconds;

@Value("${max.Attempts:-1}")
private Integer maxAttempts;

@Bean
public RestTemplate restTemplate() {

    RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
    return restTemplate;
}

private HttpComponentsClientHttpRequestFactory getClientHttpRequestFactory() {

    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
    requestFactory.setReadTimeout(readTimeoutInMilliSeconds);
    requestFactory.setConnectTimeout(connectTimeoutInMilliSeconds);
    return requestFactory;
}

@Bean
public RetryTemplate retryTemplate() {

    Map<Class<? extends Throwable>, Boolean> retryableExpressions = new HashMap<>();

    // connection and read timeouts
    retryableExpressions.put(ResourceAccessException.class, true);

    // 404
    retryableExpressions.put(RestClientException.class, false);

    SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy(maxAttempts, retryableExpressions);

    FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
    backOffPolicy.setBackOffPeriod(backOffPeriodInMilliSeconds);

    RetryTemplate retryTemplate = new RetryTemplate();
    retryTemplate.setRetryPolicy(simpleRetryPolicy);
    retryTemplate.setBackOffPolicy(backOffPolicy);

    return retryTemplate;
}

@Bean
public RetryRestTemplate retryRestTemplate() {
    return new RetryRestTemplate(
            restTemplate(),
            retryTemplate());
   }
}

application.properties

read.Timeout.InMilliSeconds=10000
connect.Timeout.InMilliSeconds=10000
backOff.PeriodInMilliSeconds=10000
max.Attempts=5

堆栈跟踪

Caused by: java.lang.NullPointerException: null
at com.beans.Retry.getClientHttpRequestFactory(Retry.java:43)
at com.beans.Retry.restTemplate(Retry.java:36)
at com.beans.Services.retryRestTemplate(Services.java:82)
at com.beans.Services$$EnhancerBySpringCGLIB$$819e8a9c.CGLIB$retryRestTemplate$3(<generated>)
at com.beans.Services$$EnhancerBySpringCGLIB$$819e8a9c$$FastClassBySpringCGLIB$$65931da6.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.beans.Services$$EnhancerBySpringCGLIB$$819e8a9c.retryRestTemplate(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 213 common frames omitted

进程以退出代码 1 结束

重试休息模板

public class RetryRestTemplate {

private RestTemplate restTemplate;
private RetryTemplate retryTemplate;

public RetryRestTemplate(RestTemplate restTemplate, RetryTemplate retryTemplate) {
    this.restTemplate = this.restTemplate;
    this.retryTemplate = this.retryTemplate;
}

public ResponseEntity getForEntity(URI uri, Class c) {
    return retryTemplate.execute(retryContext -> {
        System.out.println("Check");
        return restTemplate.getForEntity(uri, c);
    });
}

public ResponseEntity exchange(String url, HttpMethod get, HttpEntity headers, Class c) {
    return retryTemplate.execute(retryContext -> {
        return restTemplate.exchange(url, get, headers, c);
    });
}

public <T extends Object> ResponseEntity<T> postForEntity(String apiUrl, HttpEntity<Object> entityRequest, Class<T> responseClass) {
    return retryTemplate.execute(retryContext -> {
        return restTemplate.postForEntity(apiUrl, entityRequest, responseClass);
    });
}

}

【问题讨论】:

  • 能否添加堆栈跟踪?
  • 对不起,我对 java 有点陌生。我如何在 IntelliJ 中做到这一点?
  • 你能显示application.properties吗?
  • Retry 是 Spring 托管类吗?尝试在public class Retry 上方添加@Component
  • 我不这么认为。我刚刚命名它,因为在课堂上我正在创建一个休息模板和重试模板来为我的超时执行重试。我添加了@Component 注释,但不幸的是,这并没有解决我的问题。

标签: java maven spring-boot annotations spring-retry


【解决方案1】:

Retry 类可能不受 Spring 管理。在Retry 类上添加@Configuration。

@Configuration
public class Retry {
}

【讨论】:

    【解决方案2】:

    尝试将@Value(...)移动到对应的方法中作为输入参数如下:

    private HttpComponentsClientHttpRequestFactory getClientHttpRequestFactory(
        @Value("${read.Timeout.InMilliSeconds:-1}") Integer readTimeoutInMilliSeconds,
        @Value("${connect.Timeout.InMilliSeconds:-1}") Integer connectTimeoutInMilliSeconds) {
        ...
    }
    
    @Bean
    public RetryTemplate retryTemplate(
        @Value("${backOff.Period.InMilliSeconds:-1}") Integer backOffPeriodInMilliSeconds,
        @Value("${max.Attempts:-1}") Integer maxAttempts) {
        ...
    }
    

    或者您也可以尝试为Retry 创建一个构造函数,并使用@Value 作为构造函数参数:

    private Integer readTimeoutInMilliSeconds;
    private Integer connectTimeoutInMilliSeconds;
    private Integer backOffPeriodInMilliSeconds;
    private Integer maxAttempts;
    
    Retry(@Value("${read.Timeout.InMilliSeconds:-1}") Integer readTimeoutInMilliSeconds,
          @Value("${connect.Timeout.InMilliSeconds:-1}") Integer connectTimeoutInMilliSeconds,
          @Value("${backOff.Period.InMilliSeconds:-1}") Integer backOffPeriodInMilliSeconds,
          @Value("${max.Attempts:-1}") Integer maxAttempts) {
        this.readTimeoutInMilliSeconds = readTimeoutInMilliSeconds;
        this.connectTimeoutInMilliSeconds = connectTimeoutInMilliSeconds;
        this.backOffPeriodInMilliSeconds = backOffPeriodInMilliSeconds;
        this.maxAttempts = maxAttempts;
    }
    

    【讨论】:

      【解决方案3】:

      除了@Value注解之外,还有其他方法可以获取属性值。通过使用Environment 接口的实例。

      按照以下步骤操作:

      1. Retry.java 上添加@Component 注释
      2. 在您的Retry.java 中导入并自动连接Environment

        import org.springframework.core.env.Environment
        @Autowired
        private Environment env;
        
      3. 从 env 中获取属性的值。例如,

        env.getProperty("read.Timeout.InMilliSeconds","-1");

      该物业的价值还有其他几种口味。您可以在this 上查看。

      【讨论】:

        【解决方案4】:

        2 件事:
        1)正如其他人所说,添加配置
        2)检查您是否在为其创建对象的任何类中使用 Retry as Autowired。如果在实例化对象中使用了任何 bean 类,则它返回 null。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-02-12
          • 1970-01-01
          • 2021-11-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多