# CloseFeign **Repository Path**: tasfe/CloseFeign ## Basic Information - **Project Name**: CloseFeign - **Description**: 仿照OpenFeign写的声明式REST客户端RPC框架 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-05-10 - **Last Updated**: 2023-05-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # CloseFeign
展开/收起 缘由是前天在刷知乎的时候看到这样一个问题:[为什么说Feign是伪RPC?](https://www.zhihu.com/question/298707085) 有些评论里的回答过于逆天,总是在拿传输层TCP协议和应用层HTTP协议比较这明显是认知有偏差,其实无论是下面哪种组合,本质上都是告知对方要执行哪个方法,什么参数,对方执行完后返回结果 [1] 应用层协议HTTP + HttpClient [2] 应用层协议自定义/HTTP2 + 使用Netty自己构建的Client 首先说明个人观点,我觉得在Feign它是REST客户端的同时也能完成RPC的功能,因为不但支持服务发现并且在用法上和Dubbo,Montan等RPC框架几乎无异,都是不需要关注接口的具体实现即可完成远程服务方法的调用。 简述过程:向IOC容器中注入带有注解的接口类型对象(动态代理生成),当执行FeignClient Bean中的方法时会触发代理对象Invoke()方法向远端发送请求,然后返回结果,这样就对于使用者屏蔽了服务发现和网络通信的细节,让使用者像调用本地接口一样简单。 正好最近在改之前写的自定义应用层协议RPC的各种bug,用Netty构建服务端,客户端实现双方通信写麻了,所以我就在想试试写一下Feign这种以访问对方暴露出HTTP REST接口的方式远程调用的框架,写个小demo由于不知道这个框架叫什么,众所周知SpringCloud有个组件叫OpenFeign,所以就叫CloseFeign了(狗头)
## demo https://github.com/Raccoon-a/CloseFeign/tree/main/demo ## Getting started 进入目录转存至本地maven仓库供其他项目使用 `cd .\CloseFeign\CloseFeign-core\target\` `$ mvn install:install-file -Dfile=spring-cloud-starter-CloseFeign-1.0.0-jar-with-dependencies.jar -DgroupId=cn.rylan -DartifactId=spring-cloud-starter-CloseFeign -Dversion=1.0.0 -Dpackaging=jar` ```xml cn.rylan spring-cloud-starter-CloseFeign 1.0.0 ``` ```yaml server: port: 4000 spring: application: name: test cloud: close-feign: #负载均衡配置 [随机random - 轮询roundRobin] balancer: roundRobin nacos: discovery: server-addr: 127.0.0.1:8848 ``` ```java @SpringBootApplication @EnableCloseFeign(basePackages = {"com.example.server.feign"}) public class TestServerApplication { public static void main(String[] args) { SpringApplication.run(TestServerApplication.class, args); } } ``` ```java @CloseFeignClient(serviceName = "core-application") public interface FeignClient { @FeignRequestMapping(uri = "/material/id/1", type = "GET") CommonReturnType getById(); @FeignRequestMapping(uri = "/material/id/{id}", type = "GET") CommonReturnType getById(@PathVariable("id") Long id ); @FeignRequestMapping(uri = "/material/names", type = "POST") CommonReturnType getBatch(@RequestBody List names); @FeignRequestMapping(uri = "/material/test", type = "POST") CommonReturnType test(@RequestBody Material material); } ``` ```java @RestController public class TestController { @Autowired FeignClient feignClient; @GetMapping("/test") public CommonReturnType test() { var list = List.of("西红柿", "玉米"); System.out.println("getBatch: " + feignClient.getBatch(list)); System.out.println(feignClient.test(new Material(1001L, "material", "icon", "分类", "desc"))); return feignClient.getByName("西红柿"); } } ``` ```java @Bean public RequestInterceptor interceptor() { return new RequestInterceptor() { @Override public void apply(RequestTemplate template) { var requestAttributes = RequestContextHolder.getRequestAttributes(); assert requestAttributes != null; var request = ((ServletRequestAttributes) requestAttributes).getRequest(); var cookie = request.getHeader("Cookie"); var headers = new HttpHeaders(); headers.add("Cookie", cookie); headers.setAcceptCharset(Collections.singletonList(StandardCharsets.UTF_8)); headers.setContentType(MediaType.APPLICATION_JSON); template.setHeaders(headers); } }; } ```