欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringCloud OpenFeign Post請求400錯誤解決方案

 更新時間:2020年09月30日 09:36:58   投稿:yaominghui  
這篇文章主要介紹了SpringCloud OpenFeign Post請求400錯誤解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

在微服務開發(fā)中SpringCloud全家桶集成了OpenFeign用于服務調用,SpringCloud的OpenFeign使用SpringMVCContract來解析OpenFeign的接口定義。 但是SpringMVCContract的Post接口解析實現(xiàn)有個巨坑,就是如果使用的是@RequestParam傳參的Post請求,參數(shù)是直接掛在URL上的。

問題發(fā)現(xiàn)與分析

最近線上服務器突然經常性出現(xiàn)CPU高負載的預警,經過排查發(fā)現(xiàn)日志出來了大量的OpenFeign跨服務調用出現(xiàn)400的錯誤(HTTP Status 400)。

一般有兩種情況:

  • nginx 返回400
  • java應用返回400

通過分析發(fā)現(xiàn)400是java應用返回的,那么可以確定是OpenFeign客戶端發(fā)起跨服務請求時出現(xiàn)異常了。 但是查看源碼發(fā)現(xiàn)出現(xiàn)這個問題的服務接口非常簡單,就是一個只有三個參數(shù)的POST請求接口,這個錯誤并不是必現(xiàn)的錯誤,而是當參數(shù)值比較長(String)的時候才會出現(xiàn)。 所以可以初步確認可能是參數(shù)太長導致請求400,對于POST請求因參數(shù)太長導致400錯誤非常疑惑,POST請求除非把參數(shù)掛在URL上,否則不應該出現(xiàn)400才對。

問題排查

為了驗證上面的猜測,手寫了一個簡單的示例,在驗證過程中特意開啟了OpenFeign的debug日志。

首先編寫服務接口

這是一個簡單的Post接口,僅有一個參數(shù)(這里的代碼僅用于驗證,非正式代碼)

@FeignClient(name = "user-service-provider")
public interface HelloService {
  @PostMapping("/hello")
  public String hello(@RequestParam("name") String name);
}

編寫服務

服務這里隨便寫一個Http接口即可(同上,代碼僅用于驗證)

@SpringBootApplication
@RestController
public class Starter {
  @RequestMapping("/hello")
  public String hello(String name) {
    return "User服務返回值:Hello " + String.valueOf(name);
  }
	
  public static void main(String[] args) {
    SpringApplication.run(Starter.class, args);
  }
}

服務注冊并調用

將服務注冊到注冊中心上,通過調用hello服務

@Autowired
public HelloService helloService;	
@RequestMapping("/hello")
public String hello(String name) {
  return helloService.hello(name);
}

通過日志可以發(fā)現(xiàn),SpringCloud集成OpenFeign的POST請求確實是直接將參數(shù)掛在URL上,如下圖:

正是因為這個巨坑,導致了線上服務器經常性高CPU負載預警。

問題解決

問題知道了,那么就好解決了,用SpringCloud官方的說法是可以使用@RequestBody來解決這個問題,但是@RequestBody的使用是有限制的,也就是參數(shù)只能有一個,而且需要整個調用鏈路都做相應的調整,這個代價有點高,這里不采用這種方式,而是采用RequestInterceptor來處理。

編寫RequestInterceptor

這里將request的queryLine取下來放在body中,需要注意的是,只有body沒有值的時候才能這么做。

public class PostRequestInterceptor implements RequestInterceptor {
  @Override
  public void apply(RequestTemplate template) {
    if ("post".equalsIgnoreCase(template.method()) && template.body() == null) {
      String query = template.queryLine();
      template.queries(new HashMap<>());
      if (StringUtils.hasText(query) && query.startsWith("?")) {
        template.body(query.substring(1));
      }
      template.header("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
    }
  }
}

配置RequestInterceptor

feign:
client:
config:
default:
requestInterceptors: cn.com.ava.yaolin.springcloud.demo.PostRequestInterceptor

在下圖可以看出請求參數(shù)不再掛在URL上了

@RequestBody的解決方案

問題雖然解決了,但采用的不是官方推薦的方案,這里將官方推薦的這種@RequestBody的解決方法也貼出來。 使用@RequestBody解決,需要4個步驟:

編寫請求參數(shù)Bean

public class HelloReqForm {
  private String name;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

調整接口聲明

@PostMapping("/hello")
public String hello(@RequestBody HelloReqForm form);

調整服務調用

HelloReqForm form = new HelloReqForm();
form.setName(name);
return helloService.hello(form);

調整服務實現(xiàn)

@RequestMapping("/hello")
public String hello(@RequestBody HelloReqForm form) {
}

最終調用日志

涉及的Java類

最后列出一些涉及的java類:

  • SpringMVCContract 服務接口
  • RequestParamParameterProcessor 參數(shù)
  • feign.RequestTemplate Rest請求構造器
  • feign.Request 處理http請求

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Mybatis單個參數(shù)的if判斷報異常There is no getter for property named ''xxx'' in ''class java.lang.Integer''的解決方案

    Mybatis單個參數(shù)的if判斷報異常There is no getter for property named ''x

    今天小編就為大家分享一篇關于Mybatis單個參數(shù)的if判斷報異常There is no getter for property named 'xxx' in 'class java.lang.Integer'的解決方案,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • 淺談SpringMVC中Interceptor和Filter區(qū)別

    淺談SpringMVC中Interceptor和Filter區(qū)別

    這篇文章主要介紹了淺談SpringMVC中Interceptor和Filter區(qū)別,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-04-04
  • java求數(shù)組元素重復次數(shù)和java字符串比較大小示例

    java求數(shù)組元素重復次數(shù)和java字符串比較大小示例

    這篇文章主要介紹了java求數(shù)組元素重復次數(shù)和java字符串比較大小示例,需要的朋友可以參考下
    2014-04-04
  • 世界著名程序SpringMVC完整過程

    世界著名程序SpringMVC完整過程

    這篇文章主要為大家介紹了世界著名程序SpringMVC實現(xiàn)過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • Java開發(fā)學習之Bean的作用域和生命周期詳解

    Java開發(fā)學習之Bean的作用域和生命周期詳解

    這篇文章主要介紹了淺談Spring中Bean的作用域,生命周期和注解,從創(chuàng)建到消亡的完整過程,例如人從出生到死亡的整個過程就是一個生命周期。本文將通過示例為大家詳細講講,感興趣的可以學習一下
    2022-06-06
  • java弱口令檢測機制解析

    java弱口令檢測機制解析

    這篇文章主要介紹了java弱口令檢測機制,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 詳解Java如何實現(xiàn)自定義注解

    詳解Java如何實現(xiàn)自定義注解

    注解(Annotation),也叫元數(shù)據。一種代碼級別的說明。它是JDK1.5及以后版本引入的一個特性,與類、接口、枚舉是在同一個層次。本文將通過示例詳解Java如何實現(xiàn)自定義注解,需要的可以參考一下
    2022-06-06
  • SpringMvc根據返回值類型不同處理響應的方法

    SpringMvc根據返回值類型不同處理響應的方法

    這篇文章主要介紹了SpringMvc根據返回值類型不同處理響應,我們可以通過控制器方法的返回值設置跳轉的視圖,控制器支持如void,String,ModelAndView類型,需要的朋友可以參考下
    2023-09-09
  • Java基礎鞏固抽象類與接口詳解

    Java基礎鞏固抽象類與接口詳解

    在類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類稱為抽象類,接口是Java中最重要的概念之一,它可以被理解為一種特殊的類,不同的是接口的成員沒有執(zhí)行體,是由全局常量和公共的抽象方法所組成,本文給大家介紹Java抽象類和接口,感興趣的朋友一起看看吧
    2022-05-05
  • Spring?Boot?整合持久層之Spring Data JPA

    Spring?Boot?整合持久層之Spring Data JPA

    在介紹Spring Data JPA的時候,我們首先認識下Hibernate。Hibernate是數(shù)據訪問解決技術的絕對霸主,使用O/R映射技術實現(xiàn)數(shù)據訪問,O/R映射即將領域模型類和數(shù)據庫的表進行映射,通過程序操作對象而實現(xiàn)表數(shù)據操作的能力,讓數(shù)據訪問操作無須關注數(shù)據庫相關的技術
    2022-08-08

最新評論