網頁

2019/7/15

Spring Boot RestTemplate @Autowired無法注入

今天在Spring Boot(2.1.6.RELEASE)應用程式的Controller類別中用@Autowired注入RestTemplate的實例時出現下面錯誤訊息而無法啟動。

DemoController

package com.abc.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;


@RestController
@RequestMapping("/demo")
public class DemoController {
    
    @Autowired
    private RestTemplate restTemplate;   
    ...
}
***************************
APPLICATION FAILED TO START
***************************

Description:

Field restTemplate in com.abc.demo.controller.DemoController required a bean of type 'org.springframework.web.client.RestTemplate' that could not be found.

The injection point has the following annotations:
 - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'org.springframework.web.client.RestTemplate' in your configuration.

訊息大意是說找不到org.springframework.web.client.RestTemplate的Bean,並提示我們在應用程式的配置中定義一個org.springframework.web.client.RestTemplate的Bean。

所以在Spring Boot的SpringBootApplication類別中使用@Bean定義一個RestTemplate的Bean如下。

SpringBootDemoApplication

@SpringBootApplication
public class SpringBootDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }
    
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
}

必須手動配置Bean是因為RestTemplate使用前常需要自訂各種參數,所以Spring Boot不幫我們自動配置。

以下引述官方說明:

Since RestTemplate instances often need to be customized before being used, Spring Boot does not provide any single auto-configured RestTemplate bean. It does, however, auto-configure a RestTemplateBuilder, which can be used to create RestTemplate instances when needed.


完成以上RestTemplate的Bean配置即可在Controller中正常以@Autowired注入RestTemplate的實例。



不過Spring Boot有自動配置RestTemplateBuilder的Bean,所以在Controller或Service類別中可改用以下方式取得RestTemplate實例。

DemoController

package com.abc.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;


@RestController
@RequestMapping("/demo")
public class DemoController {
    
    private final RestTemplate restTemplate;

  // 建構式注入
    public DemoController(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
    }

    @GetMapping(value = "/{id}", produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String getDemoResult(@PathVariable int id) {
        return this.restTemplate.getForObject("http://localhost:8080/services/{id}", String.class);
    }
    ...
}

參考:

沒有留言:

張貼留言