Spring Cloud OpenFeign Demo

In the previous project, OpenFeign needed to be used in Spring Cloud. The version of Spring Cloud is the latest Greenwich.SR2 version, and the corresponding Spring Boot is 2.1.7.release.

I found a lot of materials on the Internet, most of which are not clear, and the version is relatively low, which is not suitable for the requirements of my latest version of Spring Cloud. So I decided to write my own tutorial.

This tutorial addresses the following issues:

  1. How to configure OpenFeignServer
  2. How do I configure OpenFeignClient
  3. Multiple parameter passing problems
  4. The FeignClient log is faulty. Procedure
  5. Multiple FeignClients using the same name

How to configure OpenFeignServer

We know that OpenFeign is a declarative Web Service client used in Spring Cloud.

OpenFeignServer is a normal Rest service. The difference is that we need to register it with Eureka Server for the convenience of OpenFeignClient calls.

The startup classes are as follows:

@SpringBootApplication
@EnableDiscoveryClient
public class OpenFeignServer {
        public static void main(String[] args) { SpringApplication.run(OpenFeignServer.class, args); }}Copy the code

We defined two Rest services:

OrderController:


@Slf4j
@RestController
@RequestMapping(path = "/order")
public class OrderController {

    /**
     * PostMapping with @RequestBody
     * @param user
     */
    @PostMapping("doOrder")
    public void doOrder(@RequestBody User user){
        log.info("do order !!!!"); }}Copy the code

UserController:

@RestController
@RequestMapping(path = "/user")
public class UserController {

    /**
     * GetMapping example with @RequestParam
     * @param userId
     * @return userName
     */
    @GetMapping("getUserName")
    public String getUserName(@RequestParam("userId") String userId){
        if("100".equals(userId)) {
            return Jacky Cheung;
        }else{
            return "Andy Lau"; }}/**
     * GetMapping example with @RequestParam and @SpringQueryMap
     * @param userId
     * @param user
     * @return userAge
     */
    @GetMapping("getUserAge")
    public String getUserAge(@RequestParam("userId") String userId, @SpringQueryMap User user){
        if("100".equals(userId)) {
            return "20";
        }else{
            return "18"; }}}Copy the code

We registered it with Eureka as OpenFeign-Server

spring:
  application:
    name: openfeign-server
Copy the code

How do I configure OpenFeignClient

OpenFeignClient has the following POM dependencies:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
Copy the code

To configure OpenFeignClient, use @FeignClient to annotate an interface, as shown below:

@FeignClient(value = "openfeign-server")
@RequestMapping(path = "/user")
public interface UserClient {

    @GetMapping("getUserName")
    public String getUserName(@RequestParam("userId") String userId);

    @GetMapping("getUserAge")
    public String getUserAge(@RequestParam("userId") String userId, @SpringQueryMap User user);
}
Copy the code

Where the value in @FeignClient is the registration name of the service to be called, that is, the registration name of OpenFeignServer in Eureka.

The FeignClient Request path, method, and parameters must be consistent with those of the invoked Rest service.

We can then call OpenFeignClient as follows:

@Slf4j
@RestController
public class UserController {

    @Autowired
    private UserClient userClient;

    @GetMapping("getUserName2")
    public void getUserName(a){
        log.info(userClient.getUserName("100")); }}Copy the code

Multiple parameter passing problems

Generally, we use @getMapping and @postMapping to invoke Rest services.

The received parameters are retrieved using @requestParam and @RequestBody.

First let’s talk about @requestBody. @requestBody can only be used for Post requests, and there can only be one @requestBody per Post request. The @requestBody argument can include complex types.

@requestParam can be used in Post and Get requests, but be aware that the @requestParam parameter can only be a basic type or Enum, or a List or Map. So @requestParam can be used with @RequestBody.

What if we have a Get request, but a compound type? Let’s say we want to pass a User object. The User object has only the usual two String attributes. Here we can use @springQueryMap:

    @GetMapping("getUserAge")
    public String getUserAge(@RequestParam("userId") String userId, @SpringQueryMap User user);
Copy the code

Note: the argument behind @SpringQueryMap must be a plain POJO, not a compound type, otherwise it will not parse. If you must use compound types, use @requestBody instead.

The FeignClient log is faulty. Procedure

OpenFeign has four levels of logger. Level:

  • NONE No log
  • BASIC request method, request URL, return Code and execution time
  • Basic header information for HEADERS requests and returns
  • FULL request and return headers, content, metadata

To use these levels, the OpenFeignClient logger must be set to debug:

Logging: level: com: flydean: debugCopy the code

At the same time, we configure the log level of OpenFeign in the code:

@Configuration
public class CustFeignLogConfig {
    @Bean
    Logger.Level feignLoggerLevel(a) {
        returnLogger.Level.FULL; }}Copy the code

In this way, we can see all HTTP request information of DEBUG in the log.

Multiple FeignClients using the same name

In fact, our Server defines two Rest services, User and Order.

You can define UserClient like this:

@FeignClient(value = "openfeign-server")
@RequestMapping(path = "/user")
public interface UserClient {... }Copy the code

If we also define OrderClient like this:

@FeignClient(value = "openfeign-server")
@RequestMapping(path = "/order")
public interface OrderClient {... }Copy the code

An error is reported at runtime. The reason is that both FeignClients use the same value!

So how do you solve this problem?

Because the / * * *@FeignClientThe value of can't be repeated, so you need to create * in a custom way here@author wayne
 * @version FeignClientController,  2019/9/5 7:07 下午
 */
@Data
@Component
@Import(FeignClientsConfiguration.class)
public class FeignClientController {

    private OrderClient orderClient;
    private UserClient userClient;

    public FeignClientController(Decoder decoder, Encoder encoder, Client client, Contract contract) {
        this.orderClient = Feign.builder().client(client)
                .encoder(encoder)
                .decoder(decoder)
                .contract(contract)
                // The default is logger.nooplogger
                .logger(new Slf4jLogger(OrderClient.class))
                // The default is logger.level.none
                .logLevel(Logger.Level.FULL)
                .target(OrderClient.class, "http://openfeign-server");

        this.userClient = Feign.builder().client(client)
                .encoder(encoder)
                .decoder(decoder)
                .contract(contract)
                // The default is logger.nooplogger
                .logger(new Slf4jLogger(UserClient.class))
                // The default is logger.level.none
                .logLevel(Logger.Level.FULL)
                .target(UserClient.class, "http://openfeign-server"); }}Copy the code

The method is to create FeignClient manually. In the above example, we created both OrderClient and UserClient manually.

Notice in the code snippet below that manually created FeignClient has no Logger and logLevel by default. So the log information we configured above is invalid for manually created FeignClient. Here’s how to add it manually:

// The default is logger.nooplogger
                .logger(new Slf4jLogger(OrderClient.class))
                // The default is logger.level.none
                .logLevel(Logger.Level.FULL)
Copy the code

How to run

The modules of this project are built by Spring Boot, which can be directly started by running Main method in the compiler.

  1. Start openfeign – registry – server

Openfeign-registry-server starts Eureka Server for subsequent OpenFeignServer and OpenFeignClient to register.

  1. Start the openfeign – server

  2. Start openfeign – client

  3. Test openFeignClient

Get request url: http://localhost:8000/getUserName1

Check the log to see the output.

Code address of this project: Spring-cloud-Openfeign-demo

See flydean’s blog for more tutorials