[Special topic on Fegin technology] "Original ecology" opened the beginning of Fegin's RPC technology. Would you use the original ecology of Fegin? (superior)

Prerequisites

  • Feign is the invocation framework of the service consumer in Spring Cloud, usually used in combination with ribbon, hystrix, etc.
  • Due to legacy reasons, in some projects, the entire system is not a SpringCloud project, or even a Spring project, and users only focus on simplifying the writing of http call codes.
  • * If you use a relatively heavy framework such as httpclient or okhttp, the amount of coding and learning curve will be a challenge for beginners, but using RestTemplate in spring, there is no configuration solution, so I think whether it can be separated from Spring cloud , using Feign independently.

brief introduction

Feign makes it easier to write Java HTTP clients. Feign is inspired by Retrofit, JAXRS-2.0 and WebSocket. Feign was originally designed to reduce the complexity of uniformly binding Denominator to HTTP API, regardless of whether it supports Restful. Feign aims to connect to the HTTP API with minimal resources and code. Arbitrary HTTP APIs can be written with customizable decoders and error handling.

maven dependencies

  <dependency>
            <groupId>com.netflix.feigngroupId>
            <artifactId>feign-coreartifactId>
            <version>8.18.0version>
        dependency>
        <dependency>
            <groupId>com.netflix.feigngroupId>
            <artifactId>feign-jacksonartifactId>
            <version>8.18.0version>
        dependency>
        <dependency>
            <groupId>io.github.lukehutchgroupId>
            <artifactId>fast-classpath-scannerartifactId>
            <version>2.18.1version>
	   dependency>
	   <dependency>
    	<groupId>com.netflix.feigngroupId>
    	<artifactId>feign-jacksonartifactId>
        <version>8.18.0version>
    dependency>
复制代码

Define configuration class

RemoteService service = Feign.builder()
            .options(new Options(1000, 3500))
            .retryer(new Retryer.Default(5000, 5000, 3))
			.encoder(new JacksonEncoder())
            .decoder(new JacksonDecoder())
            .target(RemoteService.class, "http://127.0.0.1:8085");
复制代码
  • The options method specifies the connection timeout and response timeout
  • The retryer method specifies the retry strategy
  • The target method binds the interface with the server address.
  • The return type is the bound interface type.

custom interface

Randomly define a service interface for remote calls, and declare related interface parameters and request addresses.

Specify the HTTP protocol and URL address through @RequestLine


public class User{
    
    
   String userName;
}

public interface RemoteService {
    
    

    User getOwner(User user);

    public User getOwner( User user,
         String requestToken,
         Long userId,
         String userName);
}
复制代码

service provider

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

public class UserController {
    
    

    public User list( User user) throws InterruptedException{
    
    
        System.out.println(user.getUsername());
        user.setId(100L);
        user.setUsername(user.getUsername().toUpperCase());
        return user;
    }
}
复制代码

transfer

Call the interface wrapped by feign in the same way as calling the local method, and directly obtain the return value provided by the remote service.

String result = service.getOwner(new User("scott"));
复制代码

Two problems with native Feign

  1. Native Feign can only parse one interface at a time and generate the corresponding request proxy object. If there are multiple call interfaces in a package, it is very troublesome to parse it multiple times.
  2. The call proxy generated by Feign is just an ordinary object, how to register it in Spring so that we can use @Autowired to inject at any time.

solution:

  1. For the problem of multiple parsing, you can scan the package path by specifying, and then parse the classes in the package in turn.
  2. Implement the BeanFactoryPostProcessor interface to extend the functions of the Spring container.

define an annotation class

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public  FeignApi {
    
    

String serviceUrl();
}
复制代码

Generate Feign proxy and register to Spring implementation class:

import feign.Feign;
import feign.Request;
import feign.Retryer;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
import io.github.lukehutch.fastclasspathscanner.scanner.ScanResult;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import java.util.List;

public class FeignClientRegister implements BeanFactoryPostProcessor{
    
    

    private String  scanPath="com.xxx.api";

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    
    
        List classes = scan(scanPath);
        if(classes==null){
    
    
            return ;
        }
        System.out.println(classes);
        Feign.Builder builder = getFeignBuilder();
        if(classes.size()>0){
    
    
            for (String claz : classes) {
    
    
                Class targetClass = null;
                try {
    
    
                    targetClass = Class.forName(claz);
                    String url=targetClass.getAnnotation(FeignApi.class).serviceUrl();
                    if(url.indexOf("http://")!=0){
    
    
                        url="http://"+url;
                    }
                    Object target = builder.target(targetClass, url);
                    beanFactory.registerSingleton(targetClass.getName(), target);
                } catch (Exception e) {
    
    
                    throw new RuntimeException(e.getMessage());
                }
            }
        }
    }

    public Feign.Builder getFeignBuilder(){
    
    
        Feign.Builder builder = Feign.builder()
                .encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
                .options(new Request.Options(1000, 3500))
                .retryer(new Retryer.Default(5000, 5000, 3));
        return builder;
    }

    public List scan(String path){
    
    
        ScanResult result = new FastClasspathScanner(path).matchClassesWithAnnotation(FeignApi.class, (Class aClass) -> {
    
    
        }).scan();
        if(result!=null){
    
    
            return result.getNamesOfAllInterfaceClasses();
        }
        return  null;
    }
}
复制代码
Call interface writing example:
import com.xiaokong.core.base.Result;
import com.xiaokong.domain.DO.DeptRoom;
import feign.Headers;
import feign.Param;
import feign.RequestLine;
import com.xiaokong.register.FeignApi;

import java.util.List;

public interface RoomApi {
    
    

    Result selectById( String id);

    Result> selectList();
}
复制代码
Interface usage example:

public class ServiceImpl{
    
    

    private RoomApi roomApi;

    public void demo(){
    
    
        Result result = roomApi.selectById("1");
        System.out.println(result);
    }
}
复制代码

Precautions:

  1. If the interface returns a complex nested object, you must specify the generic type explicitly, because when Feign parses a complex object, it needs to obtain the generic type inside the object returned by the interface through reflection to correctly use Jackson to parse. If the type is not specified explicitly, Jackson will convert the json object into a LinkedHashMap type.
  2. If you are using Spring and need to call other people's interfaces through http, you can use this tool to simplify the operations of calling and parsing.

share resources

Information sharing
To obtain the above resources, please visit the open source project and click to jump

Guess you like

Origin blog.csdn.net/star20100906/article/details/132180379