MCPcopy Index your code
hub / github.com/crossoverJie/feign-plus

github.com/crossoverJie/feign-plus @v0.0.2

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.0.2 ↗ · + Follow
185 symbols 369 edges 32 files 44 documented · 24%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

feign-plus

A better feign client library to combine with SpringBoot.


Write Feign client with annotation, like this:

We can provider an interface.

@RequestMapping("/v1/demo")
@FeignPlusClient(name = "demo", url = "${feign.demo.url}", port = "${feign.demo.port}")
public interface DemoApi {
    @GetMapping("/id")
    String sayHello(@RequestParam(value = "id") Long id);

    @GetMapping("/id/{id}")
    String id(@PathVariable(value = "id") Long id);

    @PostMapping("/create")
    Order create(@RequestBody OrderCreateReq req);

    @GetMapping("/query")
    Order query(@SpringQueryMap OrderQueryDTO dto);
}

Now we can use it as we normally use SpringBoot.

@SpringBootApplication
@EnableFeignPlusClients(basePackages = "com.example.provider.api")
@RestController
public class DemoApplication {

    @Resource
    private DemoApi demoApi;

    @GetMapping(value = "/hello")
    public String hello() {
        demoApi.id(12L);
        demoApi.sayHello(34L);
        demoApi.create(new OrderCreateReq("100"));
        demoApi.query(new OrderQueryDTO("999", "zhangsan"));
        return "hello";
    }

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

}

Feature

  • [x] Request/Response/Exception log record.
  • [x] Custom interceptor.
  • [x] Micrometer support.
  • [x] Exception passing.

Interceptor

By default, the request log is logged using the debug level.

For custom interceptor you need to create a bean that extends the DefaultLogInterceptor.

Example usage:

@Component
@Slf4j
public class CustomFeignInterceptor extends DefaultLogInterceptor {
    @Override
    public void request(String target, String url, String body) {
        super.request(target, url, body);
        log.info("request");
    }

    @Override
    public void exception(String target, String url, FeignException feignException) {
        super.exception(target, url, feignException);
    }

    @Override
    public void response(String target, String url, Object response) {
        super.response(target, url, response);
        log.info("response");
    }
}

Exception passing

Custom exception like this:

@Data
public class DemoException extends RuntimeException {
    private String appName;
    private int code;
    private String debugStackTrace;
}    

Provier

When the provider throws an exception:

    @GetMapping("/query")
    public Order query(OrderQueryDTO dto) {
        log.info("dto = {}", dto);
        if (dto.getId().equals("1")) {
            throw new DemoException("provider test exception");
        }
        return new Order(dto.getId());
    }

consumer will get a return of HTTP_CODE = 500.

{
"appName": "provider-demo",
"code": 500,
"message": "provider test exception",
"debugStackTrace": "com.example.provider.api.exception.DemoException: provider test exception\n\tat com.exampl.provider.core.ProviderApplication.query(ProviderApplication.java:49)\n\tat"
}

Consumer

Configuring an exception decoder:

@Configuration
public class FeignExceptionConfig {
    @Bean
    public FeignErrorDecoder feignExceptionDecoder() {
        return (methodName, response, e) -> {
            HttpStatus status = JSONUtil.toBean(response, HttpStatus.class);
            return new DemoException(status.getAppName(), status.getCode(), status.getMessage(), status.getDebugStackTrace());
        };
    }
}

then the consumer can catch DemoException like local call:

    try {
        demoApi.query(new OrderQueryDTO(id, "zhangsan"));
    } catch (DemoException e) {
        log.error("feignCall:{}, sourceApp:[{}], sourceStackTrace:{}", e.getMessage(), e.getAppName(), e.getDebugStackTrace(), e);
    }

More configuration

feign:
  plus:
    connect-timeout: 11000
    max-idle-connections: 520
    read-timeout: 12000

Extension points exported contracts — how you extend this code

AnnotatedParameterProcessor (Interface)
Function: @author crossoverJie Date: 2022/2/10 00:14 @since JDK 11 [14 implementers]
src/main/java/top/crossoverjie/feign/plus/contract/AnnotatedParameterProcessor.java
Github (Interface)
Function: @author crossoverJie Date: 2020/7/25 02:54 @since JDK 11
src/test/java/top/crossoverjie/feign/test/Github.java
FeignLogInterceptor (Interface)
Function: @author crossoverJie Date: 2022/2/11 22:16 @since JDK 11 [2 implementers]
src/main/java/top/crossoverjie/feign/plus/log/FeignLogInterceptor.java
FeignErrorDecoder (Interface)
Function: @author crossoverJie Date: 2022/4/28 00:15 @since JDK 11 [2 implementers]
src/main/java/top/crossoverjie/feign/plus/decoder/FeignErrorDecoder.java
HttpEncoding (Interface)
Function: @author crossoverJie Date: 2022/2/10 00:22 @since JDK 11
src/main/java/top/crossoverjie/feign/plus/contract/HttpEncoding.java

Core symbols most depended-on inside this repo

value
called by 9
src/main/java/top/crossoverjie/feign/plus/contract/SpringMvcContract.java
getBean
called by 8
src/main/java/top/crossoverjie/feign/plus/springboot/FeignSpringContextHolder.java
request
called by 8
src/main/java/top/crossoverjie/feign/plus/log/FeignLogInterceptor.java
getMethodMetadata
called by 7
src/main/java/top/crossoverjie/feign/plus/contract/AnnotatedParameterProcessor.java
getParameterIndex
called by 7
src/main/java/top/crossoverjie/feign/plus/contract/AnnotatedParameterProcessor.java
setParameterName
called by 5
src/main/java/top/crossoverjie/feign/plus/contract/AnnotatedParameterProcessor.java
resolve
called by 4
src/main/java/top/crossoverjie/feign/plus/contract/SpringMvcContract.java
annotationType
called by 3
src/main/java/top/crossoverjie/feign/plus/contract/SpringMvcContract.java

Shape

Method 153
Class 26
Interface 6

Languages

Java100%

Modules by API surface

src/test/java/top/crossoverjie/feign/test/GitHubRes.java40 symbols
src/main/java/top/crossoverjie/feign/plus/contract/SpringMvcContract.java35 symbols
src/main/java/top/crossoverjie/feign/plus/springboot/FeignPlusConfigurationProperties.java11 symbols
src/main/java/top/crossoverjie/feign/plus/factory/FeignPlusBeanFactory.java10 symbols
src/main/java/top/crossoverjie/feign/plus/springboot/FeignPlusAutoConfiguration.java8 symbols
src/main/java/top/crossoverjie/feign/plus/contract/AnnotatedParameterProcessor.java8 symbols
src/main/java/top/crossoverjie/feign/plus/springboot/FeignSpringContextHolder.java7 symbols
src/main/java/top/crossoverjie/feign/plus/register/FeignPlusClientScanner.java7 symbols
src/main/java/top/crossoverjie/feign/plus/contract/FeignUtils.java5 symbols
src/main/java/top/crossoverjie/feign/plus/log/FeignLogInterceptor.java4 symbols
src/main/java/top/crossoverjie/feign/plus/log/DefaultLogInterceptor.java4 symbols
src/main/java/top/crossoverjie/feign/plus/contract/annotation/PathVariableParameterProcessor.java4 symbols

For agents

$ claude mcp add feign-plus \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact