首页 > 其他分享 >使用 RestTemplate 发送http请求的正确姿势原来是这样的!

使用 RestTemplate 发送http请求的正确姿势原来是这样的!

时间:2024-09-01 22:24:17浏览次数:13  
标签:姿势 uriVariables http responseType url RestTemplate param headers return

本文要介绍的这个工具类,是基于RestTemplate做了一层代码封装!!非常好用哦!

  • 第一步添加httpclient依赖包
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.6</version>
</dependency>
  • 然后创建一个配置,初始化RestTemplate
@Configuration
public class HttpConfiguration {

    /**
     * 初始化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 <T>
     * @return
     */
    public <T> T get(String url, Map<String, String> headers, Class<T> responseType, Object... uriVariables){
        ResponseEntity<T> rsp = commonExchange(url, HttpMethod.GET, new HttpEntity<>(createHeaders(headers)), responseType, uriVariables);
        return buildResponse(rsp);
    }


    /**
     * get请求,返回响应实体(响应业务对象支持范型)
     * 支持restful风格
     * @param url
     * @param headers
     * @param responseType
     * @param uriVariables
     * @param <T>
     * @return
     */
    public <T> T get(String url, Map<String, String> headers, ParameterizedTypeReference<T> responseType, Object... uriVariables){
        ResponseEntity<T> rsp = 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 <T>
     * @return
     */
    public <T> T postByFrom(String url, Map<String, String> headers, Map<String, Object> paramMap, Class<T> responseType, Object... uriVariables){
        //指定请求头为表单类型
        HttpHeaders httpHeaders = createHeaders(headers);
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        ResponseEntity<T> rsp = 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 <T>
     * @return
     */
    public <T> T postByFrom(String url, Map<String, String> headers, Map<String, Object> paramMap, ParameterizedTypeReference<T> responseType, Object... uriVariables){
        //指定请求头为表单类型
        HttpHeaders httpHeaders = createHeaders(headers);
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        ResponseEntity<T> rsp = 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 <T>
     * @return
     */
    public <T> T postByJson(String url, Map<String, String> headers, Object request, Class<T> responseType, Object... uriVariables){
        //指定请求头为json类型
        HttpHeaders httpHeaders = createHeaders(headers);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
        ResponseEntity<T> rsp = 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 <T>
     * @return
     */
    public <T> T postByJson(String url, Map<String, String> headers, Object request, ParameterizedTypeReference<T> responseType, Object... uriVariables){
        //指定请求头为json类型
        HttpHeaders httpHeaders = createHeaders(headers);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
        ResponseEntity<T> rsp = commonExchange(url, HttpMethod.POST, new HttpEntity<>(request, httpHeaders), responseType, uriVariables);
        return buildResponse(rsp);
    }

    /**
     * post请求,json提交,重定项
     * 支持restful风格
     * @param url
     * @param headers
     * @param request
     * @param uriVariables
     * @return
     */
    public String postForLocation(String url, Map<String, String> headers, 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> T put(String url, Map<String, String> headers, Object request, Class<T> responseType, Object... uriVariables){
        //指定请求头为json类型
        HttpHeaders httpHeaders = createHeaders(headers);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
        ResponseEntity<T> rsp = 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> T put(String url, Map<String, String> headers, Object request, ParameterizedTypeReference<T> responseType, Object... uriVariables){
        //指定请求头为json类型
        HttpHeaders httpHeaders = createHeaders(headers);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
        ResponseEntity<T> rsp = commonExchange(url, HttpMethod.PUT, new HttpEntity<>(request, httpHeaders), responseType, uriVariables);
        return buildResponse(rsp);
    }


    /**
     * delete请求(响应业务对象不支持范型)
     * @param url
     * @param headers
     * @param uriVariables
     * @return
     */
    public <T> T delete(String url, Map<String, String> headers, Class<T> responseType, Object... uriVariables){
        ResponseEntity<T> rsp = commonExchange(url, HttpMethod.DELETE, new HttpEntity<>(createHeaders(headers)), responseType, uriVariables);
        return buildResponse(rsp);
    }

    /**
     * delete请求(响应业务对象支持范型)
     * @param url
     * @param headers
     * @param uriVariables
     * @return
     */
    public <T> T delete(String url, Map<String, String> headers, ParameterizedTypeReference<T> responseType, Object... uriVariables){
        ResponseEntity<T> rsp = 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 <T>
     * @return
     */
    public <T> T uploadFile(String url, Map<String, String> headers, MultiValueMap<String, Object> paramMap, Class<T> responseType, Object... uriVariables){
        //指定请求头为文件&表单类型
        HttpHeaders httpHeaders = createHeaders(headers);
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
        ResponseEntity<T> rsp = 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 <T>
     * @return
     */
    public <T> T uploadFile(String url, Map<String, String> headers, MultiValueMap<String, Object> paramMap, ParameterizedTypeReference<T> responseType, Object... uriVariables){
        //指定请求头为文件&表单类型
        HttpHeaders httpHeaders = createHeaders(headers);
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
        ResponseEntity<T> rsp = 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, Map<String, String> headers, Object... uriVariables){
        ResponseEntity<byte[]> rsp = 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, Map<String, String> headers, 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 <T>
     * @return
     */
    public <T> ResponseEntity<T> commonExchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables){
        return restTemplate.exchange(url, method, requestEntity, responseType, uriVariables);
    }


    /**
     * 公共http请求方法(响应业务对象支持范型)
     * @param url
     * @param method
     * @param requestEntity
     * @param responseType
     * @param uriVariables
     * @param <T>
     * @return
     */
    public <T> ResponseEntity<T> commonExchange(String url, HttpMethod method, HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType, Object... uriVariables){
        return restTemplate.exchange(url, method, requestEntity, responseType, uriVariables);
    }



    /**
     * 封装头部参数
     * @param headers
     * @return
     */
    private HttpHeaders createHeaders(Map<String, String> headers){
        return new HttpHeaders(){{
            if(headers != null && !headers.isEmpty()){
                headers.entrySet().forEach(item -> {
                    set(item.getKey(), item.getValue());
                });
            }
        }};
    }


    /**
     * 封装请求体
     * @param paramMap
     * @return
     */
    private MultiValueMap<String, Object> createBody(Map<String, Object> paramMap){
        MultiValueMap<String, Object> valueMap = new LinkedMultiValueMap<>();
        if(paramMap != null && !paramMap.isEmpty()){
            paramMap.entrySet().forEach(item -> {
                valueMap.add(item.getKey(), item.getValue());
            });
        }
        return valueMap;
    }

    /**
     * 返回响应对象
     * @param rsp
     * @param <T>
     * @return
     */
    private <T> T buildResponse(ResponseEntity<T> rsp){
        if(!rsp.getStatusCode().is2xxSuccessful()){
            throw new RuntimeException(rsp.getStatusCode().getReasonPhrase());
        }
        return rsp.getBody();
    }
}

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

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

/**
 * 模拟JSON请求,post方法测试
 * @param request
 * @return
 */
@RequestMapping(value = "testPostByJsonObj", method = RequestMethod.POST)
public ResponseBeanObj<ResponseBean> testPostByJsonObj(@RequestBody RequestBean requestBean,
                                              HttpServletRequest request){
    HttpServletRequestLog.systemLog(request);
    //范型测试
    ResponseBean responseBean = new ResponseBean();
    responseBean.setCode("200000");
    responseBean.setMsg("responseBean");

    //范型测试
    ResponseBeanObj<ResponseBean> result = 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<ResponseBeanObj<ResponseBean>> typeRef = new ParameterizedTypeReference<ResponseBeanObj<ResponseBean>>() {};

//使用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<ResponseBeanObj<ResponseBean>> typeRef = new ParameterizedTypeReference<ResponseBeanObj<ResponseBean>>() {};
    //范型测试
    ResponseBeanObj<ResponseBean> responseBean = httpTemplate.postByJson(url, createHeader("testPostByJsonObj"), request, typeRef);
    System.out.println(JSON.toJSONString(responseBean));
}

在某些场景下,当你使用restTemplate发起网络请求时,所有的请求头部需要带上统一的参数,例如Authorization鉴权码,what can I do?

那我们可以在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;
}


最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!





标签:姿势,uriVariables,http,responseType,url,RestTemplate,param,headers,return
From: https://blog.51cto.com/u_16502039/11890454

相关文章

  • 使用 RestTemplate 发送http请求的正确姿势原来是这样的!
    本文要介绍的这个工具类,是基于RestTemplate做了一层代码封装!!非常好用哦!第一步添加httpclient依赖包<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.6</version></dependency>然后......
  • 【运维系列】如何为HTTP、HTTPS和RESTCONF开放安全策略
    防火墙提供了简单易用的WebUI。用户从浏览器访问承载在防火墙上的HTTPServer,可以完成绝大部分的配置管理工作。缺省情况下,防火墙启用HTTPS服务,服务端口为8443,且不可修改。从浏览器发起的HTTP访问会被重定向到HTTPS。RESTCONF以HTTP协议的方法提供了NETCONF协议的核心功能,编程接......
  • nodejs起一个http2
    静态页面其实就是复制官网的代码其中证书是我自己申请的可以用证书dingshaohua.comimportfsfrom"fs";importhttp2from"node:http2";constserver=http2.createSecureServer({key:fs.readFileSync("/etc/letsencrypt/live/dingshaohua.com/privkey.pem"),......
  • nginx代理http2服务
    NGINX不支持HTTP/2到后端,这从官方文档中可以看出,支持后端的最高HTTP版本为v1.1。其实添加此类支持实际上没有什么意义,因为HTTP/2的主要功能是请求多路复用。可当NGINX处理HTTP代理时,前端NGINX会将请求路由到后端的匹配位置(因为NGINX总是检查单个请求并将其路由到某个......
  • 运维系列&AI系列&Lenovo-G双系统系列(前传-装之前搜索的):ubuntu正确安装显卡驱动的姿势
    ubuntu正确安装显卡驱动的姿势ubuntu正确安装显卡驱动的姿势1.ubuntu16.04默认安装了第三方开源的驱动程序nouveau,安装nvidia显卡驱动首先需要禁用nouveau,不然会碰到冲突的问题,导致无法安装nvidia显卡驱动。2.在英伟达的官网上查找你自己电脑的显卡型号然后下载相应的......
  • http post请求和get请求的区别
    (1)post请求更安全(不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中,get请求的是静态资源,则会缓存,如果是数据,则不会缓存)(2)post请求发送的数据更大(get请求有url长度限制,http协议本身不限制,请求长度限制是由浏览器和web服务器决定和设置)(3)post请求能发送更多的......
  • HTTP请求方式
    http最大的作用就是确定了请求和响应数据的格式。常见的请求方式:get方法发送一个请求来取得服务器上的某一资源。post方法向url指定的资源提交数据或附加新的数据。put方法put方法跟post方法很像,也是向服务器提交数据,但是put方法指向了资源在服务器上的位置,而po......
  • 【网络】QUIC协议和HTTP3
    面试常考,临时抱佛脚学一下。参考https://zhuanlan.zhihu.com/p/266578819HTTP1.0和HTTP1.1HTTP1.0中,每一个请求必须等上一个请求收到响应了才能继续。且每一次请求都会重新建立TCP链接。HTTP1.1中可以复用TCP链接,但是依旧没有解决队头阻塞的问题,虽然复用了TCP链接,但是请求B依旧需......
  • 探索异步之美:aiohttp库的魔力与奥秘
    文章目录探索异步之美:aiohttp库的魔力与奥秘背景:为何选择aiohttp?什么是aiohttp?如何安装aiohttp?简单函数使用方法场景应用常见Bug及解决方案总结探索异步之美:aiohttp库的魔力与奥秘背景:为何选择aiohttp?在当今这个快速变化的技术世界中,效率和性能是开发人员追求的......
  • golang使用http客户端 多个协程同时请求接口
    packagemainimport( "encoding/json" "fmt" "io" "net/http" "net/url" "sync")typeApiResponsestruct{ Codeint`json:"code"` Msgstring`json:"msg&qu......