您现在的位置是:亿华云 > 应用开发

手撸了一个网络请求工具类,开发速度迅速提升了300%

亿华云2025-10-03 02:15:08【应用开发】2人已围观

简介一、简介在上一篇文章中,我们详细的介绍了RestTemplate工具类的用法,相比直接使用Apache的HttpClient进行网络传输,采用RestTemplate开发代码确实简化了很多,甚至可以做

一、手撸速度简介

在上一篇文章中,个网我们详细的络请介绍了RestTemplate工具类的用法,相比直接使用Apache的求工HttpClient进行网络传输,采用RestTemplate开发代码确实简化了很多,具类甚至可以做到傻瓜式操作,迅速但是提升基于当前的团队人员开发习惯,我们可不可以继续基于RestTemplate再做一层封装呢?手撸速度以便于操作Http网络请求,更加简单、个网便捷!

答案是络请肯定的!

手撸了一个网络请求工具类,开发速度迅速提升了300%

本文要介绍的这个工具类,就是求工小编基于RestTemplate做了一层代码封装,里面涵盖了GET、具类POST、迅速PUT、提升DELETE、手撸速度文件上传与下载等等方法,同时支持自定义头部传参,通过灵活的传参,可以满足绝大部分业务场景下的网络请求场景!

手撸了一个网络请求工具类,开发速度迅速提升了300%

同时,在上一篇介绍RestTemplate的《真不是我吹,Spring里这款牛逼的云服务器网络工具库我估计你都没用过!》文章里,我们还漏掉了一个最常用的场景,假如返回的对象,是一个范型类型,该怎么处理?

手撸了一个网络请求工具类,开发速度迅速提升了300%

在本篇的文章里,我们也会详细的介绍这种问题的处理方法!

废话也不多说,直接上代码,希望对网友们能有所帮助!

二、代码实践

下面以SpringBoot项目为例,如果是Spring项目,操作也类似,在配置类初始化的时候,实例化一个RestTemplate。

首先添加httpclient依赖包,作为RestTemplate底层客户端

org.apache.httpcomponents

httpclient

4.5.6

接着创建一个配置,初始化RestTemplate@Configuration

public class HttpConfiguration {

/

**

* 没有实例化RestTemplate时,初始化RestTemplate

* @return

*/

@ConditionalOnMissingBean(RestTemplate.class)

@Bean

public RestTemplate restTemplate(){

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());

return restTemplate;

}

/

**

* 使用HttpClient作为底层客户端

* @return

*/

private ClientHttpRequestFactory getClientHttpRequestFactory() {

int timeout = 5000;

RequestConfig config = RequestConfig.custom()

.setConnectTimeout(timeout)

.setConnectionRequestTimeout(timeout)

.setSocketTimeout(timeout)

.build();

CloseableHttpClient client = HttpClientBuilder

.create()

.setDefaultRequestConfig(config)

.build();

return new HttpComponentsClientHttpRequestFactory(client);

}

}然后,创建一个HttpTemplate工具类,将其生命周期交给Spring管理import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.core.ParameterizedTypeReference;

import org.springframework.http.*;

import org.springframework.stereotype.Component;

import org.springframework.util.LinkedMultiValueMap;

import org.springframework.util.MultiValueMap;

import org.springframework.web.client.RequestCallback;

import org.springframework.web.client.ResponseExtractor;

import org.springframework.web.client.RestTemplate;

import java.net.URI;

import java.util.Arrays;

import java.util.Map;

import java.util.Objects;

@Component

public class HttpTemplate {

private static final Logger log = LoggerFactory.getLogger(HttpTemplate.class);

@Autowired

private RestTemplate restTemplate;

/

**

* get请求,返回响应实体(响应业务对象不支持范型)

* 支持restful风格

* @param url

* @param headers

* @param responseType

* @param uriVariables

* @param

* @return

*/

public T get(String url, Mapheaders, ClassresponseType, Object... uriVariables){

ResponseEntityrsp = commonExchange(url, HttpMethod.GET, new HttpEntity<>(createHeaders(headers)), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* get请求,返回响应实体(响应业务对象支持范型)

* 支持restful风格

* @param url

* @param headers

* @param responseType

* @param uriVariables

* @param

* @return

*/

public T get(String url, Mapheaders, ParameterizedTypeReferenceresponseType, Object... uriVariables){

ResponseEntityrsp = commonExchange(url, HttpMethod.GET, new HttpEntity<>(createHeaders(headers)), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* post请求,form表单提交(响应业务对象不支持范型)

* 支持restful风格

* @param url

* @param headers

* @param paramMap

* @param responseType

* @param uriVariables

* @param

* @return

*/

public T postByFrom(String url, Mapheaders, MapparamMap, ClassresponseType, Object... uriVariables){

//指定请求头为表单类型

HttpHeaders httpHeaders = createHeaders(headers);

httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

ResponseEntityrsp = commonExchange(url, HttpMethod.POST, new HttpEntity<>(createBody(paramMap), httpHeaders), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* post请求,form表单提交(响应业务对象支持范型)

* 支持restful风格

* @param url

* @param headers

* @param paramMap

* @param responseType

* @param uriVariables

* @param

* @return

*/

public T postByFrom(String url, Mapheaders, MapparamMap, ParameterizedTypeReferenceresponseType, Object... uriVariables){

//指定请求头为表单类型

HttpHeaders httpHeaders = createHeaders(headers);

httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

ResponseEntityrsp = commonExchange(url, HttpMethod.POST, new HttpEntity<>(createBody(paramMap), httpHeaders), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* post请求,json提交(响应业务对象不支持范型)

* 支持restful风格

* @param url

* @param headers

* @param request

* @param responseType

* @param uriVariables

* @param

* @return

*/

public T postByJson(String url, Mapheaders, Object request, ClassresponseType, Object... uriVariables){

//指定请求头为json类型

HttpHeaders httpHeaders = createHeaders(headers);

httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);

ResponseEntityrsp = commonExchange(url, HttpMethod.POST, new HttpEntity<>(request, httpHeaders), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* post请求,json提交(响应业务对象支持范型)

* 支持restful风格

* @param url

* @param headers

* @param request

* @param responseType

* @param uriVariables

* @param

* @return

*/

public T postByJson(String url, Mapheaders, Object request, ParameterizedTypeReferenceresponseType, Object... uriVariables){

//指定请求头为json类型

HttpHeaders httpHeaders = createHeaders(headers);

httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);

ResponseEntityrsp = commonExchange(url, HttpMethod.POST, new HttpEntity<>(request, httpHeaders), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* post请求,云南idc服务商json提交,重定项

* 支持restful风格

* @param url

* @param headers

* @param request

* @param uriVariables

* @return

*/

public String postForLocation(String url, Mapheaders, Object request, Object... uriVariables){

//指定请求头为json类型

HttpHeaders httpHeaders = createHeaders(headers);

httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);

URI uri = restTemplate.postForLocation(url, new HttpEntity<>(request, httpHeaders), uriVariables);

if(Objects.nonNull(uri)){

return uri.toString();

}

return null;

}

/

**

* put请求,json提交(响应业务对象不支持范型)

* @param url

* @param headers

* @param request

* @param uriVariables

*/

public T put(String url, Mapheaders, Object request, ClassresponseType, Object... uriVariables){

//指定请求头为json类型

HttpHeaders httpHeaders = createHeaders(headers);

httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);

ResponseEntityrsp = commonExchange(url, HttpMethod.PUT, new HttpEntity<>(request, httpHeaders), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* put请求,json提交(响应业务对象支持范型)

* @param url

* @param headers

* @param request

* @param uriVariables

*/

public T put(String url, Mapheaders, Object request, ParameterizedTypeReferenceresponseType, Object... uriVariables){

//指定请求头为json类型

HttpHeaders httpHeaders = createHeaders(headers);

httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);

ResponseEntityrsp = commonExchange(url, HttpMethod.PUT, new HttpEntity<>(request, httpHeaders), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* delete请求(响应业务对象不支持范型)

* @param url

* @param headers

* @param uriVariables

* @return

*/

public T delete(String url, Mapheaders, ClassresponseType, Object... uriVariables){

ResponseEntityrsp = commonExchange(url, HttpMethod.DELETE, new HttpEntity<>(createHeaders(headers)), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* delete请求(响应业务对象支持范型)

* @param url

* @param headers

* @param uriVariables

* @return

*/

public T delete(String url, Mapheaders, ParameterizedTypeReferenceresponseType, Object... uriVariables){

ResponseEntityrsp = commonExchange(url, HttpMethod.DELETE, new HttpEntity<>(createHeaders(headers)), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* post请求,文件表单上传提交(响应业务对象不支持范型)

* 支持restful风格

* @param url

* @param headers

* @param paramMap

* @param responseType

* @param uriVariables

* @param

* @return

*/

public T uploadFile(String url, Mapheaders, MultiValueMapparamMap, ClassresponseType, Object... uriVariables){

//指定请求头为文件&表单类型

HttpHeaders httpHeaders = createHeaders(headers);

httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

ResponseEntityrsp = commonExchange(url, HttpMethod.POST, new HttpEntity<>(paramMap, httpHeaders), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* post请求,文件表单上传提交(响应业务对象支持范型)

* 支持restful风格

* @param url

* @param headers

* @param paramMap

* @param responseType

* @param uriVariables

* @param

* @return

*/

public T uploadFile(String url, Mapheaders, MultiValueMapparamMap, ParameterizedTypeReferenceresponseType, Object... uriVariables){

//指定请求头为文件&表单类型

HttpHeaders httpHeaders = createHeaders(headers);

httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

ResponseEntityrsp = commonExchange(url, HttpMethod.POST, new HttpEntity<>(paramMap, httpHeaders), responseType, uriVariables);

return buildResponse(rsp);

}

/

**

* 下载文件

* @param url

* @param headers

* @param uriVariables

* @return

*/

public byte[] downloadFile(String url, Mapheaders, Object... uriVariables){

ResponseEntityrsp = commonExchange(url, HttpMethod.GET, new HttpEntity<>(createHeaders(headers)), byte[].class, uriVariables);

return buildResponse(rsp);

}

/

**

* 下载大文件

* @param url

* @param headers

* @param responseExtractor

* @param uriVariables

*/

public void downloadBigFile(String url, Mapheaders, ResponseExtractor responseExtractor, Object... uriVariables){

RequestCallback requestCallback = request -> {

//指定请求头信息

request.getHeaders().addAll(createHeaders(headers));

//定义请求头的接收类型

request.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));

};

restTemplate.execute(url, HttpMethod.GET, requestCallback,responseExtractor, uriVariables);

}

/

**

* 公共http请求方法(响应业务对象不支持范型)

* @param url

* @param method

* @param requestEntity

* @param responseType

* @param uriVariables

* @param

* @return

*/

public ResponseEntitycommonExchange(String url, HttpMethod method, HttpEntity requestEntity, ClassresponseType, Object... uriVariables){

return restTemplate.exchange(url, method, requestEntity, responseType, uriVariables);

}

/

**

* 公共http请求方法(响应业务对象支持范型)

* @param url

* @param method

* @param requestEntity

* @param responseType

* @param uriVariables

* @param

* @return

*/

public ResponseEntitycommonExchange(String url, HttpMethod method, HttpEntity requestEntity, ParameterizedTypeReferenceresponseType, Object... uriVariables){

return restTemplate.exchange(url, method, requestEntity, responseType, uriVariables);

}

/

**

* 封装头部参数

* @param headers

* @return

*/

private HttpHeaders createHeaders(Mapheaders){

return new HttpHeaders(){ {

if(headers != null && !headers.isEmpty()){

headers.entrySet().forEach(item -> {

set(item.getKey(), item.getValue());

});

}

}};

}

/

**

* 封装请求体

* @param paramMap

* @return

*/

private MultiValueMapcreateBody(MapparamMap){

MultiValueMapvalueMap = new LinkedMultiValueMap<>();

if(paramMap != null && !paramMap.isEmpty()){

paramMap.entrySet().forEach(item -> {

valueMap.add(item.getKey(), item.getValue());

});

}

return valueMap;

}

/

**

* 返回响应对象

* @param rsp

* @param

* @return

*/

private T buildResponse(ResponseEntityrsp){

if(!rsp.getStatusCode().is2xxSuccessful()){

throw new RuntimeException(rsp.getStatusCode().getReasonPhrase());

}

return rsp.getBody();

}

}

最后,我们来做一下单元测试,使用案例如下,接口api还是基于上篇文章提供的服务@RunWith(SpringRunner.class)

@SpringBootTest

public class HttpControllerJunit {

@Autowired

private HttpTemplate httpTemplate;

/

**

* get请求测试

*/

@Test

public void testGet(){

//请求地址

String url = "http://localhost:8080/testGet";

//发起请求,直接返回对象

ResponseBean responseBean = httpTemplate.get(url, createHeader("get"), ResponseBean.class);

System.out.println(responseBean.toString());

}

/

**

* get请求测试,restful风格

*/

@Test

public void testGetByRestFul(){

//请求地址

String url = "http://localhost:8080/testGetByRestFul/{ 1}";

//发起请求,直接返回对象(restful风格)

ResponseBean responseBean = httpTemplate.get(url, createHeader("testGetByRestFul"), ResponseBean.class, "张三");

System.out.println(responseBean.toString());

}

/

**

* 模拟表单提交,post请求

*/

@Test

public void testPostByForm(){

//请求地址

String url = "http://localhost:8080/testPostByFormAndObj";

//表单参数

MapparamMap = new HashMap<>();

paramMap.put("userName", "唐三藏");

paramMap.put("userPwd", "123456");

//发起请求

ResponseBean responseBean = httpTemplate.postByFrom(url, createHeader("testPostByFormAndObj"), paramMap, ResponseBean.class);

System.out.println(responseBean.toString());

}

/

**

* 模拟JSON提交,post请求

*/

@Test

public void testPostByJson(){

//请求地址

String url = "http://localhost:8080/testPostByJson";

//入参

RequestBean request = new RequestBean();

request.setUserName("唐三藏");

request.setUserPwd("123456789");

//发送post请求,并打印结果,以String类型接收响应结果JSON字符串

ResponseBean responseBean = httpTemplate.postByJson(url, createHeader("testPostByJson"), request, ResponseBean.class);

System.out.println(responseBean.toString());

}

/

**

* 重定向,post请求,json方式提交

*/

@Test

public void testPostByLocation(){

//请求地址

String url = "http://localhost:8080/testPostByLocation";

//入参

RequestBean request = new RequestBean();

request.setUserName("唐三藏");

request.setUserPwd("123456789");

//用于提交完成数据之后的页面跳转

String uri = httpTemplate.postForLocation(url, createHeader("testPostByLocation"), request);

System.out.println(uri);

}

/

**

* put请求,json方式提交

*/

@Test

public void testPutByJson(){

//请求地址

String url = "http://localhost:8080/testPutByJson";

//入参

RequestBean request = new RequestBean();

request.setUserName("唐三藏");

request.setUserPwd("123456789000");

//模拟JSON提交,put请求

ResponseBean responseBean = httpTemplate.put(url, createHeader("testPutByJson"), request, ResponseBean.class);

System.out.println(responseBean.toString());

}

/

**

* delete请求,json方式提交

*/

@Test

public void testDeleteByJson(){

//请求地址

String url = "http://localhost:8080/testDeleteByJson";

//模拟JSON提交,delete请求

ResponseBean responseBean = httpTemplate.delete(url, createHeader("testDeleteByJson"), ResponseBean.class);

System.out.println(responseBean.toString());

}

/

**

* 文件上传,post请求

*/

@Test

public void uploadFile(){

//需要上传的文件

String filePath = "/Users/panzhi/Desktop/Jietu20220205-194655.jpg";

//请求地址

String url = "http://localhost:8080/upload";

//提交参数设置

MultiValueMapparam = new LinkedMultiValueMap<>();

param.add("uploadFile", new FileSystemResource(new File(filePath)));

//服务端如果接受额外参数,可以传递

param.add("userName", "张三");

ResponseBean responseBean = httpTemplate.uploadFile(url, createHeader("uploadFile"), param, ResponseBean.class);

System.out.println(responseBean.toString());

}

/

**

* 小文件下载

* @throws IOException

*/

@Test

public void downloadFile() throws IOException {

String userName = "张三";

String fileName = "f9057640-90b2-4f86-9a4b-72ad0e253d0d.jpg";

//请求地址

String url = "http://localhost:8080/downloadFile/{ 1}/{ 2}";

//发起请求,直接返回对象(restful风格)

byte[] stream = httpTemplate.downloadFile(url, createHeader("downloadFile"), userName,fileName);

// 将下载下来的文件内容保存到本地

String targetPath = "/Users/panzhi/Desktop/" + fileName;

Files.write(Paths.get(targetPath), Objects.requireNonNull(stream, "未获取到下载文件"));

}

/

**

* 大文件下载

* @throws IOException

*/

@Test

public void downloadBigFile() {

String userName = "张三";

String fileName = "f9057640-90b2-4f86-9a4b-72ad0e253d0d.jpg";

String targetPath = "/Users/panzhi/Desktop/" + fileName;

//请求地址

String url = "http://localhost:8080/downloadFile/{ 1}/{ 2}";

//对响应进行流式处理而不是将其全部加载到内存中

httpTemplate.downloadBigFile(url, createHeader("downloadBigFile"), clientHttpResponse -> {

Files.copy(clientHttpResponse.getBody(), Paths.get(targetPath));

return null;

}, userName, fileName);

}

/

**

* 自定义请求头部

* @param value

* @return

*/

private MapcreateHeader(String value){

Mapheaders = new HashMap<>();

headers.put("token", value);

return headers;

}

}假如返回的对象是一个范型,应该怎么处理呢?

在上篇文章中,我们介绍的服务器托管返回对象都是非范型,例如返回的都是ResponseBean这个业务对象,用法也很简单,以POST请求+JSON提交方式为例,通过如下方式即可实现返回对象的序列化!

ResponseBean responseBean = httpTemplate.postByJson(url, createHeader("testPostByJson"), request, ResponseBean.class);

但是,假如返回的对象是ResponseBean这样的,通过上面的方式来操作会直接报错!

当遇到返回的对象是范型类型的时候,我们可以这样操作!

以下面这个/testPostByJsonObj接口为例!

/

**

* 模拟JSON请求,post方法测试

* @param request

* @return

*/

@RequestMapping(value = "testPostByJsonObj", method = RequestMethod.POST)

public ResponseBeanObjtestPostByJsonObj(@RequestBody RequestBean requestBean,

HttpServletRequest request){

HttpServletRequestLog.systemLog(request);

//范型测试

ResponseBean responseBean = new ResponseBean();

responseBean.setCode("200000");

responseBean.setMsg("responseBean");

//范型测试

ResponseBeanObjresult = new ResponseBeanObj<>();

result.setCode("200");

result.setMsg("请求成功,方法:testPostByJsonObj,请求参数:" + JSON.toJSONString(requestBean));

result.setObj(responseBean);

System.out.println(JSON.toJSONString(result));

return result;

}

使用RestTemplate工具发起网络请求,代码如下!

//将返回的范型对象包装到ParameterizedTypeReference对象里面

ParameterizedTypeReference> typeRef = new ParameterizedTypeReference>() { };

//使用restTemplate发起网络请求

ResponseBeanObj<ResponseBean> responseBean = restTemplate.exchange(url, HttpMethod.POST, request, typeRef);

采用restTemplate.exchange()方法,即可实现返回对象范型类型的反序列化!

如果使用上面封装的HttpTemplate工具进行操作,也更简单,代码如下:

/

**

* 模拟JSON提交,post请求,范型返回对象测试

*/

@Test

public void testPostByJsonObj(){

//请求地址

String url = "http://localhost:8080/testPostByJsonObj";

//入参

RequestBean request = new RequestBean();

request.setUserName("唐三藏");

request.setUserPwd("123456789");

//发送post请求

ParameterizedTypeReference> typeRef = new ParameterizedTypeReference>() { };

//范型测试

ResponseBeanObjresponseBean = httpTemplate.postByJson(url, createHeader("testPostByJsonObj"), request, typeRef);

System.out.println(JSON.toJSONString(responseBean));

}

三、自定义拦截器

在某些场景下,当你使用restTemplate发起网络请求时,所有的请求头部需要带上统一的参数,例如Authorization鉴权码,这个时候改怎么办呢?

可能有的同学,想到的就是在传参数的时候,带上请求头部参数!这种方法也可以解决问题!

有没有好的办法统一入口加入呢?

答案肯定是有的,我们可以利用RestTemplate提供的拦截器链来解决这个问题。

例如在RestTemplate初始化之后,添加一个拦截器,然后在拦截器的请求头部统一注入鉴权码,就可以轻松实现全局加入某个参数,方式如下!

/

**

* 初始化RestTemplate

* @return

*/

@Bean

public RestTemplate restTemplate(){

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());

// 添加一个拦截器,在请求头部添加 Authorization 鉴权码

restTemplate.getInterceptors().add((request, body, execution) -> {

request.getHeaders().add("Authorization", "xxxxxXXXXX");

return execution.execute(request, body);

});

return restTemplate;

}

四、小结

通过本章的讲解,想必读者初步的了解了如何基于RestTemplate做第二次封装,以便于更佳适配当前团队开发人员的习惯。

RestTemplate的功能其实非常强大,作者也仅仅学了点皮毛,在后续如果有新的功能,也会分享给大家,希望对网友们有所帮助!

很赞哦!(38934)