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

在启动过程中运行弹簧启动应用程序时,我遇到了以下异常:

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

我正在我的 TestController 中自动装配 RestTemplate。我正在使用 Maven 进行依赖管理。

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>
205706 次浏览

错误直接指出 RestTemplatebean 没有在上下文中定义,因此无法加载 bean。

  1. 为 RestTemplate 定义一个 bean,然后使用它
  2. 使用 RestTemplate 的新实例

如果您确定这个 bean 是为 RestTemplate 定义的,那么使用以下命令打印在 Spring 启动应用程序加载的上下文中可用的 bean

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

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

错误就是这么说的。您没有创建任何 RestTemplate bean,所以它不能自动连接任何。如果你需要一个 RestTemplate,你必须提供一个。例如,将以下内容添加到 Java:

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

自从 Spring 启动1.4以来,还有一个方便的构建器,您可以自动连接并使用它来创建 RestTemplate bean。这样做的好处是,您可以使用构建器模式来注册拦截器、定制器等。

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

注意,在 Eureka 的 Spring Cloud starter 的早期版本中,为您创建了一个 RestTemplate bean,但是现在不再是这样了。

如果 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)

然后像这样创建一个 TestRestTemplate

private TestRestTemplate template = new TestRestTemplate();

这将有助于避免创建不会在测试之外使用的 RestTemplate。

由于在使用 RestTemplate 实例之前通常需要进行自定义,因此 SpringBoot 不提供任何自动配置的 RestTemplate bean。

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

取决于您正在使用的技术和什么版本会影响您在 @Configuration类中定义 RestTemplate的方式。

没有 Spring 引导的 Spring > = 4

简单地定义一个 @Bean:

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

Spring Boot < = 1.3

不需要定义一个,SpringBoot 会自动为您定义一个。

Spring Boot > = 1.4

SpringBoot 不再自动定义 RestTemplate,而是定义 RestTemplateBuilder,允许您对创建的 RestTemplate 进行更多控制。您可以在 @Bean方法中注入 RestTemplateBuilder作为参数来创建 RestTemplate:

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

用在你的课堂上

@Autowired
private RestTemplate restTemplate;

参考文献

请确定两件事:

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

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

这个方法的范围应该是 公众人士而不是 二等兵

完整例子-

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

最简单的方法,我能够实现类似的壮举使用下面的代码(参考文献) , 但我建议不要在控制器(坚实的原则)中进行 API 调用。 而且这种自动配电方式比传统的方式优化得更好。

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";
}
}
  • 你必须加上 @ Bean Public RestTemplate restTemplate (RestTemplateBuilder 生成器){ 返回 builder.build () ; }

您正在尝试注入 restTemplate,但是需要创建配置类。 然后需要创建返回新 RestTemplate 的 bean,请参见下面的示例。

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




@Configuration
public class YourConfigClass {




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


}