openfeign整合springcloud get请求自动转成post

代码如下:

controller

   
    @Autowired
    private MasterDataService masterDataService;

    @GetMapping(value = "/getDepartsByCode")
    public Result<?> getDepartsByCode() {
        Map<String, String> departsByCode = masterDataService.getDepartsByCode("00000001");
        return Result.ok(departsByCode);
    }

feign service

@GetMapping(value = "/masterdata/efsMdWarehouse/getDepartsByCode")
public Map<String, String> getDepartsByCode(String code);

返回

{
  "success": true,
  "message": "操作成功!",
  "code": 200,
  "result": {
    "success": "false",
    "message": "不支持POST请求方法,支持以下GET、",
    "code": "405",
    "result": null,
    "languageList": null,
    "timestamp": "1636515842420"
  },
  "languageList": null,
  "timestamp": 1636515854016
}

debug 源码:

feign.ReflectiveFeign
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      if ("equals".equals(method.getName())) {
        try {
          Object otherHandler =
              args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
          return equals(otherHandler);
        } catch (IllegalArgumentException e) {
          return false;
        }
      } else if ("hashCode".equals(method.getName())) {
        return hashCode();
      } else if ("toString".equals(method.getName())) {
        return toString();
      }

      return dispatch.get(method).invoke(args);
    }
走invoke 之后进 SynchronousMethodHandler
  @Override
  public Object invoke(Object[] argv) throws Throwable {
    RequestTemplate template = buildTemplateFromArgs.create(argv);
    Options options = findOptions(argv);
    Retryer retryer = this.retryer.clone();
    while (true) {
      try {
        return executeAndDecode(template, options);
      } catch (RetryableException e) {
        try {
          retryer.continueOrPropagate(e);
        } catch (RetryableException th) {
          Throwable cause = th.getCause();
          if (propagationPolicy == UNWRAP && cause != null) {
            throw cause;
          } else {
            throw th;
          }
        }
        if (logLevel != Logger.Level.NONE) {
          logger.logRetry(metadata.configKey(), logLevel);
        }
        continue;
      }
    }
  }

走 return executeAndDecode(template, options) 进

Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
    Request request = targetRequest(template);

    if (logLevel != Logger.Level.NONE) {
      logger.logRequest(metadata.configKey(), logLevel, request);
    }

    Response response;
    long start = System.nanoTime();
    try {
      response = client.execute(request, options);
      // ensure the request is set. TODO: remove in Feign 12
      response = response.toBuilder()
          .request(request)
          .requestTemplate(template)
          .build();
    } catch (IOException e) {
      if (logLevel != Logger.Level.NONE) {
        logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));
      }
      throw errorExecuting(request, e);
    }
    long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);


    if (decoder != null)
      return decoder.decode(response, metadata.returnType());

    CompletableFuture<Object> resultFuture = new CompletableFuture<>();
    asyncResponseHandler.handleResponse(resultFuture, metadata.configKey(), response,
        metadata.returnType(),
        elapsedTime);

    try {
      if (!resultFuture.isDone())
        throw new IllegalStateException("Response handling not done");

      return resultFuture.join();
    } catch (CompletionException e) {
      Throwable cause = e.getCause();
      if (cause != null)
        throw cause;
      throw e;
    }
  }

response = client.execute(request, options);  执行请求

    @Override
    public Response execute(Request request, Options options) throws IOException {
      HttpURLConnection connection = convertAndSend(request, options);
      return convertResponse(connection, request);
    }

重点第一行 字面意思 转换并且发送

HttpURLConnection convertAndSend(Request request, Options options) throws IOException {
      final URL url = new URL(request.url());
      final HttpURLConnection connection = this.getConnection(url);
      if (connection instanceof HttpsURLConnection) {
        HttpsURLConnection sslCon = (HttpsURLConnection) connection;
        if (sslContextFactory != null) {
          sslCon.setSSLSocketFactory(sslContextFactory);
        }
        if (hostnameVerifier != null) {
          sslCon.setHostnameVerifier(hostnameVerifier);
        }
      }
      connection.setConnectTimeout(options.connectTimeoutMillis());
      connection.setReadTimeout(options.readTimeoutMillis());
      connection.setAllowUserInteraction(false);
      connection.setInstanceFollowRedirects(options.isFollowRedirects());
      connection.setRequestMethod(request.httpMethod().name());

      Collection<String> contentEncodingValues = request.headers().get(CONTENT_ENCODING);
      boolean gzipEncodedRequest =
          contentEncodingValues != null && contentEncodingValues.contains(ENCODING_GZIP);
      boolean deflateEncodedRequest =
          contentEncodingValues != null && contentEncodingValues.contains(ENCODING_DEFLATE);

      boolean hasAcceptHeader = false;
      Integer contentLength = null;
      for (String field : request.headers().keySet()) {
        if (field.equalsIgnoreCase("Accept")) {
          hasAcceptHeader = true;
        }
        for (String value : request.headers().get(field)) {
          if (field.equals(CONTENT_LENGTH)) {
            if (!gzipEncodedRequest && !deflateEncodedRequest) {
              contentLength = Integer.valueOf(value);
              connection.addRequestProperty(field, value);
            }
          } else {
            connection.addRequestProperty(field, value);
          }
        }
      }
      // Some servers choke on the default accept string.
      if (!hasAcceptHeader) {
        connection.addRequestProperty("Accept", "*/*");
      }

      if (request.body() != null) {
        if (disableRequestBuffering) {
          if (contentLength != null) {
            connection.setFixedLengthStreamingMode(contentLength);
          } else {
            connection.setChunkedStreamingMode(8196);
          }
        }
        connection.setDoOutput(true);
        OutputStream out = connection.getOutputStream();
        if (gzipEncodedRequest) {
          out = new GZIPOutputStream(out);
        } else if (deflateEncodedRequest) {
          out = new DeflaterOutputStream(out);
        }
        try {
          out.write(request.body());
        } finally {
          try {
            out.close();
          } catch (IOException suppressed) { // NOPMD
          }
        }
      }
      return connection;
    }
  }

debug 观察 connetion.getMethod() 的值,

发现在  OutputStream out = connection.getOutputStream(); 这一行改成了post

进去看看

public synchronized OutputStream getOutputStream() throws IOException {
        this.connecting = true;
        SocketPermission var1 = this.URLtoSocketPermission(this.url);
        if (var1 != null) {
            try {
                return (OutputStream)AccessController.doPrivilegedWithCombiner(new PrivilegedExceptionAction<OutputStream>() {
                    public OutputStream run() throws IOException {
                        return HttpURLConnection.this.getOutputStream0();
                    }
                }, (AccessControlContext)null, var1);
            } catch (PrivilegedActionException var3) {
                throw (IOException)var3.getException();
            }
        } else {
            return this.getOutputStream0();
        }
    }

走进 return this.getOutputStream0(); 最终源码看见了

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";
                }

                if ("TRACE".equals(this.method) && "http".equals(this.url.getProtocol())) {
                    throw new ProtocolException("HTTP method TRACE doesn't support output");
                } else if (this.inputStream != null) {
                    throw new ProtocolException("Cannot write output after reading input.");
                } else {
                    if (!this.checkReuseConnection()) {
                        this.connect();
                    }

                    boolean var1 = false;
                    String var8 = this.requests.findValue("Expect");
                    if ("100-Continue".equalsIgnoreCase(var8) && this.streaming()) {
                        this.http.setIgnoreContinue(false);
                        var1 = true;
                    }

                    if (this.streaming() && this.strOutputStream == null) {
                        this.writeRequests();
                    }

                    if (var1) {
                        this.expect100Continue();
                    }

                    this.ps = (PrintStream)this.http.getOutputStream();
                    if (this.streaming()) {
                        if (this.strOutputStream == null) {
                            if (this.chunkLength != -1) {
                                this.strOutputStream = new HttpURLConnection.StreamingOutputStream(new ChunkedOutputStream(this.ps, this.chunkLength), -1L);
                            } else {
                                long var3 = 0L;
                                if (this.fixedContentLengthLong != -1L) {
                                    var3 = this.fixedContentLengthLong;
                                } else if (this.fixedContentLength != -1) {
                                    var3 = (long)this.fixedContentLength;
                                }

                                this.strOutputStream = new HttpURLConnection.StreamingOutputStream(this.ps, var3);
                            }
                        }

                        return this.strOutputStream;
                    } else {
                        if (this.poster == null) {
                            this.poster = new PosterOutputStream();
                        }

                        return this.poster;
                    }
                }
            }
        } catch (RuntimeException var5) {
            this.disconnectInternal();
            throw var5;
        } catch (ProtocolException var6) {
            int var2 = this.responseCode;
            this.disconnectInternal();
            this.responseCode = var2;
            throw var6;
        } catch (IOException var7) {
            this.disconnectInternal();
            throw var7;
        }
    }

这里是get请求 就改成post了

总结:

        如果request的body里有数据 就认为非get请求 ,即使用了@GetMapping 注解 也是会改成post的

        解决: 加 @RequestParam 注解 ,把参数拼接到url后就可以了

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Spring Cloud Gateway中添加POST请求参数,可以使用Spring Cloud Gateway的过滤器来修改请求体。下面是一个示例过滤器,它将“name”参数添加到POST请求请求体中: ```java @Component public class AddNameToRequestBodyFilter implements GlobalFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { if (exchange.getRequest().getMethod() == HttpMethod.POST) { return DataBufferUtils.join(exchange.getRequest().getBody()) .flatMap(dataBuffer -> { byte[] bytes = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(bytes); DataBufferUtils.release(dataBuffer); String body = new String(bytes, StandardCharsets.UTF_8); body += "&name=yourName"; //添加name参数 byte[] newBytes = body.getBytes(StandardCharsets.UTF_8); Flux<DataBuffer> newBody = Flux.just(exchange.getResponse().bufferFactory().wrap(newBytes)); ServerHttpRequest request = exchange.getRequest().mutate().body(newBody).build(); return chain.filter(exchange.mutate().request(request).build()); }); } else { return chain.filter(exchange); } } } ``` 在上面的示例中,我们检查请求的HTTP方法是否为POST。如果是,则通过`DataBufferUtils.join`将请求体中的所有数据缓冲区连接起来,并将其转换为字符串。然后,我们添加“name”参数,将请求体转换回字节数组,并创建一个新的Flux DataBuffer对象来包含新的请求体。最后,我们使用`ServerHttpRequest.mutate`方法创建一个新的请求对象,其中包含新的请求体,并将其传递给下一个过滤器。如果请求的HTTP方法不是POST,则直接调用`chain.filter(exchange)`传递请求。 需要注意的是,这只是一个简单的示例,你需要根据自己的业务逻辑来修改和完善这个过滤器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值