SpringCloud(三)声明式Web服务客户端Feign

SpringCloud(三)声明式Web服务客户端Feign

Feign是一个声明式的服务Web服务客户端,使得编写Web服务客户端更加容易。SpringCloud使用Feign,Ribbon和Eureka可实现负载均衡。

启用Feign

在调用方服务的pom文件中增加spring-cloud-starter-feign依赖并声明启用Feign客户端。比如我们是web-app-service调用sms-service的接口,我们需要在web-app-service服务中增加依赖并声明启用Feign。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(defaultConfiguration = FeignClientsConfiguration.class)
public class WebApplicationStarter {

    public static void main(String[] args) {
        SpringApplication.run(WebApplicationStarter.class, args);
    }
}

新建一个Feign客户端

新建一个接口使用@FeignClient注解,那么@FeignClient注解中namevalue属性用来创建一个Ribbon负载均衡器。你也可以指定他的url属性(绝对路径或者是一个主机名称)。

@FeignClient(name = "sms-service")
public interface SMSService {}

Robbin客户端将根据@FeignClient的属性发现sms-service服务的物理地址。如果你的服务是一个Eureka客户端,他将会在Eureka服务端发现sms-service服务。
@FeignClientconfiguration属性可以自定义Feign客户端的配置,包括feign.Decoderfeign.EncoderfeignContract,对于不同的FeignClient他们的configuration不会相互影响。

基于SpringMVC注解的FeignClient

SpringCloud中Feign默认的configuration使用的ContractSpringMvcContract所以它可以解析@RequestMapping注解这样你就可以像开发一个Controller一样定义一个接口。

@FeignClient(name = "sms-service")
public interface SMSService {

    @RequestMapping(value="sms", method = RequestMethod.POST)
    String add(@RequestBody SMSEntity entity);

    @RequestMapping(value = "sms", method = RequestMethod.GET)
    String queryAll();

    @RequestMapping(value = "sms/{id}", method = RequestMethod.GET)
    SMSEntity getById(@PathVariable("id") String id);

    @RequestMapping(value = "sms/{id}", method = RequestMethod.PUT)
    String update(@PathVariable("id") String id, @RequestBody SMSEntity entity);

    @RequestMapping(value = "sms/{id}", method = RequestMethod.DELETE)
    String delete(@PathVariable("id") String id);
}

基于Feign原生注解的FeignClient

我们也可以使用Feign原生的Contract,在这个接口中我们的sms-service-cmmon-feign服务在Eureka中不存在,我们通过url指向一个Web服务,Feign通过url@RequestLine解析路径和请求方式向Web服务发起请求。

/**
 * 这是一个普通的Feign客户端,
 * 使用这种方法可以直接调用未在同一Eureka(集群)中注册的应用或者外部接口
 * Created by chenxyz on 2018/5/27.
 */
@FeignClient(name = "sms-service-common-feign", url = "http://localhost:8001", configuration = CommonFeignConfig.class)
public interface CommonSMSFeignService {

    /** 普通GET请求 */
    @RequestLine("GET /sms")
    String querySms();

    /** POST请求传递对象 */
    @RequestLine("POST /sms")
    String sendSms(SMSEntity sms);

    /** 固定一个body请求的模板,占位符代表参数 */
    @RequestLine("POST /sms")
    @Headers("Content-Type: application/json")
    // 可以是{"pohone":"10086","content":"hahha"}
    // 或者可以是<xml></xml>
    @Body("%7B\"phoneNo\": \"{phoneNo}\", \"message\": \"{message}\"%7D")
    String sendSmsTemplate(@Param("phoneNo") String phoneNo, @Param("message") String message);

    /** 获取短信内容 */
    @RequestLine("GET /sms/{id}")
    SMSEntity getSms(@Param("id") long id);


    /** 获取短信内容 */
    @Headers("Content-Type: application/json")
    @RequestLine("PUT /sms/{id}")
    String updateSms(@Param("id") long id, SMSEntity sms);


    /** 获取短信内容 */
    @RequestLine("DELETE /sms/{id}")
    String delete(@Param("id") long id);
}
public class CommonFeignConfig {

    @Bean
    public Contract feignContract(ConversionService feignConversionService) {
        return new feign.Contract.Default();
    }
}

CommonFeignConfig不必使用@Configuration注解,如果你已经这么做了,需要从@ComponentScan中排除,否则他将会成为feign.Decoderfeign.EncoderfeignContract等方法默认的源。
SpringCloud的Feign客户端提供的默认的Bean。

BeanType beanName ClassName
Decoder feignDecoder ResponseEntityDecoder (which wraps a SpringDecoder)
Encoder feignEncoder SpringEncoder
Logger feignLogger Slf4jLogger
Contract feignContract SpringMvcContract
Feign.Builder feignBuilder HystrixFeign.Builder
Client feignClient if Ribbon is enabled it is a LoadBalancerFeignClient, otherwise the default feign client is used

CommonFeignConfig使用feign.Contract.Default代替了SpringMvcContract,使得CommonSMSFeignService可以解析原生的@RequestLine注解。而SMSService使用的SpringMvcContract可以解析与SpringMVC中的@RequestMapping注解。
在案例中两个Feign客户端分别使用了两个不同的configuration,但是不会相互影响,这是因为他们是相互隔离的。SpringCloud为使用了FeignClientsConfiguration的Feign客户端创建了一个新的ApplicationContext集合。


相关代码
SpringCloudDemo-Feign

猜你喜欢

转载自blog.csdn.net/chenxyz707/article/details/80508612