使用OpenFeign实现服务远程调用

发布于:2025-04-06 ⋅ 阅读:(16) ⋅ 点赞:(0)

在微服务架构中,由于业务功能的分工不同,我们把项目拆分为多个独立的服务,并常常将其部署在不同的服务器上,这个时候如果服务A的某个功能需要借助服务B来实现,那么这个时候如何去调用就成了问题,目前有一种常用的服务调用方法OpenFeign,用其可以实现服务之间的调用。

使用方法

1.原理

        当一个服务通过openfeign向另一个服务发起远程调用时,feign会发起一个http请求,请求路径就是配置的url,服务A先将这个请求发往nacos,nacos根据服务发起者定义的服务目标名称寻找对应的服务,并将请求转发过去,并响应结果。

2.环境准备

        我们要实现服务的调用,首先需要让他们之间互相能够发现彼此的存在,所以我们这里采用nacos作为服务的注册发现。

        将服务A(serverA)和服务B(serverB)注册到nacos当中

        在它们的pom文件中添加以下依赖(nacos当中若配置了其他的属性需要再添加如nacos-config等依赖)

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

3.操作流程

        假设我们需要让服务A调用服务B的某个方法,我们首先在服务A的pom文件中添加如下依赖

<!-- Spring Cloud 微服务远程调用 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
        <!--feign支持Multipart格式传参-->
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form</artifactId>
            <version>3.8.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form-spring</artifactId>
            <version>3.8.0</version>
        </dependency>

以下是实现远程调用的一个样例

假设我们的需要调用服务B的接口方法是这样的

public class ServerBController {

    @Autowired
    ServerBService serverBservice;

    @RequestMapping(value = "/media/upload/coursefile", consumes = MediaType.MULTIPART_FORM_DATA_VALU)
    public UploadFileResultDto upload(@RequestPart("filedata") MultipartFile multipartFile,
                                      @RequestParam(value= "objectName",required=false) String objectName) throws IOException {
        //文件信息
        UploadFileParamDto uploadFileParamDto = new UploadFileParamDto();
        //原始文件名称
        uploadFileParamDto.setFilename(multipartFile.getOriginalFilename());
        //文件大小
        uploadFileParamDto.setFileSize(multipartFile.getSize());
        //文件类型
        uploadFileParamDto.setFileType("001001");
        //获取文件
        File TempFile = File.createTempFile("md5", ".temp");
        multipartFile.transferTo(TempFile);

        Long companyId = 1L;
        //文件路径
        String absolutePath = TempFile.getAbsolutePath();
        //上传图片
        return mediaFileService.uploadMediaFile(companyId,uploadFileParamDto,absolutePath,objectName);
    }

}

我们在服务A的类路径下创建一个包“feignClient”,在其下面创建一个远程调用接口ServerBClient

                           //这里为可选项,配置文件为你想要实现的功能     //fallback逻辑(可选)
@FeignClient(value = "ServerB",configuration = MultipartSupportConfig.class,fallbackFactory = MediaServiceClientFallbackFactory.class)
public interface ServerBClient {

 //这里要和被调用处的接口路径保持一致
 @RequestMapping(value = "/media/upload/coursefile",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
 String upload(@RequestPart("filedata") MultipartFile upload,@RequestParam(value = "objectName",required=false) String objectName);
}

注意在这个接口中的抽象类需要和被调用处的方法的请求方式、请求路径、参数都要保持一致

在FeignClient中定义的configuration和fallbackFactory需要自己定义,可以先删掉不写

在服务A的启动类上加上这个注解,表示启动服务远程调用

//将其中的包路径替换为你的包路径
@EnableFeignClients(basePackages={"com.enjoylearning.content.feignClient"})

 这个时候我们启动服务A和服务B,让其在nacos中的服务列表中出现。

假设我们在服务A的Service层中需要调用服务B的这个方法,那么我们应该这样调用

@Service
public class ServiceAServiceImpl implements ServiceAService {

    @Autowired
    private ServerBClient serverBClient;  //将远程调用接口注入

    @Override
    private void yourFunction(){
        //  ...  你的业务逻辑
        
        //这里通过注入的feignClient接口调用服务B的upload方法
        serverBClient.upload(参数A,参数B);        

        //  ...  你的业务逻辑 
    }
}

最后服务A将能够正常的调用服务B的方法。

对于configuration和fallback等内容,我将在后续的篇幅中进行讲解使用方式和原理