【问题标题】:How to Create or configure Rest Template using @Bean in Spring Boot如何在 Spring Boot 中使用 @Bean 创建或配置 Rest 模板
【发布时间】:2016-11-25 18:41:32
【问题描述】:

我想在 Spring Boot 应用程序的配置类中使用 @Bean 注释将 RestTemplate 定义为应用程序 bean。

我在我的应用程序流的不同位置调用 4 个休息服务。目前我在每次请求时都创建RestTemplate。有没有办法可以使用@Bean 将其定义为应用程序bean 并使用@Autowired 注入它?

这个问题的主要原因是我可以使用@Bean 定义RestTemplate,但是当我用@Autowired 注入它时,我失去了所有定义的拦截器(拦截器没有被调用。)

配置类

@Bean(name = "appRestClient")
public RestTemplate getRestClient() {

    RestTemplate  restClient = new RestTemplate(
        new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));

    List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
    interceptors.add(new RestServiceLoggingInterceptor());
    restClient.setInterceptors(interceptors);

    return restClient;
}

服务类

public class MyServiceClass {

    @Autowired
    private RestTemplate appRestClient;

    public String callRestService() {
        // create uri, method response objects
        String restResp = appRestClient.getForObject(uri, method, response);
        // do something with the restResp
        // return String
    }
}

似乎我的Interceptors 根本没有被这个配置调用。但是RestTemplate 能够调用 REST 服务并获得响应。

【问题讨论】:

  • 你确定你注入的是同一个RestTemplate 实例,你可能会选择其他一些bean?尝试在 @Autowired 注释旁边添加来自 org.springframework.beans.factory.annotation.Qualifier@Qualifier("appRestClient")
  • 感谢您的输入 daniel。当我尝试使用 @Qualifier 时,拦截器没有被拾取。我想我在这里遗漏了一些东西。

标签: spring-boot


【解决方案1】:

Spring boot 2.*.* 版本的回答。

我正在使用 Spring boot 2.1.2.RELEASE 并且我还在我的项目中添加了 RestTemplate 在一个存在邮件方法的类中。

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {

    return builder.setConnectTimeout(Duration.ofMillis(300000))
     .setReadTimeout(Duration.ofMillis(300000)).build();
}

并在我的服务或其他课程中使用像这样

@Autowired
RestTemplate res;

在方法中

 HttpEntity<String> entity = new HttpEntity<>(str, headers);
            return res.exchange(url, HttpMethod.POST, entity, Object.class);

【讨论】:

    【解决方案2】:

    如果您使用的是 Spring Boot 1.4.0 或更高版本,Edd 的解决方案将不起作用。您必须使用 RestTemplateBuilder 才能使其正常工作。这是一个例子

    @Bean(name="simpleRestTemplate")
    @Primary
    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){
    
        RestTemplate template = restTemplateBuilder.requestFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()))
                                                    .interceptors(logRestRequestInterceptor) //This is your custom interceptor bean
                                                    .messageConverters(new MappingJackson2HttpMessageConverter())
                                                    .build();
        return template;
    
    
    }
    

    现在您可以将 bean 自动装配到您的服务类中

    @Autowired
    @Qualifier("simpleRestTemplate")
    private RestTemplate simpleRestTemplate;
    

    希望对你有帮助

    【讨论】:

      【解决方案3】:

      从拦截器的名称来看,我猜你正在登录它?您可能会错过日志级别配置。我使用1.3.6.RELEASE 版本创建了一个小应用程序来检查您的配置是否正常工作。

      在这个类中,我定义了 RestTemplate bean 和带有日志记录的拦截器。

      package com.example;
      
      // imports...
      
      @SpringBootApplication
      public class TestApplication {
      
          private static final Logger LOGGER = LoggerFactory.getLogger(TestApplication.class);
      
          public static void main(String[] args) {
              SpringApplication.run(TestApplication.class, args);
          }
      
          @Bean(name = "appRestClient")
          public RestTemplate getRestClient() {
              RestTemplate restClient = new RestTemplate(
                      new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
      
              // Add one interceptor like in your example, except using anonymous class.
              restClient.setInterceptors(Collections.singletonList((request, body, execution) -> {
      
                  LOGGER.debug("Intercepting...");
                  return execution.execute(request, body);
              }));
      
              return restClient;
          }
      }
      

      为了使日志记录正常工作,我还必须在 application.properties 中设置正确的调试级别。

      logging.level.com.example=DEBUG
      

      然后我创建一个服务,在其中注入 RestTemplate

      @Service
      public class SomeService {
      
          private final RestTemplate appRestClient;
      
          @Autowired
          public SomeService(@Qualifier("appRestClient") RestTemplate appRestClient) {
              this.appRestClient = appRestClient;
          }
      
          public String callRestService() {
              return appRestClient.getForObject("http://localhost:8080", String.class);
          }
      }
      

      还有一个端点来测试它。

      @RestController
      public class SomeController {
      
          private final SomeService service;
      
          @Autowired
          public SomeController(SomeService service) {
              this.service = service;
          }
      
          @RequestMapping(value = "/", method = RequestMethod.GET)
          public String testEndpoint() {
              return "hello!";
          }
      
          @RequestMapping(value = "/test", method = RequestMethod.GET)
          public String test() {
              return service.callRestService();
          }
      }
      

      通过对http://localhost:8080/test 执行GET 请求,我应该期望得到字符串hello! 被打印(该服务调用http://localhost:8080,它返回hello! 并将其发送回给我)。带有记录器的拦截器也在控制台中打印出Intercepting...

      【讨论】:

        猜你喜欢
        • 2021-08-02
        • 1970-01-01
        • 1970-01-01
        • 2015-05-26
        • 1970-01-01
        • 1970-01-01
        • 2016-08-22
        • 2015-03-17
        • 1970-01-01
        相关资源
        最近更新 更多