Не вдалося автоматично прокласти поле: RestTemplate у програмі Spring boot


109

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

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

    <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.micro.test</groupId>
    <artifactId>Test-MicroService</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>Test-MicroService</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

1
Оновлення вашого питання не очевидно, що коли все пов'язано магічним шляхом RestTemplate, автоматичне створення не буде для вас автоматично.
daniel.eichten

Оновлено - підручник на власній сторінці Spring Boot нічого не говорить про створення RestTemplate Bean !!
Метт

Відповіді:


174

Саме про це говорить помилка. Ви не створили жодного RestTemplateквасолі, тому він не може автопроводити жодного. Якщо вам потрібно, RestTemplateвам доведеться надати його. Наприклад, додайте в TestMicroServiceApplication.java наступне :

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

Зауважте, у попередніх версіях весняного хмарного стартера для Eureka RestTemplateдля вас було створено бобові, але це вже не відповідає дійсності.


Дякую за вашу відповідь. Це допомогло!
Хузі

19
Захищене питання та ваша відповідь. Не очевидно, що вам доведеться вручну створювати, RestTemplateколи все інше створено і пов'язане для вас магічно. Особливо, якщо використовується весняна хмара, перед якою передбачено автоматичне налаштування RestTemplate. ;-)
daniel.eichten

2
Чесно кажучи, саме тому я поставив це питання тут на форумі. Я очікував, що RestTemplate буде пов'язаний для мене. :-) Це спрацювало нормально, коли я включив залежність Eureka в POM.xml. Це працювало нормально, не визначаючи RestTemplate bean. Один із класів Еврики, можливо, визначив цю квасолю чи так.
Хузі

4
Просто оновлення. Від Spring Boot 1.4.0 RestTemplateBuilderможна використовувати для управління RestTemplateекземплярами. Приклад тут spring.io/guides/gs/consuming-rest
Менсур

Я не можу поки оновити до SB 1.4.0. Я хочу це зробити за допомогою 1.3.8.RELEASE, але рішення @ g00glen00b не працювало для мене. Я також використовую spring-cloud-netflixартефактид з версією 1.1.5.RELEASE. Мій RestTemplate викликається з @RestControllerкласу java, який використовується @Autowiredдля RestTemplate. Може хтось, будь ласка, допоможе?
ZeroGraviti

33

Залежно від того, які технології ви використовуєте та які версії впливатимуть на визначення RestTemplateвашого @Configurationкласу.

Весна> = 4 без весняного завантаження

Просто визначте @Bean:

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

Весняний черевик <= 1,3

Не потрібно визначати її, 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;

Довідково


8

Якщо TestRestTemplate є дійсним варіантом у вашому тесті пристрою, ця документація може бути доречною

http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#boot-features-rest-templates-test-utility

Коротка відповідь: якщо використовується

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)

тоді @Autowiredбуде працювати. Якщо використовується

@SpringBootTest(webEnvironment=WebEnvironment.MOCK)

потім створіть тестовий шаблон TestRestTem

private TestRestTemplate template = new TestRestTemplate();

1

Помилка прямо вказує на те, що RestTemplateквасоля не визначена в контексті, і вона не може завантажувати боби.

  1. Визначте квасоля для RestTemplate та використовуйте її
  2. Використовуйте новий екземпляр шаблону RestTemplate

Якщо ви впевнені, що квасоля визначена для RestTemplate, використовуйте наступне для друку бобів, доступних у контексті, завантаженому програмою весняного завантаження.

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

Якщо це містить квасоля за вказаною назвою / типом, то все добре. Або ж визначте нову квасолю і потім використовуйте її.


1

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

RestTemplateBuilder пропонує належний спосіб налаштувати та інстанціювати решта шаблону шаблону, наприклад, для базових auth чи перехоплювачів.

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder
                .basicAuthorization("user", "name") // Optional Basic auth example
                .interceptors(new MyCustomInterceptor()) // Optional Custom interceptors, etc..
                .build();
}


0

Переконайтесь, що дві речі:

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();
}
}

0

Найпростішим способом я зміг досягти подібного подвигу, використовуючи наведений нижче код ( посилання ), але я б запропонував не робити дзвінки 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";
    }
}

0

ви намагаєтеся вставити шаблон restTemplate, але вам потрібно створити клас конфігурації. тоді вам потрібно створити боб, який поверне вам новий RestTemplate, див. нижче приклад.

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


@Configuration
public class YourConfigClass {


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

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.