下面提到的使用 org.springframework.web.client.RestTemplate RestTemplate 的风格的潜在问题是什么?

What is the potential issue with below mentioned style of using org.springframework.web.client.RestTemplate RestTemplate?

这是我的应用程序 class 的主要部分

@SpringBootApplication (scanBasePackages = { "com.xyz.*" })
@EnableAsync
@EnableAspectJAutoProxy (proxyTargetClass=true)
@EnableScheduling
public class XyzApplication {

    public static void main(String[] args) {
        SpringApplication.run(XyzApplication.class, args);
    }

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        builder.requestFactory(new HttpComponentsClientHttpRequestFactory());
        return builder.build();
    }
}

在多个服务和组件中,此 RestTemplate 正在自动装配。

就像在控制器中一样使用

@RestController
@RequestMapping({ "my-api" })
public class CommonController {

    @Autowired
    AppConfig appConfig;

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping("check")
    public String pwa() {
        ResponseEntity<String> response = restTemplate.getForEntity(appConfig.getApiConfig().get("ApiURL"), String.class);
        if (HttpStatus.OK == response.getStatusCode()) {
            return response.getBody().toString();
        } else {
            Logger.error(this.getClass(), "Api is not working");
        }

        return null;

    }
}

并且在不同的服务中,例如

@Service
public class DetailsQuery {

    @Autowired
    private AppConfig appConfig;

    @Autowired
    private RestTemplate restTemplate;

    @Async
    public Future<ConcurrentHashMap<String, Object>> getDetails(JSONObject object) throws InterruptedException, RestClientException {

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

        HttpEntity<String> entity = new HttpEntity<String>(object.toString(), headers);

        Map<String, Object> jsonObject = restTemplate.postForObject(new URI(appConfig.getApiConfig().get("searchApi")), entity, Map.class);

        ConcurrentHashMap<String, Object> response = new ConcurrentHashMap<String, Object>();
        response.putAll(jsonObject);

        return new AsyncResult<ConcurrentHashMap<String,Object>>(new ConcurrentHashMap<>(response));

    }

}

问题是这个实现抛出

There was an unexpected error (type=Internal Server Error, status=500). I/O error on GET request for "http://xx.xxxxxx.xxx/xxxx/xxxx/xxxxxx":

这是间歇性的制作,尽管 curl 请求相同的作品。

您可以查看一下,您正在自动连接 RestTemplate 单例对象,但是,每次调用该方法时,它都会将相同的消息转换器添加到 resttemplate。

请记住,resttemplate 构造后是线程安全的,但处理消息转换器在构造后可能不是线程安全的。看看这个线程的例子:

Is RestTemplate thread safe?

您可以尝试做如下的事情来为您的服务创建一个 resttemplate 实例

@Service
public class DetailsQuery {

  private final RestTemplate restTemplate;

  @Autowired
  public DetailsQuery (RestTemplateBuilder restTemplateBuilder) {
    this.restTemplate = restTemplateBuilder.additionalMessageConverters(new MappingJackson2HttpMessageConverter()) build();
  }

  ....
}

或者在 @Config class 中创建单例 Resttemplate 对象。