Я получаю следующее исключение при запуске весеннего загрузочного приложения во время запуска:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.web.client.RestTemplate com.micro.test.controller.TestController.restTemplate; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.web.client.RestTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Я автоматически подключаю RestTemplate в своем TestController. Я использую Maven для управления зависимостями.

TestMicroServiceApplication.java

package com.micro.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestMicroServiceApplication {

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

TestController.java

    package com.micro.test.controller;

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

@RestController
public class TestController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value="/micro/order/{id}",
        method=RequestMethod.GET,
        produces=MediaType.ALL_VALUE)
    public String placeOrder(@PathVariable("id") int customerId){

        System.out.println("Hit ===> PlaceOrder");

        Object[] customerJson = restTemplate.getForObject("http://localhost:8080/micro/customers", Object[].class);

        System.out.println(customerJson.toString());

        return "false";
    }

}

POM.xml

    

    4.0.0

    com.micro.test
    Test-MicroService
    0.0.1-SNAPSHOT
    jar

    Test-MicroService
    Demo project for Spring Boot

    
        org.springframework.boot
        spring-boot-starter-parent
        1.3.3.RELEASE
         
    

    
        UTF-8
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    



Ответы (9)

Это именно то, о чем говорит ошибка. Вы не создали bean-компонент RestTemplate, поэтому он не может автоматически подключать его. Если вам нужен RestTemplate, вам нужно будет его предоставить. Например, добавьте в TestMicroServiceApplication.javaследующее:

@ Bean
public RestTemplate restTemplate () {
    вернуть новый RestTemplate ();
}

Обратите внимание: в более ранних версиях облачного стартера Spring для Eureka для вас был создан bean-компонент RestTemplate, но это уже не так.

Если TestRestTemplate является допустимым параметром в вашем модульном тесте, эта документация может быть актуальной

http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#boot-features-rest-templates-test-утилита

Краткий ответ: при использовании

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)

, тогда @ Autowired будет работать. При использовании

@SpringBootTest(webEnvironment=WebEnvironment.MOCK)

затем создайте TestRestTemplate, например,

private TestRestTemplate template = new TestRestTemplate();

Самый простой способ, которым я смог добиться аналогичного результата, - использовать приведенный ниже код (ссылка), но я бы посоветовал не выполнять вызовы API в контроллерах (принципы SOLID). Также автоматическое подключение таким способом лучше оптимизировать, чем традиционный способ.

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

@RestController
public class TestController {

    private final RestTemplate restTemplate;


    @Autowired
    public TestController(RestTemplateBuilder builder) {
        this.restTemplate = builder.build();
    }

    @RequestMapping(value="/micro/order/{id}", method= RequestMethod.GET, produces= MediaType.ALL_VALUE)
    public String placeOrder(@PathVariable("id") int customerId){

        System.out.println("Hit ===> PlaceOrder");

        Object[] customerJson = restTemplate.getForObject("http://localhost:8080/micro/customers", Object[].class);

        System.out.println(customerJson.toString());

        return "false";
    }
}
  • Вы должны добавить @ Бин public RestTemplate restTemplate (RestTemplateBuilder builder) { вернуть builder.build (); }

вы пытаетесь ввести restTemplate, но вам нужно создать класс конфигурации. тогда вам нужно создать bean-компонент, который вернет вам новый RestTemplate, см. пример ниже.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class YourConfigClass {


    @Bean
    public RestTemplate restTesmplate() {
        return new RestTemplate();
    }

}

Поскольку экземпляры RestTemplate часто необходимо настраивать перед использованием, Spring Boot не предоставляет ни одного автоматически настраиваемого bean-компонента RestTemplate.

RestTemplateBuilder предлагает правильный способ настройки и создания экземпляра bean-компонента остального шаблона, например, для базовой аутентификации или перехватчиков.

@ Bean
public RestTemplate restTemplate (RestTemplateBuilder builder) {
    возвратный строитель
            .basicAuthorization ("user", "name") // Необязательный пример базовой аутентификации
            .interceptors (new MyCustomInterceptor ()) // Необязательные пользовательские перехватчики и т. д.
            .строить();
}

Ошибка прямо указывает на то, что bean-компонент RestTemplate не определен в контексте и не может загрузить bean-компоненты.

  1. Определите bean-компонент для RestTemplate, а затем используйте его
  2. Используйте новый экземпляр RestTemplate

Если вы уверены, что bean-компонент определен для RestTemplate, используйте следующую команду для печати bean-компонентов, доступных в контексте, загруженном приложением Spring Boot

ApplicationContext ctx = SpringApplication.run(Application.class, args);
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
    System.out.println(beanName);
}

Если он содержит bean-компонент с указанным именем / типом, то все в порядке. Или же определите новый bean-компонент и затем используйте его.

Пожалуйста, убедитесь в двух вещах:

1- Используйте аннотацию @ Bean с методом.

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

2- Область действия этого метода должна быть общедоступной не частной.

Полный пример -

@Service
public class MakeHttpsCallImpl implements MakeHttpsCall {

@Autowired
private RestTemplate restTemplate;

@Override
public String makeHttpsCall() {
    return restTemplate.getForObject("https://localhost:8085/onewayssl/v1/test",String.class);
}

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

В зависимости от того, какие технологии вы используете и какие версии будут влиять на то, как вы определяете RestTemplate в своем классе @ Configuration.

Spring> = 4 без Spring Boot

Просто определите @ Bean:

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

Spring Boot <= 1.3

Нет необходимости определять один, Spring Boot автоматически определяет его для вас.

Spring Boot> = 1,4

Spring Boot больше не определяет автоматически RestTemplate, а вместо этого определяет RestTemplateBuilder, что позволяет вам больше контролировать создаваемый RestTemplate. Вы можете ввести RestTemplateBuilder в качестве аргумента в свой метод @ Bean, чтобы создать RestTemplate:

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
   // Do any additional configuration here
   return builder.build();
}

Использование в вашем классе

@Autowired
private RestTemplate restTemplate;

Ссылка

2022 WebDevInsider