Java 8调用PATCH请求报Invalid HTTP method错误,求解决方案
问题描述
尝试在Java 1.8.0_171环境下,向ClientApp的REST API发送PATCH请求时,触发java.net.ProtocolException: Invalid HTTP method: PATCH错误。曾尝试使用X-HTTP-Method-Override请求头但未成功,且受组织限制无法升级Java版本。
代码示例
package com.in.Test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Base64; public class ConnectToCorbion { public static void main(String[] args) throws IOException { String PATCH_PARAMS = "[ { \"op\": \"replace\", \"path\": \"/optionalFields1/text1\", \"value\": \"SR234568\", \"from\" : \"string\" }]"; String my_url = "https://uat.clientapp.com/api/ChangeActivities"; byte[] patchData = PATCH_PARAMS.getBytes( StandardCharsets.UTF_8 ); URL obj = null; System.out.println("BEFORE"); obj = new URL(my_url); System.out.println("AFTER"); String username = "username"; String password = "password"; HttpURLConnection patchConnection = null; System.out.println("BEFORE openConnection"); try { patchConnection = (HttpURLConnection) obj.openConnection(); } catch (IOException e) { e.printStackTrace(); } System.out.println("AFTER openConnection"); patchConnection.setRequestMethod("PATCH"); //patchConnection.setRequestProperty("X-HTTP-Method-Override", "PATCH"); patchConnection.setRequestProperty("Accept", "application/json"); patchConnection.setRequestProperty("Content-Type", "application/json-patch+json"); patchConnection.setRequestProperty("messageType", "application/json-patch+json"); // Basic Auth for Java 8+ patchConnection.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString( (username + ":" + password).getBytes() ) ); patchConnection.setDoOutput(true); OutputStream os = null; System.out.println("BEFORE getOutputStream"); os = patchConnection.getOutputStream(); System.out.println("AFTER getOutputStream"); os.write(PATCH_PARAMS.getBytes()); os.flush(); os.close(); int responseCode = patchConnection.getResponseCode(); System.out.println("Response Code : " + responseCode); if (responseCode == HttpURLConnection.HTTP_CREATED) { //success BufferedReader in = new BufferedReader(new InputStreamReader( patchConnection.getInputStream())); String inputLine; StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); System.out.println(response.toString()); } else { System.out.println("PATCH NOT WORKING"); } } }
错误日志
BEFORE AFTER BEFORE openConnection AFTER openConnection Exception in thread "main" java.net.ProtocolException: Invalid HTTP method: PATCH at java.net.HttpURLConnection.setRequestMethod(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.setRequestMethod(Unknown Source) at sun.net.www.protocol.https.HttpsURLConnectionImpl.setRequestMethod(Unknown Source) at com.in.Test.ConnectToCorbion.main(ConnectToCorbion.java:44)
解决方案
问题根源
Java 8的HttpURLConnection默认仅支持GET、POST、HEAD、OPTIONS、PUT、DELETE这些HTTP方法,直接调用setRequestMethod("PATCH")会触发方法校验失败,抛出ProtocolException。
方案1:反射绕过方法限制
通过反射修改HttpURLConnection内部的method字段,绕过内置的方法校验逻辑,适用于Java 8u171版本:
// 替换原代码中的patchConnection.setRequestMethod("PATCH"); try { java.lang.reflect.Field methodField = HttpURLConnection.class.getDeclaredField("method"); methodField.setAccessible(true); methodField.set(patchConnection, "PATCH"); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); }
注意:该方法依赖JDK内部实现,若后续小版本更新修改了字段名或访问权限可能失效,但对于当前指定版本稳定可用。
方案2:正确使用X-HTTP-Method-Override请求头
若目标API服务器支持X-HTTP-Method-Override机制,需发送POST请求并添加该头来模拟PATCH请求,同时保持请求体和Content-Type不变:
// 替换原setRequestMethod("PATCH"),改用POST patchConnection.setRequestMethod("POST"); // 添加方法覆盖头 patchConnection.setRequestProperty("X-HTTP-Method-Override", "PATCH");
注意:必须确认目标服务器已配置支持该请求头,否则无法触发PATCH逻辑。
方案3:使用兼容Java 8的第三方HTTP客户端库
若允许引入第三方依赖,推荐使用Apache HttpClient 4.x或OkHttp 3.x,它们原生支持PATCH方法且完全兼容Java 8:
Apache HttpClient示例
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPatch; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import java.nio.charset.StandardCharsets; import java.util.Base64; // 初始化客户端 CloseableHttpClient client = HttpClientBuilder.create().build(); HttpPatch patch = new HttpPatch(my_url); // 设置请求头 patch.setHeader("Accept", "application/json"); patch.setHeader("Content-Type", "application/json-patch+json"); String auth = Base64.getEncoder().encodeToString((username + ":" + password).getBytes()); patch.setHeader("Authorization", "Basic " + auth); // 设置请求体 StringEntity entity = new StringEntity(PATCH_PARAMS, StandardCharsets.UTF_8); patch.setEntity(entity); // 执行请求并处理响应 CloseableHttpResponse response = client.execute(patch); int responseCode = response.getStatusLine().getStatusCode(); // 此处添加响应解析逻辑 client.close(); response.close();
OkHttp示例
import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import java.nio.charset.StandardCharsets; import java.util.Base64; // 初始化客户端 OkHttpClient client = new OkHttpClient(); // 构建请求体和请求 RequestBody body = RequestBody.create(PATCH_PARAMS, MediaType.parse("application/json-patch+json")); String auth = Base64.getEncoder().encodeToString((username + ":" + password).getBytes()); Request request = new Request.Builder() .url(my_url) .patch(body) .addHeader("Accept", "application/json") .addHeader("Authorization", "Basic " + auth) .build(); // 执行请求并处理响应 Response response = client.newCall(request).execute(); int responseCode = response.code(); // 此处添加响应解析逻辑 response.close();
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

