无法自动装配字段:Spring 启动应用程序中的 RestTemplate

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36151421/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 01:00:26  来源:igfitidea点击:

Could not autowire field:RestTemplate in Spring boot application

springmavenspring-bootresttemplate

提问by Khuzi

I am getting below exception while running spring boot application during start up:

我在启动期间运行 spring boot 应用程序时遇到异常:

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

I am autowiring RestTemplate in my TestController. I am using Maven for dependency managagement.

我在我的 TestController 中自动装配 RestTemplate。我正在使用 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

测试控制器.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

POM文件

    <?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>

回答by g00glen00b

It's exactly what the error says. You didn't create any RestTemplatebean, so it can't autowire any. If you need a RestTemplateyou'll have to provide one. For example, add the following to TestMicroServiceApplication.java:

这正是错误所说的。您没有创建任何RestTemplatebean,因此它无法自动装配任何 bean。如果你需要一个,RestTemplate你必须提供一个。例如,将以下内容添加到TestMicroServiceApplication.java

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

Note, in earlier versions of the Spring cloud starter for Eureka, a RestTemplatebean was created for you, but this is no longer true.

请注意,在 Eureka 的 Spring cloud starter 的早期版本中,RestTemplate为您创建了一个bean,但现在不再如此。

回答by Sahil Chhabra

Depending on what technologies you're using and what versions will influence how you define a RestTemplatein your @Configurationclass.

取决于您使用的技术和版本将影响您RestTemplate@Configuration类中定义 a的方式。

Spring >= 4 without Spring Boot

Spring >= 4 没有 Spring Boot

Simply define an @Bean:

简单地定义一个@Bean

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

Spring Boot <= 1.3

弹簧靴 <= 1.3

No need to define one, Spring Boot automatically defines one for you.

不需要定义一个,Spring Boot 会自动为你定义一个。

Spring Boot >= 1.4

弹簧靴 >= 1.4

Spring Boot no longer automatically defines a RestTemplatebut instead defines a RestTemplateBuilderallowing you more control over the RestTemplate that gets created. You can inject the RestTemplateBuilderas an argument in your @Beanmethod to create a RestTemplate:

Spring Boot 不再自动定义 aRestTemplate而是定义 aRestTemplateBuilder允许您更好地控制创建的 RestTemplate 。你可以RestTemplateBuilder在你的@Bean方法中作为参数注入来创建一个RestTemplate

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

Using it in your class

在你的课堂上使用它

@Autowired
private RestTemplate restTemplate;

Reference

参考

回答by Mark K.

If a TestRestTemplate is a valid option in your unit test, this documentation might be relevant

如果 TestRestTemplate 是单元测试中的有效选项,则此文档可能是相关的

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

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

Short answer: if using

简短回答:如果使用

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)

then @Autowiredwill work. If using

然后@Autowired会工作。如果使用

@SpringBootTest(webEnvironment=WebEnvironment.MOCK)

then create a TestRestTemplate like this

然后像这样创建一个 TestRestTemplate

private TestRestTemplate template = new TestRestTemplate();

回答by Pierrick HYMBERT

Since RestTemplate instances often need to be customized before being used, Spring Boot does not provide any single auto-configured RestTemplate bean.

由于 RestTemplate 实例在使用前经常需要自定义,因此 Spring Boot 不提供任何单个自动配置的 RestTemplate bean。

RestTemplateBuilderoffers proper way to configure and instantiate the rest template bean, for example for basic auth or interceptors.

RestTemplateBuilder提供了正确的方法来配置和实例化 rest 模板 bean,例如用于基本身份验证或拦截器。

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

回答by VinayVeluri

Error points directly that RestTemplatebean is not defined in context and it cannot load the beans.

错误直接指出RestTemplatebean 未在上下文中定义并且无法加载 bean。

  1. Define a bean for RestTemplate and then use it
  2. Use a new instance of the RestTemplate
  1. 为 RestTemplate 定义一个 bean 然后使用它
  2. 使用 RestTemplate 的新实例

If you are sure that the bean is defined for the RestTemplate then use the following to print the beans that are available in the context loaded by spring boot application

如果您确定为 RestTemplate 定义了 bean,则使用以下命令打印 spring boot 应用程序加载的上下文中可用的 bean

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

If this contains the bean by the name/type given, then all good. Or else define a new bean and then use it.

如果这包含给定名称/类型的 bean,那么一切都很好。或者定义一个新的bean然后使用它。

回答by vineet

Please make sure two things:

请确保两件事:

1- Use @Beanannotation with the method.

1-@Bean在方法中使用注释。

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

2- Scope of this method should be publicnot private.

2- 此方法的范围应该是public而不是private

Complete Example -

完整示例 -

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

回答by Padi kodwo

The simplest way I was able to achieve a similar feat to use the code below (reference), but I would suggest not to make API calls in controllers(SOLID principles). Also autowiring this way is better optimsed than the traditional way of doing it.

我能够实现类似壮举的最简单方法是使用下面的代码(参考),但我建议不要在控制器中进行 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";
    }
}

回答by Ranushka Lakmal Sankalpa

  • You must add @Bean public RestTemplate restTemplate(RestTemplateBuilder builder){ return builder.build(); }
  • 你必须添加 @Bean public RestTemplate restTemplate(RestTemplateBuilder builder){ return builder.build(); }

回答by Fazle Subhan

you are trying to inject the restTemplate but you need to create configuration class . then there you need to create bean that return you new RestTemplate see the below example.

您正在尝试注入 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();
    }

}