Java调用外部REST请求的几种办法
发布时间:2021-12-02 14:30:21 所属栏目:大数据 来源:互联网
导读:1 restTemplate spring 提供 特点: 1、RestOperations 提供了各种封装方法,非常方便直接将返回转成实体类。 2、默认使用JDK 的HttpURLConnection进行通信,但是可以通过RestTemplate.setRequestFactory 切换到不同的HTTP源:如Apache HttpComponents、Nett
1 restTemplate — spring 提供 特点: 1、RestOperations 提供了各种封装方法,非常方便直接将返回转成实体类。 2、默认使用JDK 的HttpURLConnection进行通信,但是可以通过RestTemplate.setRequestFactory 切换到不同的HTTP源:如Apache HttpComponents、Netty、OkHttp。 3、支持同步、异步请求; 4、支持更多的定制,比如拦截器等。 ps:支持 get 请求,参数是 body 的形式。 参考:https://www.huaweicloud.com/a... 国外知名博客Baeldung的博客 The Guide to RestTemplate: https://www.baeldung.com/rest... 1.1 底层是java的HttpURLConnection(默认使用,可以定制) 所有的请求都需要执行 doExecute() 方法 @Nullable protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException { Assert.notNull(url, "URI is required"); Assert.notNull(method, "HttpMethod is required"); ClientHttpResponse response = null; Object var14; try { // 创建请求 ClientHttpRequest request = this.createRequest(url, method); if (requestCallback != null) { requestCallback.doWithRequest(request); } response = request.execute(); this.handleResponse(url, method, response); var14 = responseExtractor != null ? responseExtractor.extractData(response) : null; } catch (IOException var12) { String resource = url.toString(); String query = url.getRawQuery(); resource = query != null ? resource.substring(0, resource.indexOf(63)) : resource; throw new ResourceAccessException("I/O error on " + method.name() + " request for "" + resource + "": " + var12.getMessage(), var12); } finally { if (response != null) { response.close(); } } return var14; } HttpAccessor 创建请求 public abstract class HttpAccessor { ... // 省略代码无数 protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException { // 使用 ClientHttpRequestFactory 创建请求 ClientHttpRequest request = this.getRequestFactory().createRequest(url, method); if (this.logger.isDebugEnabled()) { this.logger.debug("HTTP " + method.name() + " " + url); } return request; } } ClientHttpRequestFactory接口的具体实现,如:SimpleClientHttpRequestFactory 创建请求 public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { // 使用 HttpURLConnection 创建请求 HttpURLConnection connection = this.openConnection(uri.toURL(), this.proxy); this.prepareConnection(connection, httpMethod.name()); return (ClientHttpRequest)(this.bufferRequestBody ? new SimpleBufferingClientHttpRequest(connection, this.outputStreaming) : new SimpleStreamingClientHttpRequest(connection, this.chunkSize, this.outputStreaming)); } 1.2 post 请求,返回直接封装为实体 RestTemplate restTemplate = new RestTemplate(); HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar")); Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.class); assertThat(foo, notNullValue()); assertThat(foo.getName(), is("bar")); 1.3 get请求,但是参数是body形式 一般 get 请求,不支持 body 传参。 参考:https://stackoverflow.com/que... HTTP GET with a body is a somewhat unconventional construct that falls in a gray area of the HTTP specification - the end result is that many older pieces of software either cannot handle such a request at all, or will explicitly reject it because they believe it to be malformed. 带有body参数的HTTP GET是一种非传统的构造,属于HTTP规范的灰色区域。最终的结果是,许多旧的软件要么根本不能处理这样的请求,要么会明确拒绝,因为他们认为它是格式错误的请求。 /** * 注意:get请求,但是参数是body形式 * * @param url * @param paramBody * @return */ private String getWithBody(String url, Map<String, Object> paramBody) { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); HttpEntity requestEntity = new HttpEntity(JsonUtil.of(paramBody), httpHeaders); RestTemplate template = getTemplate(); ResponseEntity response = template.exchange(url, HttpMethod.GET, requestEntity, String.class); Object result = response.getBody(); logger.info("/invokeThirdPartyRequest/getWithBody/result/[{}]", result.toString()); return result.toString(); } /** * 获取 RestTemplate * * @return */ private RestTemplate getTemplate() { RestTemplate restTemplate = new RestTemplate(); //修改restTemplate的RequestFactory使其支持Get携带body参数 restTemplate.setRequestFactory(new HttpComponentsClientRestfulHttpRequestFactory()); return restTemplate; } import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpUriRequest; import org.springframework.http.HttpMethod; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import java.net.URI; public class HttpComponentsClientRestfulHttpRequestFactory extends HttpComponentsClientHttpRequestFactory { @Override protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) { if (httpMethod == HttpMethod.GET) { return new HttpGetRequestWithEntity(uri); } return super.createHttpUriRequest(httpMethod, uri); } /** * 定义HttpGetRequestWithEntity实现HttpEntityEnclosingRequestBase抽象类,以支持GET请求携带body数据 */ private static final class HttpGetRequestWithEntity extends HttpEntityEnclosingRequestBase { public HttpGetRequestWithEntity(final URI uri) { super.setURI(uri); } @Override public String getMethod() { return HttpMethod.GET.name(); } } } 2 HttpUtil — hutool 提供 HttpUtil 其实是 HttpRequest 的封装。 它支持各种封装好的get、post、put请求。 2.1 get 请求 public static String get(String urlString, Charset customCharset) { return ((HttpRequest)HttpRequest.get(urlString).charset(customCharset)).execute().body(); } public static String get(String urlString) { return get(urlString, HttpGlobalConfig.timeout); } public static String get(String urlString, int timeout) { return HttpRequest.get(urlString).timeout(timeout).execute().body(); } // form 表单格式的入参 public static String get(String urlString, Map<String, Object> paramMap) { return HttpRequest.get(urlString).form(paramMap).execute().body(); } // form 表单格式的入参,并设置超时时间 public static String get(String urlString, Map<String, Object> paramMap, int timeout) { return HttpRequest.get(urlString).form(paramMap).timeout(timeout).execute().body(); } 2.2 post 请求 这些请求最终调用的都是 HttpRequest 的 execute() 方法。 // form 表单格式的入参 public static String post(String urlString, Map<String, Object> paramMap) { return post(urlString, paramMap, HttpGlobalConfig.timeout); } // form 表单格式的入参,并设置超时时间 public static String post(String urlString, Map<String, Object> paramMap, int timeout) { return HttpRequest.post(urlString).form(paramMap).timeout(timeout).execute().body(); } // body 格式入参 public static String post(String urlString, String body) { return post(urlString, body, HttpGlobalConfig.timeout); } // body 格式入参,并设置超时时间 public static String post(String urlString, String body, int timeout) { return HttpRequest.post(urlString).timeout(timeout).body(body).execute().body(); } 2.3 一个例子 Map<String, Object> param = new HashMap<>(); param.put("userId", userId); String res = HttpUtil.post(url, JsonUtil.of(param)); 3 HttpRequest — hutool 提供 HttpRequest 提供了非常方便构造请求的构造函数。当参数比较多、header比较多的时候,可以使用这种方式。(这里使用了构造模式) 3.1 底层是Java的HttpURLConnection HttpRequest 底层又是使用了 java 提供的 HttpURLConnection 上源码: 最终都需要执行这个execute方法,这个方法调用了hutool封装的HttpConnection,这个HttpConnection又使用了java提供的HttpURLConnection。 // hutool 执行方法 public HttpResponse execute(boolean isAsync) { this.urlWithParamIfGet(); this.initConnection(); this.send(); HttpResponse httpResponse = this.sendRedirectIfPossible(); if (null == httpResponse) { httpResponse = new HttpResponse(this.httpConnection, this.charset, isAsync, this.isIgnoreResponseBody()); } return httpResponse; } public class HttpConnection { private final URL url; private final Proxy proxy; // 这个连接 HttpURLConnection ,是java提供的 private HttpURLConnection conn; ...// 省略无数代码 } 3.2 一个例子 private String invoke(String url, String isMock, Map<String, Object> map) { String result = HttpRequest.post(url).body(JSONUtil.toJsonStr(map)).execute().body(); return result; } (编辑:济南站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐