spring cloud 通過feign請求設置請求頭


本文為博主原創,轉載請注明出處:

  spring cloud 服務組件之間通過feign 的方式請求,會攜帶很少的基礎類型的消息頭參數,比如Content-Type等,但不會攜帶自定義或指定的請求頭參數,

在實際的開發過程中,需要對從網關或其他服務組件使用feign請求時,攜帶原始請求的請求頭,並做一些基礎校驗和業務校驗等。

  1.如果要在服務使用feign請求過程中,攜帶請求的原始請求頭信息時,需要是請求處於同一個線程,這樣才能在使用feign請求時,才能獲取到當前請求的

原始請求頭。在使用feignClient請求時,默認是會新建線程,去執行服務請求,如果新建線程,則會解析不到原始請求的請求頭。需要對hystrix 進行一下的配置,

才能保證處於同一個線程當中。

hystrix默認使用多線程管理請求連接池,從主線程到發送基於hystrix的feign請求線程已不在同一個線程內。可通過設置策略區分是否為同一個線程。

  strategy: SEMAPHORE 基於信號量,前后會保持同一個線程。strategy: THREAD 基於異步線程,前后為不同的線程

 

hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          strategy: SEMAPHORE
          thread:
            timeoutInMilliseconds: 60000

添加以上配置,可以對feignClient 進行消息頭的配置,

  2.由於feign 請求底層是通過 RestTemplate 進行請求,Feign 支持請求攔截器,在發送請求前,可以對發送的模板進行操作,例如設置請求頭等屬性,

自定請求攔截器需要實現 feign.RequestInterceptor 接口,該接口的方法 apply 有參數 template ,該參數類型為 RequestTemplate,我們可以根據實際情況對請求信息進行調整,

 對消息頭的封裝,可以使用攔截器進行一下的封裝:

package com.imooc.homepage.config;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;

@Configuration
public class FeignConfiguration  implements RequestInterceptor{
    @Override
    public void apply(RequestTemplate template) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 對消息頭進行配置
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                String values = request.getHeader(name);
                template.header(name, values);
            }
        }
        // 對請求體進行配置
        Enumeration<String> bodyNames = request.getParameterNames();
        StringBuffer body =new StringBuffer();
        if (bodyNames != null) {
            while (bodyNames.hasMoreElements()) {
                String name = bodyNames.nextElement();
                String values = request.getParameter(name);
                body.append(name).append("=").append(values).append("&");
            }
        }
        if(body.length()!=0) {
            body.deleteCharAt(body.length()-1);
            template.body(body.toString());
        }
    }

}

3.對FeignClient添加以上配置,進行請求:

@FeignClient(value = "client-homepage-course", fallback = CourseClientHystrix.class,configuration = FeignConfiguration.class)
public interface CourseClient {

    @RequestMapping(value = "/homepage-course/get/courses", method = RequestMethod.POST)
    List<CourseInfo> getCourseInfos(@RequestBody CourseInfosRequest request);
}

 

  在服務中配置 FeignConfiguration 時,上面的代碼示例是通過 RequestContextHolder.getRequestAttributes() 解析到當前請求頭的參數,

RequestContextHolder是基於ThreadLocal實現的,所以需要保證請求是一直處於同一個線程當中,hystrix強大在於是支持此擴展操作的。

  另一種解決方案:由於所解析的模塊沒有添加spring-web相關的依賴配置,無法使用 RequestContextHolder ,使用 過濾器過濾出當前

線程中的請求頭,並保存到ThreadLocal 中,在 FeignConfiguration 中解析 保存在ThreadLocal中的消息頭參數,然后設置消息頭給RestTemplate.  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM