Spring Cloud (9): Implementing declarative REST calls using Feign

I. Brief Introduction

Earlier, we used RestTemplate to implement rest api calls. The code is as follows:

@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) throws Exception {
    return  this.restTemplate.getForObject("http://spring-ribbon-eureka-client2/" + id, User.class);
}

As can be seen from the above code, we use splicing URI. If there are too many parameters, it will be very troublesome. The solution is to use Feign.


Feign is a declarative, template HTTP client developed by Netflix. Feign can help us to call HTTP API more conveniently and elegantly.

Spring cloud enhanced Feign by supporting Spring MVC annotations and integrating Ribbon and Eureka.

Integration of Feign for Service Consumers

2.1. Adding dependencies

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

2.2. Create a Feign interface and add the @FeignClient annotation

package com.example.demo.feign;

import com.example.demo.pojo.User;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * describe
 *
 * @Author: I love big gold
 * @Description: describe
 * @Date: Create in 10:14 2017/7/17
 */
@FeignClient(name = "spring-ribbon-eureka-client2")
public interface UserFeignClient {
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public User findById(@PathVariable("id") Long id) throws Exception;
}

Explain:

 1. Spr-ribbon-eureka-client2 in the @FeignClient annotation is an arbitrary client name for creating a Ribbon load balancer.

 2. Because this example uses Eureka, Ribbon parses spring-ribbon-eureka-client 2 into services in the Eureka Server service registry.

 3. If you don't want to use Eureka, you can configure the server list using the service.ribbon.listOfServers property.


2.3. Add feign to Controller

@RestController
public class UserController {
    @Autowired
    private UserFeignClient userFeignClient;

    @GetMapping("/user/{id}")
    public User findById(@PathVariable Long id) throws Exception {
        if (null == id) {
            return null;
        }
        return  this.userFeignClient.findById(id);
    }
}


2.4. Modify the startup class to add the @EnableFeignClients annotation

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

@EnableEurekaClient
@EnableFeignClients
@SpringBootApplication
public class SpringFeignConsumerApplication {

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

3. Custom Feign Configuration

In Spring Cloud, Feign's default configuration class is FeignClients Configuration, which defines the coder, decoder, contract used by Feign by default.

Spring Cloud allows you to customize Feign configurations by annotating @FeignClient's configura attribute, which has a higher priority than FeignClients Configuration.

In addition, some configurations do not provide default values, but spirng also scans the types listed therein (that is, this allocation can also be customized)


Example: Customize the configuration of Feign to work with its own annotations.

Note: The code is based on the above project.

3.1. Create configuration classes for Feign

package com.example.demo.config;

import com.example.demo.ExcludeFromComponentScan;
import feign.Contract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Feign Configuration class
 * Note: This class should not be in @ComponetScan in the main application context
 * @Author: I love big gold
 * @Description: Feign Configuration class
 * @Date: Create in 15:57 2017/7/17
 */
@Configuration
@ExcludeFromComponentScan
public class FeignConfiguration {
    /**
     * Change the contract to feign's original default contract. So you can use the annotations that feign comes with
     * @Author: I love big gold
     * @Description: Change the contract to feign's original default contract. So you can use the annotations that feign comes with
     * @Date: 16:02 2017/7/17
     * @return Default feign contract
     */
    @Bean
    public Contract feignContract() {
        return new Contract.Default();
    }
}
package com.example.demo;

public @interface ExcludeFromComponentScan {

}

3.2. Modify Feign Interface

package com.example.demo.feign;

import com.example.demo.config.FeignConfiguration;
import com.example.demo.pojo.User;
import feign.Param;
import feign.RequestLine;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * describe
 *
 * @Author: I love big gold
 * @Description: describe
 * @Date: Create in 10:14 2017/7/17
 */
@FeignClient(name = "spring-ribbon-eureka-client2", configuration = FeignConfiguration.class)
public interface UserFeignClient {

    /**
     * Use the annotation @RequestLine that comes with feign
     * @Author: I love big gold
     * @Description: Use the annotation @RequestLine that comes with feign
     * @Date: 17:42 2017/7/17
     * @param id User id
     * @return User Information
     * @throws Exception
     */
    @RequestLine("GET /{id}")
    public User findById(@Param("id") Long id) throws Exception;
}


OK.

3.3. Testing

Visit: http://localhost:8086/user/1 


Similarly, you can customize Feign's encoder, decoder, log printing, and even add interceptors for Feign.

For example, some interfaces require Http Basic-based authentication before they can be invoked, and configuration classes can write as follows:

@Configuration
@ExcludeFromComponentScan
public class FeignConfiguration {
    @Bean
    public BasicAuthRuestInterceptor basicAuthRuestInterceptor() {
        return new BasicAuthRuestInterceptor("user","password");
    }
}

Not finished, to be continued ____________.

Keywords: Java Spring REST Attribute

Added by ParkerPHP on Thu, 13 Jun 2019 01:12:06 +0300