feign项目中使用

POM.xml引入依赖


    org.springframework.cloud
    spring-cloud-starter-openfeign
    ${openfeign.version}
    
        
            commons-io
            commons-io
        
    

系统中的feign客户端

代码

@FeignClient(name = "user-service", url = "${lq.getewayIp}/api/user-service", configuration = FeignRequestConfiguration.class, fallback = UserFeignFallBack.class)
public interface UserFeign {

    /**
     * 获取登录信息
     */
    @GetMapping("/user/getLoginInfo")
    R getLoginInfo(@RequestParam(name = "token") String token);

    /**
     * 获取当前登录人的信息
     */
    @GetMapping("/user/getCurrentUserInfo")
    R getCurrentUserInfo();
}

注解说明

@FeignClient(name = "user-service", url = "${lq.getewayIp}/api/user-service", configuration = FeignRequestConfiguration.class, fallback = UserFeignFallBack.class)

## 解释
//@FeignClient:这是Feign客户端的注解。
//name = "user-service":定义Feign客户端的名称,这个名称通常与服务发现(例如nacos)中的服务名称匹配。
//url = "${lq.getewayIp}/api/user−service":定义Feign客户端的URL。这里使用了Spring的属性引用‘{lq.getewayIp},这意味着在运行时,lq.getewayIp`的值会被用来填充URL
//configuration = FeignRequestConfiguration.class:定义Feign客户端的配置类。你可以在这个FeignRequestConfiguration类中定义特定于这个Feign客户端的配置,例如请求/响应的序列化和反序列化、拦截器、拦截器等
//fallback = UserFeignFallBack.class:这是Feign客户端的fallback类,当调用目标服务失败时(例如由于网络问题、服务宕机等原因),Feign客户端会自动调用这个fallback类中的方法。这个类通常会处理失败的情况,例如返回默认值或执行重试策略等
## 总结
//这个注解定义了一个Feign客户端,用于与服务名为"user-service"的服务进行通信,并且提供了URL、配置和fallback等属性

feign请求拦截器

定义了如何定制Feign客户端的请求

这个拦截器的目的是从原始的HTTP请求中复制所有的头部信息(除了"content-length")到Feign客户端发出的请求中。这样,当使用Feign客户端发起请求时,它可以保持与原始HTTP请求相同的头部设置

代码与解释

// @Configuration:这是一个Spring的注解,表示该类是一个配置类,用于定义和配置Spring Bean。
@Configuration
//这定义了一个名为FeignRequestConfiguration的类,该类实现了RequestInterceptor接口。RequestInterceptor是Feign客户端的一个接口,用于拦截和处理请求
public class FeignRequestConfiguration implements RequestInterceptor {
    //这是RequestInterceptor接口中的apply方法,用于自定义请求。该方法接受一个RequestTemplate参数,这个参数代表了即将发出的请求。
    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //判断如果从定时任务发起的feign请求 是无法获取到request域的 所以做过滤判断为空的时候不往feign中组装任何request域的内容
        if (ObjectUtil.isNotEmpty(attributes)){
            // 设置请求头 从ServletRequestAttributes中获取实际的HTTP请求
            HttpServletRequest request = attributes.getRequest();
            //获取HTTP请求的所有头部名称
            Enumeration headerNames = request.getHeaderNames();
            if (headerNames != null) {
                while (headerNames.hasMoreElements()) {
                    //获取下一个头部名称
                    String name = headerNames.nextElement();
                    //获取该头部名称对应的值
                    String value = request.getHeader(name);
                    if (name.equals("content-length")){
                        continue;
                    }
                    //将获取到的头部名称和值添加到即将发出的Feign请求中
                    requestTemplate.header(name, value);
                }
            }
        }

    }
}

feign熔断实现类

这是一个使用Spring Cloud Feign的熔断(fallback)实现类。熔断是一种在分布式系统中应对故障的方法,当某个服务调用失败或响应过慢时,熔断机制可以阻止对该服务的进一步调用,以避免整个系统的崩溃

这个UserFeignFallBack类是当Feign客户端调用目标服务失败时的备选方案。当调用失败时,它不会尝试再次调用或等待,而是直接返回一个预定义的失败响应,状态码为20004,消息为"feign熔断"。这有助于防止系统的进一步崩溃,并允许系统以一种可控制的方式失败。

代码与解释

public class UserFeignFallBack implements UserFeign {
    @Override
    public R getLoginInfo(String token) {
        //当调用目标服务失败或超时时,这个熔断实现将返回这个失败响应
        return R.fail(20004, "feign熔断");
    }

    @Override
    public R getCurrentUserInfo() {
        return R.fail(20004, "feign熔断");
    }
}

nacos中配置

Feign结合了Ribbon和Hystrix,提供了客户端负载均衡和故障处理能力

这些配置为Feign客户端提供了各种超时设置、负载均衡策略和故障处理机制

feign:
  httpclient:   //这是关于HTTP客户端的配置
    connection-timer-repeat: 30000 //这表示如果连接失败,将尝试重新连接的时间间隔是30000毫秒,即30秒
###配置请求超时时间
hystrix: //Hystrix是Netflix开源的库,用于隔离、熔断和监控分布式系统的调用
  command:  //这指的是特定命令的配置,例如特定的Feign客户端方法。
    default:  // 这是默认的命令配置
      execution: //这是关于Hystrix执行流的配置
        isolation: // 这涉及到隔离Hystrix命令执行流的配置
          thread:  //这指的是使用线程来执行命令的配置
            timeout:  // 这指的是超时设置
              enabled: true  //这意味着线程超时是启用的
            timeoutInMilliseconds: 60000    //这设置了线程的超时时间为60秒

调用端服务

启动类配置

调用端在启动类上添加@EnableFeignClients注解

@SpringBootApplication
@EnableFeignClients(basePackages = {"cn.com.sinosoft.*"})
public class ManagementPlanApp {

    public static void main(String[] args){
        SpringApplication application = new SpringApplication(ManagementPlanApp.class);
        application.setApplicationStartup(new BufferingApplicationStartup(2048));
        application.run(args);
        System.out.println("启动成功");
    }
}

具体代码中调用

//注入
@Resource
        
private UserFeign userFeign;

//使用
R> specialDept = userFeign.findSpecialDeptByDeptName(deptNames);
if (specialDept.getCode() != 200) {
    log.error("获取部门信息失败 -> result={}", specialDept);
    throw new ServiceException("获取部门信息失败,请重新尝试");
}

List deptVoList = JSONObject.parseArray(JSONObject.toJSONString(specialDept.getData()), JSONObject.class);
    

gateway.yml中放行接口

下面的接口不拦截token,调用feign方法放开token拦截

# 不拦截token的接口 
no_filter_url: .*swagger-ui.html.*,.*/doc.html,.*/swagger-resources,.*/v2/api-docs,.*/webjars/.*,.*/favicon.ico,.*/admin.*,.*/auth/xcxLogin,.*/v3/api-docs.*,.*/getLoginInfo.*,.*/auth/xcxLogin.*,.*/file/upload.*,.*/exportData.*,.*/testReceivePosition.*,.*/testReceiveUser.*,.*/testReceiveOrg.*,.*/receiveUser.*,.*/receiveOrg.*,.*/receiveAccount.*,.*/receivePosition.*,.*/init/org.*,.*/init/org2.*,.*/init/role.*,.*/receiveItem.*,.*/test,.*/dept/findSonDept.*,.*/user/getUserId.*,.*/login.*,.*/packageZipByFolder.*,.*/downloadTemplate.*,.*/sms/message.*,.*/user/findSonUser.*,.*/user/findUser.*,.*/onlyoffice.*,.*/js.*,.*/css.*,.*/dept/findCompanyId.*,.*/editor.*,.*/viewer.*,.*/api/callback.*,.*/api/file.*,.*/dept/findProjectDept.*,.*/dept/findDept.*,.*/synchronizeUserInfo.*,.*/commentTemplatePrint.*,.*/api/before.*,.*/template.*,.*/issued.*,.*/authority.*,.*/opinion.*,.*/fileinfo.*,.*/file/download.*,.*/api/doc.*,.*/dept/findCompany.*,.*/dept/findSpecialDeptByDeptName.*,.*/user/getPersonnelUser.*,.*/user/getPersonnelAllUser.*

问题:

调用端服务调用feign接口时,服务参数请求头等是如何传递和处理的,feign的请求拦截器如何工作的?

服务参数和请求头的传递:

  • 当调用端服务使用 Feign 客户端发起请求时,它首先创建一个 Feign 接口的实例。这个接口定义了要调用的远程服务的方法。
  • 调用端服务在调用 Feign 接口方法时,会传入必要的参数。这些参数通常是通过方法参数来传递的,可以包括路径变量、查询参数、请求体等。
  • 同时,调用端服务可以设置请求头信息。这可以通过在 Feign 接口方法上使用注解(如 @RequestHeader)来实现,或者在创建 Feign 客户端时进行全局配置。

服务参数和请求头的处理:

  • Feign 客户端在接收到调用端服务的请求后,会根据接口方法的定义和传入的参数,构建 HTTP 请求。这包括确定请求的 URL、HTTP 方法(GET、POST 等)、请求头信息和请求体(如果有的话)。
  • 对于路径变量和查询参数,Feign 会将它们插入到请求的 URL 中。对于请求头,Feign 会将它们添加到 HTTP 请求的头部。
  • 一旦 HTTP 请求构建完成,Feign 客户端就会发送这个请求到远程服务。

Feign 请求拦截器的工作机制:

  • Feign 请求拦截器允许在发送 HTTP 请求之前或之后执行自定义逻辑。这可以用于实现认证、日志记录、性能监控等功能。
  • 要使用 Feign 请求拦截器,需要实现 RequestInterceptor 接口,并重写 apply 方法。在这个方法中,你可以访问和修改即将发送的 HTTP 请求。
  • 在 apply 方法中,你可以添加、修改或删除请求头信息,也可以修改请求的其他属性(如 URL、HTTP 方法等)。这使得请求拦截器非常灵活,可以根据需要定制请求的处理逻辑。
  • 配置了请求拦截器后,每次通过 Feign 客户端发起请求时,都会先经过拦截器的处理。这使得你可以在发送请求之前执行一些必要的准备工作,或在请求发送后执行一些后续处理逻辑

你可能感兴趣的:(java,spring,spring,boot)