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

Java中HTTP GET方法調(diào)用帶有body的問(wèn)題解決

 更新時(shí)間:2024年02月02日 08:50:00   作者:wy_df18  
這篇文章主要為大家詳細(xì)介紹了Java如何解決HTTP GET方法調(diào)用帶有body的問(wèn)題,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下

1.背景描述

上游服務(wù)提供的方法非常比較奇特,查詢(xún)接口,定義的GET方法,參數(shù)通過(guò)request body傳遞的,在使用Feign Client封裝GET方法調(diào)用時(shí),會(huì)遇到一個(gè)報(bào)錯(cuò),“405 Method Not Allowed”。通過(guò)查詢(xún),知道這個(gè)錯(cuò)誤原因是HTTP調(diào)用方法錯(cuò)誤,比如:定義的API是GET方法,通過(guò)POST方法(非GET方法)調(diào)用,就會(huì)返回這個(gè)錯(cuò)誤。

@RequestLine("GET /api/user/get/")
Object getUser(@HeaderMap Map headers, UserRequest request);

2.原因分析

奇怪代碼明明寫(xiě)得是使用GET方法啊,進(jìn)一步查資料,得知原因是Feign client框架本身有一個(gè)坑:Feign client框架,默認(rèn)情況下使用的是HttpURLConnection完成實(shí)際的http請(qǐng)求調(diào)用,但是HttpURLConnection本身不支持GET方法調(diào)用時(shí)帶有body,帶有body的調(diào)用方法,只能是POST方法。

// sun.net.www.protocol.http.HttpURLConnection
private synchronized OutputStream getOutputStream0() throws IOException {
try {
    if(!this.doOutput) {
        throw new ProtocolException("cannot write to a URLConnection if doOutput=false - call setDoOutput(true)");
    } else {
        if(this.method.equals("GET")) {
            this.method = "POST";
        }
// ........
}
}
}

HTTP GET方法調(diào)用,到底支不支持帶有body呢,HTTP協(xié)議是支持的,沒(méi)有禁止,但是呢,不建議這么做,不是一個(gè)良好的習(xí)慣,因?yàn)橛行g覽器

啥的可能不支持,這個(gè)時(shí)候,你寫(xiě)的方法就尷尬了。

Stackoverflow解釋如下:

In other words, any HTTP request message is allowed to contain a message body, and thus must parse messages with that in mind. Server semantics for GET, however,
are restricted such that a body, if any, has no semantic meaning to the request. The requirements on parsing are separate from the requirements on method semantics.
So, yes, you can send a body with GET, and no, it is never useful to do so.
This is part of the layered design of HTTP/1.1 that will become clear again once the spec is partitioned (work in progress).

3.解決方法

方案一

網(wǎng)上可以很容易搜索到這個(gè)解決方法,相關(guān)博客非常多,直接copy的情況,太嚴(yán)重了。但是實(shí)際驗(yàn)證,沒(méi)有生效,具體原因待排查。

1.yml配置文件中,加入feign的配置項(xiàng):feign.httpclient.enabled: true

2.增加如下maven依賴(lài)。

<dependency>
                <groupId>org.apache.httpcomponents</groupId>                   
                <artifactId>httpclient</artifactId>                   
                <version>4.5.3</version>             
            </dependency>
            <dependency>
                <groupId>com.netflix.feign</groupId>
                <artifactId>feign-httpclient</artifactId>
                <version>8.17.0</version>
            </dependency>

方案原理:HttpURLConnection不支持GET方法帶有body的調(diào)用,ApacheHttpClient支持GET方法帶有body的調(diào)用。這個(gè)配置,就是將feign client默認(rèn)使用的HTTP調(diào)用方式,從HttpURLConnection切換到ApacheHttpClient方式。

方法不生效原因:

1.可能HTTP調(diào)用方式?jīng)]有切換成功,也就是配置沒(méi)有生效。(確定是這個(gè)原因,因?yàn)槲沂褂玫腇eign方式:Feign.builder()默認(rèn)生成的就是HttpURLConnection方式的http請(qǐng)求調(diào)用。相關(guān)源碼如下:

  // feign.Feign.Builder
private Client client = new Client.Default(null, null);
// feign.Client.Default
final HttpURLConnection connection = (HttpURLConnection) new URL(request.url()).openConnection();

因此相關(guān)配置修改是不生效的,需要重新生成一個(gè)client才行,比如:ApacheHttpClient

2.可能ApacheHttpClient本身也不支持GET方法帶有body的請(qǐng)求。(因?yàn)橹苯邮褂肁pacheHttpClient,發(fā)現(xiàn)沒(méi)有支持GET方法帶有body的調(diào)用方式)

補(bǔ)充:(待驗(yàn)證,證明)

feign分別嘗試了Java原生URLConnection,OkHttp,ApacheHttpClient三種方式:

1.URLConnection 報(bào)405錯(cuò)誤,說(shuō)明http方法不對(duì),但是feign配置是GET方法,查feign的日志也是用的GET方法。后來(lái)發(fā)現(xiàn)原因是URLConnection在的

原因:對(duì)于有request body的GET方法,自動(dòng)改為POST方法了。

2.OkHttp 直接報(bào)錯(cuò):method GET must not have a request body.

3.ApacheHttpClient完美支持。

方案二

使用AsyncHttpClient,因?yàn)锳syncHttpClient支持GET方法帶有Body的調(diào)用。

網(wǎng)上也可以很容易搜索到這個(gè)解決方法,感覺(jué)都是復(fù)制粘貼的,沒(méi)有經(jīng)過(guò)驗(yàn)證和實(shí)證,內(nèi)容完全一樣,但是都缺少最關(guān)鍵的信息,沒(méi)有給出需要引用的jar包,怎么使用測(cè)試呢?而需要引用的jar包還不好找到,實(shí)在是大坑。

1.引入maven依賴(lài)

 <dependency>
                    <groupId>org.asynchttpclient</groupId>
                    <artifactId>async-http-client</artifactId>
                    <version>2.2.0</version>
             </dependency>

2.解決方法demo

public static String get(String url, String bodyData, Map<String, String> headers) throws Exception {
                // 構(gòu)建請(qǐng)求
                BoundRequestBuilder requestBuilder = asyncHttpClient.prepareGet(url).setBody(bodyData);
                headers.forEach(requestBuilder::addHeader);
                List<Response> list = new ArrayList<>();
                requestBuilder.execute()
                        .toCompletableFuture()
                        .thenAccept(list::add)
                        .join();
                if (list.isEmpty()) {
                    return null;
                }
                Response response = list.get(0);
                if (response.getStatusCode() != 200) {
                    return null;
                }
                return response.getResponseBody();
         }

備注1:

1.方法可以返回map,增加:new ObjectMapper().readValue(response.getResponseBody(), Map.class);

2.方法本身必須返回json 對(duì)象的string才行,不能是非json對(duì)象的string,否則解析異常。

備注2:

1.沒(méi)有body的get方法,去掉.setBody(bodyData)即可。

2.沒(méi)有header的get方法調(diào)用,去掉headers.forEach(requestBuilder::addHeader);即可。

4.總結(jié)

網(wǎng)上資源很多、很豐富,各種問(wèn)題解決方案很多,但是也存在很多缺陷,不去驗(yàn)證、實(shí)踐,根本不知道里面有問(wèn)題,因此不要隨便copy別人的博客,往往copy的博客本身就存在潛在的問(wèn)題,copy之前,請(qǐng)?jiān)囼?yàn)一下,證明方法是正確的,減少給需要同學(xué)的誤導(dǎo)。

到此這篇關(guān)于Java中HTTP GET方法調(diào)用帶有body的問(wèn)題解決的文章就介紹到這了,更多相關(guān)Java HTTP GET方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java設(shè)計(jì)模式之抽象工廠模式

    Java設(shè)計(jì)模式之抽象工廠模式

    這篇文章主要為大家詳細(xì)介紹了Java設(shè)計(jì)模式之抽象工廠模式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 淺談Java設(shè)計(jì)模式之原型模式知識(shí)總結(jié)

    淺談Java設(shè)計(jì)模式之原型模式知識(shí)總結(jié)

    Java原型模式主要用于創(chuàng)建重復(fù)的對(duì)象,同時(shí)又能保證性能,這篇文章就帶大家仔細(xì)了解一下原型模式的知識(shí),對(duì)正在學(xué)習(xí)java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • SpringBoot多租戶(hù)配置與實(shí)現(xiàn)示例

    SpringBoot多租戶(hù)配置與實(shí)現(xiàn)示例

    本文詳細(xì)介紹了在SpringBoot中實(shí)現(xiàn)多租戶(hù)架構(gòu)的方法和步驟,包括配置數(shù)據(jù)源、Hibernate攔截器、租戶(hù)解析器等,以共享數(shù)據(jù)庫(kù)、共享數(shù)據(jù)表的方式,確保數(shù)據(jù)隔離和安全性,感興趣的可以了解一下
    2024-09-09
  • Netty分布式pipeline管道傳播事件的邏輯總結(jié)分析

    Netty分布式pipeline管道傳播事件的邏輯總結(jié)分析

    這篇文章主要為大家介紹了Netty分布式pipeline管道傳播事件總結(jié)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • 在SpringBoot中實(shí)現(xiàn)一個(gè)訂單號(hào)生成系統(tǒng)的示例代碼

    在SpringBoot中實(shí)現(xiàn)一個(gè)訂單號(hào)生成系統(tǒng)的示例代碼

    在Spring Boot中設(shè)計(jì)一個(gè)訂單號(hào)生成系統(tǒng),主要考慮到生成的訂單號(hào)需要滿(mǎn)足的幾個(gè)要求:唯一性、可擴(kuò)展性、以及可能的業(yè)務(wù)相關(guān)性,本文給大家介紹了幾種常見(jiàn)的解決方案及相應(yīng)的示例代碼,需要的朋友可以參考下
    2024-02-02
  • Java高性能新一代構(gòu)建工具M(jìn)aven-mvnd(實(shí)踐可行版)

    Java高性能新一代構(gòu)建工具M(jìn)aven-mvnd(實(shí)踐可行版)

    這篇文章主要介紹了Java高性能新一代構(gòu)建工具M(jìn)aven-mvnd(實(shí)踐可行版),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • 在CentOS上配置Java環(huán)境變量的教程

    在CentOS上配置Java環(huán)境變量的教程

    這篇文章主要介紹了在CentOS上配置Java環(huán)境變量的教程,同時(shí)適用于Fedora等其他RedHat系的Linux系統(tǒng),需要的朋友可以參考下
    2015-06-06
  • 修改Springboot默認(rèn)序列化工具Jackson配置的實(shí)例代碼

    修改Springboot默認(rèn)序列化工具Jackson配置的實(shí)例代碼

    這篇文章主要介紹了如何修改Springboot默認(rèn)序列化工具Jackson的配置,當(dāng)Spring容器中存在多個(gè)同類(lèi)型的Bean時(shí),默認(rèn)情況下最后一個(gè)創(chuàng)建的Bean將作為首選Bean,文中通過(guò)代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-02-02
  • springBoot靜態(tài)資源加載不到,并且配置了也不生效問(wèn)題及解決

    springBoot靜態(tài)資源加載不到,并且配置了也不生效問(wèn)題及解決

    這篇文章總結(jié)了一個(gè)在Spring Boot 2.6.x版本中,由于路徑匹配策略改變導(dǎo)致靜態(tài)資源無(wú)法加載的問(wèn)題,并提供了解決方案:通過(guò)配置類(lèi)或在配置文件中設(shè)置路徑匹配策略為AntPathMatcher,或者直接降級(jí)Spring Boot版本
    2025-02-02
  • struts2中使用注解配置Action方法詳解

    struts2中使用注解配置Action方法詳解

    這篇文章主要介紹了struts2中使用注解配置Action方法詳解,涉及一個(gè)示例,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10

最新評(píng)論