当前位置: 首页 > 后端技术 > Java

Java调用外部REST请求的几种方式

时间:2023-04-02 10:17:09 Java

1restTemplate—spring提供的特性:1.RestOperations提供了各种封装方法,直接将return转为实体类非常方便。2、默认使用JDK的HttpURLConnection进行通信,但可以通过RestTemplate.setRequestFactory切换到不同的HTTP源:如ApacheHttpComponents、Netty、OkHttp。3.支持同步和异步请求;4.支持更多的自定义,比如拦截器。ps:支持GET请求,参数为body形式。参考:https://www.huaweicloud.com/a...国外知名博主Baeldung的RestTemplate指南:https://www.baeldung.com/rest...1.1底层是java的HttpURLConnection(默认使用,可自定义)所有请求都需要执行doExecute()方法@NullableprotectedTdoExecute(URIurl,@NullableHttpMethodmethod,@NullableRequestCallbackrequestCallback,@NullableResponseExtractorresponseExtractor)throwsRestClientException{Assert.notNull(url,"URI是必需的");Assert.notNull(method,"需要HttpMethod");ClientHttpResponse响应=null;对象var14;try{//创建请求ClientHttpRequestrequest=this.createRequest(url,method);如果(requestCallback!=null){requestCallback.doWithRequest(请求);}response=request.execute();this.handleResponse(网址,方法,响应);var14=responseExtractor!=null?responseExtractor.extractData(响应):空;}catch(IOExceptionvar12){字符串资源=url.toString();字符串查询=url.getRawQuery();资源=查询!=空?resource.substring(0,resource.indexOf(63)):资源;thrownewResourceAccessException("I/Oerroron"+method.name()+"requestfor\""+resource+"\":"+var12.getMessage(),var12);}finally{if(response!=null){response.close();}}returnvar14;}HttpAccessor创建请求publicabstractclassHttpAccessor{...//省略无数代码.toryRequest()网址、方法);如果(this.logger.isDebugEnabled()){this.logger.debug("HTTP"+method.name()+""+url);}返回请求;}}ClientHttpRequestFactory接口的具体实现,如:SimpleClientHttpRequestFactorycreaterequestpublicClientHttpRequestcreateRequest(URIuri,HttpMethodhttpMethod)throwsIOException{//使用HttpURLConnection创建请求HttpURLConnectionconnection=this.openConnection(uri.toURL(),this.proxy);this.prepareConnection(connection,httpMethod.name());return(ClientHttpRequest)(this.bufferRequestBody?newSimpleBufferingClientHttpRequest(connection,this.outputStreaming):newSimpleStreamingClientHttpRequest(connection,this.chunkSize,this.outputStreaming));}1.2post请求,return直接封装为实体RestTemplaterestqueTemplate=newRestTemplateEnt()=newHttpEntity<>(newFoo("bar"));Foofoo=restTemplate.postForObject(fooResourceUrl,request,Foo.class);assertThat(foo,notNullValue());assertThat(foo.getName(),是("酒吧"));1.3get请求,但参数为body形式,属于一般get请求,不支持body传参参考:https://stackoverflow.com/que...带有正文的HTTPGET是一种有点非常规的构造,属于HTTP规范的灰色区域-最终结果是许多旧软件要么无法处理这样的请求,或者会明确拒绝它,因为他们认为它是畸形的。带有正文参数的HTTPGET是一种非常规构造,属于HTTP规范的灰色区域。最终的结果是很多旧软件要么根本无法处理这样的请求,要么会明确拒绝它,因为他们认为这是一个格式错误的请求。/***注意:get请求,但是是参数是body形式**@paramurl*@paramparamBody*@return*/privateStringgetWithBody(Stringurl,MapparamBody){HttpHeadershttpHeaders=newHttpHeaders();httpHeaders.setContentType(MediaType.APPLICATION_JSON);httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));HttpEntityrequestEntity=newHttpEntity(JsonUtil.of(paramBody),httpHeaders);RestTemplate模板=getTemplate();ResponseEntityresponse=template.exchange(url,HttpMethod.GET,requestEntity,String.class);对象结果=response.getBody();logger.info("/invokeThirdPartyRequest/getWithBody/result/[{}]",result.toString());returnresult.toString();}/***获取RestTemplate**@return*/privateRestTemplategetTemplate(){RestTemplaterestTemplate=newRestTemplate();//修改restTemplate的RequestFactory使其支持Get携带体参数restTemplate.setRequestFactory(newHttpComponentsClientRestfulHttpRequestFacto里());返回restTemplate;}导入org.apache.http.client.methods.HttpEntityEnclosingRequestBase;导入org.apache.http.client.methods.HttpUriRequest;导入org.springframework.http.HttpMethod;导入org.springframework.http.client.HttpComponentsClientHttpRequestFactory;importjava.net.URI;publicclassHttpComponentsClientRestfulHttpRequestFactoryextendsHttpComponentsClientHttpRequestFactory{@OverrideprotectedHttpUriRequestcreateHttpUriRequest(HttpMethodhttpMethod,URIuri){if(httpMethod==HttpMethod.GET){返回新的HttpGetRequestWithEntity(uri);}返回super.createHttpUriRequest(httpMethod,uri);}/***定义HttpGetRequestWithEntity实现HttpEntityEnclosingRequestBase抽像类,以支持GET请求携带body数据*/privatestaticfinalclassHttpGetRequestWithEntityextendsHttpEntityEnclosingRequestBase{publicHttpGetRequestWithEntity){uri.}@OverridepublicStringgetMethod(){返回HttpMethod.GET.name();}}}2HttpUtil—hutool提供了HttpUtil,其实就是对HttpRequest的封装。它支持各种封装的get、post、put请求。2.1获取请求publicstaticStringget(StringurlString,CharsetcustomCharset){return((HttpRequest)HttpRequest.get(urlString).charset(customCharset)).execute().body();}publicstaticStringget(StringurlString){returnget(urlString,HttpGlobalConfig.timeout);}publicstaticStringget(StringurlString,inttimeout){returnHttpRequest.get(urlString).timeout(timeout).execute().body();}//表单表单格式输入参数publicstaticStringget(StringurlString,MapparamMap){returnHttpRequest.get(urlString).form(paramMap).execute().body();}//form格式输入参数,并设置超时时间);}2.2post请求这些请求最后调用的是HttpRequest的execute()方法。//表单格式输入参数publicstaticStringpost(StringurlString,MapparamMap){returnpost(urlString,paramMap,HttpGlobalConfig.timeout);}//表单格式输入参数,并设置超时时间publicstaticStringpost(StringurlString,MapparamMap,inttimeout){returnHttpRequest.post(urlString).form(paramMap).timeout(timeout).execute().body();}//body格式输入参数publicstaticStringpost(StringurlString,Stringbody){returnpost(urlString,body,HttpGlobalConfig.timeout);}//body格式输入参数,并设置超时时间publicstaticStringpost(StringurlString,Stringbody,inttimeout){returnHttpRequest.post(urlString).timeout(timeout).body(body).execute().body();}2.3示例Mapparam=newHashMap<>();param.put("userId",userId);Stringres=HttpUtil.post(url,JsonUtil.of(param));3HttpRequest—hutool提供了HttpRequest为构造请求提供了一个非常方便的构造函数。当参数和header比较多的时候可以使用这种方法。(这里使用构造方式)3.1底层是Java的HttpURLConnectionHttpRequest。底层使用java提供的HttpURLConnection源码:最后需要执行execute方法。该方法调用了hutool封装的HttpConnection,这个HttpConnection使用的是Java提供的HttpURLConnection。//hutool执行方法publicHttpResponseexecute(booleanisAsync){this.urlWithParamIfGet();这个.initConnection();这个。发送();HttpResponsehttpResponse=this.sendRedirectIfPossible();if(null==httpResponse){httpResponse=newHttpResponse(this.httpConnection,this.charset,isAsync,this.isIgnoreResponseBody());}returnhttpResponse;}publicclassHttpConnection{privatefinalURL;privatefinalProxy代理;//这个连接HttpURLConnection是私有的,由javaHttpURLConnectionconn提供;...//省略无数代码}3.2示例privateStringinvoke(Stringurl,StringisMock,Mapmap){Stringresult=HttpRequest.post(url).body(JSONUtil.toJsonStr(map)).execute().body();返回结果;}