SpringCloud之feign

四、springcloud之feign

如果想要调用各个微服务之间的方法,可以使用spring提供的RestTemplete,或者使用客户端的服务分发组件eureka,但是这些的便捷性和优雅性都不如feign,下面介绍feign的简单操作以及坑位。

项目列表

-- consumer-order-feign

--provider-user

 

consumer-order-feign,基本功能与consumer-order类似,springboot版本1.5.9,springcloud版本为Edgware.SR2。

App启动类

package cn.huangwei.app;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.feign.EnableFeignClients;

import org.springframework.context.annotation.Bean;

import org.springframework.web.client.RestTemplate;

 

@SpringBootApplication(scanBasePackages = "cn.huangwei")

@EnableFeignClients(basePackages = "cn.huangwei.controller")

public class ConsumerOrder {

         @Bean//相当于xml中的bean标签,主要用于调用当前方法获取指定对象

         public RestTemplate getTemplate() {

                   return new RestTemplate();

         }

        

         public static void main(String[] args) {

                   SpringApplication.run(ConsumerOrder.class, args);

         }

}

可能由于版本的问题,此时的SpringBootApplication注解上,必须手动添加scanPackage的扫描包,如果不添加,将不会扫描相关注解;同时EnableFeignClients,也要添加basePackages的路径,否则接下来的FeignTest的bean实例将不会产生,提示FeignTest对象not found。

OrderController

package cn.huangwei.controller;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RestController;

 

import cn.huangwei.entity.User;

 

@RestController

public class OrderController {

         @Autowired

         private FeignTest feignTest;

        

         @GetMapping("/order/{id}")

         public User getOrder(@PathVariable long id) {

                   User user = feignTest.getUser(id);

                   return user;              

         }

}

该controller的作用就是通过访问order/id,实质上通过feign去调用provider-user的相关服务

FeignTest

package cn.huangwei.controller;

 

import org.springframework.cloud.netflix.feign.FeignClient;

import org.springframework.stereotype.Component;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

 

import cn.huangwei.entity.User;

 

@FeignClient(name = "provider-user", url = "http://localhost:7903")

public interface FeignTest {

         @GetMapping(value = "/user/{id}")

         public User getUser(@PathVariable Long id);

}

Pom文件

SpringCloud之feign_第1张图片

Application.yml

server:

  port: 8900

spring:

  application:

    name: consumer-order-feign

provider-user项目,简单的提供user的服务

启动类app

package cn.huangwei.app;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

@SpringBootApplication(scanBasePackages = "cn.huangwei")

public class ProviderUser {

         public static void main(String[] args) {

                   SpringApplication.run(ProviderUser.class, args);

         }

}

Controller

package cn.huangwei.controller;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RestController;

 

import com.netflix.appinfo.InstanceInfo;

import com.netflix.discovery.EurekaClient;

 

import cn.huangwei.entity.User;

 

@RestController

public class UserController {

    @Autowired

    private EurekaClient discoveryClient;

   

    @GetMapping("/user/{id}")

    public User getUser(@PathVariable long id) {

       return new User(id);

    }

}

Pom文件

SpringCloud之feign_第2张图片

Application.yml

server:

  port: 7903

spring:

  application:

    name: provider-user-swagger

运行项目;

先启动provider-user项目,正常启动

然后启动consumer-order-feign

提示:

SpringCloud之feign_第3张图片

原因出在这里:

SpringCloud之feign_第4张图片

如果使用了getMapping等Restful风格的注解,那么@PathVariable也需要使用restful风格,变为@PathVariable(“id”);

访问成功

feign坑位

1.@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)

@GetMapping("/user/{id}")

这两个注解的效果是等价的,但是在Feign使用中,只能用上面的那种方式,不能直接用@GetMapping,下面我们将前面的那个示例中,改成@GetMapping注解看下效果,我们发现,修改注解后重新启动服务的时候,抛了如下异常:

Caused by: java.lang.IllegalStateException: Method findById not annotated with HTTP method type (ex. GET, POST)

由于存在版本问题,这个情况可能会出现,也可能不出现

2.多参数问题

@RequestMapping(value="/user/name", method=RequestMethod.GET)

    User findByUsername(final String userName,  final String address);

启动服务后,提示

Caused by: java.lang.IllegalStateException: Method has too many Body parameters

当使用feign时,如果发送的时get请求,那么需要在请求参数前加上@RequestParam,表示该请求参数时get请求的参数,如果不标注,可能会提示Request method 'POST' not supported

因为我们使用的是get请求,如果userName没有被@RequestParam注解修饰,会自动当成requestbody来处理。只要有body,feign认为是post请求,例如参数是一个复杂对象User,那么也会当成post请求,从而报错

你可能感兴趣的:(SpringCloud)