代码如下:
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后就可以了