学习Spring Cloud第十一课(Feign的简介及基础使用)

        Feign是一个声明式的web service客户端。它让写web service客户端更加容易,要使用Feign只需创建一些接口和一些注解便可。它已经支持Feign和JAX-RS注解并且是可插拔的。Fegin同样支持可插拔的编码器和解码器。Spring cloud为Feign添加了Spring MVC的注解。Spring Cloud整合了Ribbon和Eureka以提供负载均衡的能力。

        为了更好的说明Feign的使用方法,我们复制一份microservice-simple-consumer-movie工程,命名为microservice-simple-consumer-movie-feign,修改microservice-simple-consumer-movie-feign工程的pom.xml文件,将原来的"microservice-simple-consumer-movie"更换为"microservice-simple-consumer-movie-feign"如下图。


         然后我们编辑父工程的pom.xml文件,添加模块microservice-simple-consumer-movie-feign,如下图所示。


         下面我们把MovieController中原来的代码变成如下

package com.itmuch.cloud.Controller;

import com.itmuch.cloud.entity.User;
import com.sun.org.apache.xpath.internal.SourceTree;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * Created by wanghaijie on 2017/11/19.
 */
@RestController
public class MovieController {

    @GetMapping(value = "/movie/{id}")
    public User findById(@PathVariable Long id){
        return null;
    }
    
}
       把application.yml文件中原来的负载均衡代码去掉,修改后如下所示

server:
  port: 8010
spring:
  application:
    name: microservice-consumer-movie
eureka:
  client:
    healthcheck:
      enabled: true
    serviceUrl:
      defaultZone: http://user:password123@localhost:8761/eureka
  instance:
    prefer-ip-address: true
       把MicroserviceSimpleConsumerMovieApplication这个类中原来的负载均衡注解去掉,修改后如下所示

package com.itmuch.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
public class MicroserviceSimpleConsumerMovieApplication {

	public static void main(String[] args) {
		SpringApplication.run(MicroserviceSimpleConsumerMovieApplication.class, args);
	}
}
      现在这个工程就比较干净了,下面我们来添加feign的依赖

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-feign</artifactId>
		</dependency>
       下面我们将工程的启动类类名将原来的MicroserviceSimpleConsumerMovieApplication修改为ConsumerFeignMovieApplication并且添加注解@EnableFeignClients如下图所示:

       下面新建一个接口类,类的位置与启动类在同一目录。

package com.itmuch.cloud;

import com.itmuch.cloud.entity.User;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * Created by wanghaijie on 2017/12/3.
 */
@FeignClient("microservice-provider-user")
public interface UserFeignClient {

    @GetMapping("/simple/{id}")
    public User findById(@PathVariable Long id);
}
      接着我们在MovieController使用我们的接口,如下图所示。



         好,下面我们"尝试"启动一下movie-feigin工程,会报下面的错误。

Caused by: java.lang.IllegalStateException: Method findById not annotated with HTTP method type (ex. GET, POST)
	at feign.Util.checkState(Util.java:128) ~[feign-core-9.3.1.jar:na]
	at feign.Contract$BaseContract.parseAndValidateMetadata(Contract.java:97) ~[feign-core-9.3.1.jar:na]
	at org.springframework.cloud.netflix.feign.support.SpringMvcContract.parseAndValidateMetadata(SpringMvcContract.java:133) ~[spring-cloud-netflix-core-1.2.5.RELEASE.jar:1.2.5.RELEASE]
	at feign.Contract$BaseContract.parseAndValidatateMetadata(Contract.java:64) ~[feign-core-9.3.1.jar:na]
	at feign.hystrix.HystrixDelegatingContract.parseAndValidatateMetadata(HystrixDelegatingContract.java:34) ~[feign-hystrix-9.3.1.jar:na]
	at feign.ReflectiveFeign$ParseHandlersByName.apply(ReflectiveFeign.java:146) ~[feign-core-9.3.1.jar:na]
       出现这种错误是因为Feign不支持@GetMapping,它认为我们没有指定是GET请求还是POST请求,我们必须明确指定是GET请求,因此我们在UserFeignClient接口类得使用@RequestMapping这个注解。如下图所示

        下面我们再来启动movie-feign工程,会发现又报错了,错误信息如下

Caused by: java.lang.IllegalStateException: PathVariable annotation was empty on param 0.
	at feign.Util.checkState(Util.java:128) ~[feign-core-9.3.1.jar:na]
	at org.springframework.cloud.netflix.feign.annotation.PathVariableParameterProcessor.processArgument(PathVariableParameterProcessor.java:49) ~[spring-cloud-netflix-core-1.2.5.RELEASE.jar:1.2.5.RELEASE]
	at org.springframework.cloud.netflix.feign.support.SpringMvcContract.processAnnotationsOnParameter(SpringMvcContract.java:237) ~[spring-cloud-netflix-core-1.2.5.RELEASE.jar:1.2.5.RELEASE]
	at feign.Contract$BaseContract.parseAndValidateMetadata(Contract.java:107) ~[feign-core-9.3.1.jar:na]
        出现这个错误是因为我们必须指定接收的参数的名字,我们要接收的是"id",因此我们在@PathVariable后面加上("id"),如下图所示。

         上面两个问题是使用feign的两个坑,大家使用的时候一定要注意。

          下面我们来访问http://localhost:8010/movie/1,发现正常访问到结果了。


          下面来写一个POST请求

          现在先在user工程的UserController中添加如下方法

@PostMapping("/user")
    public User postUser(@RequestBody User user){
        return user;
    }
       接着在movie-feign工程的UserFeignClient添加

@RequestMapping(value = "/user", method = RequestMethod.POST)
    public User postUser(User user);
      接着在movie-feign工程的MovieController中添加如下代码。

 @GetMapping(value = "/test")
    public User testPost(User user){
        User user1 = this.userFeignClient.postUser(user);
        return user1;
    }
       下面我们便依次重启user工程和movie工程,然后我们便可以访问http://localhost:8010/test?id=1&name=zhangsan如下图所示。



猜你喜欢

转载自blog.csdn.net/u012453843/article/details/78701547