springboot2.x | restTemplate 的简单使用

http 协议

http 协议是一个用于传输超媒体文档(例如html)的应用层的协议。他是为了web浏览器和web 服务器之间的通讯而设计的
可以参考:
MDN web Docs

http1.1

现在web中用的最广的协议。
HTTP/1.1 主要的功能要点:

  • 增加了 HEAD、POST 等新方法
  • 增加了响应状态码,标记可能的错误原因
  • 引入了协议版本号概念
  • 引入了 HTTP Header(头部)的概念,让 HTTP 处理请求和响应更加灵活
  • 传输的数据不再仅限于文本
  • 增加了 PUT、DELETE 等新的方法;
  • 增加了缓存管理和控制;
  • 明确了连接管理,允许持久连接;
  • 允许响应数据分块(chunked),利于传输大文件;
  • 强制要求 Host 头,让互联网主机托管成为可能。

http2

HTTP/1.1 发布之后,整个互联网世界呈现出了爆发式的增长,度过了十多年的“快乐时光”,更涌现出了 Facebook、Twitter、淘宝、京东等互联网新贵。

这期间也出现了一些对 HTTP 不满的意见,主要就是连接慢,无法跟上迅猛发展的互联网,但 HTTP/1.1 标准一直“岿然不动”,无奈之下人们只好发明各式各样的“小花招”来缓解这些问题,比如以前常见的切图、JS 合并等网页优化手段。

终于有一天,搜索巨头 Google 忍不住了,首先开发了自己的浏览器 Chrome,然后推出了新的 SPDY 协议,并在 Chrome 里应用于自家的服务器,如同十多年前的网景与微软一样,从实际的用户方来“倒逼”HTTP 协议的变革,这也开启了第二次的“浏览器大战”。

历史再次重演,不过这次的胜利者是 Google,Chrome 目前的全球的占有率超过了 60%。Google 借此顺势把 SPDY 推上了标准的宝座,互联网标准化组织以 SPDY 为基础开始制定新版本的 HTTP 协议,最终在 2015 年发布了 HTTP/2,RFC 编号 7540。

HTTP/2 的制定充分考虑了现今互联网的现状:宽带、移动、不安全,在高度兼容 主要的特点有:

  • 二进制协议,不再是纯文本
  • 可发起多个请求,废弃了 1.1 里的管道
  • 使用专用算法压缩头部,减少数据传输量
  • 允许服务器主动向客户端推送数据
  • 增强了安全性,“事实上”要求加密通信

restTemplate

RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。

  • 调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,
  • 可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式。
    ClientHttpRequestFactory接口主要提供了三种实现方式
    1、SimpleClientHttpRequestFactory方式,此处生成SimpleBufferingClientHttpRequest,使用HttpURLConnection创建底层的Http请求连接
    2、HttpComponentsClientHttpRequestFactory方式,此处生成HttpComponentsClientHttpRequest,使用http client来实现网络请求
    3、OkHttp3ClientHttpRequestFactory方式,此处生成OkHttp3ClientHttpRequest,使用okhttp来实现网络请求

注入 restTemplate

@Configuration
public class RestTemplateConfig {

    /**
     * 方法1 :无参数的默认
     *
     * @return
     */
//    @Bean
//    public RestTemplate restTemplate(){
//        return new RestTemplate();
//    }


    /**
     * 方法2 :
     * 用 ClientHttpRequestFactory 来创建http请求
     *
     * @param requestFactory
     * @return
     */
    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory) {
        return new RestTemplate(requestFactory);
    }

    /**
     * 优先用 SimpleClientHttpRequestFactory
     * @return
     */
    @Primary
    @Bean
    public ClientHttpRequestFactory simpleClient() {

        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();

        //单位为ms
        factory.setReadTimeout(5000);
        //单位为ms
        factory.setConnectTimeout(5000);

        return factory;
    }


    @Bean
    public ClientHttpRequestFactory okhttpClient() {
        OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory();
        //单位为ms
        factory.setReadTimeout(5000);
        //单位为ms
        factory.setConnectTimeout(5000);

        return factory;
    }

}

使用 restTemplate 进行 get,post 请求

 @Resource
 private RestTemplate restTemplate;

    @GetMapping("/test-restTemplate")
    public String testRestTemplate() {

        /**
         * get 请求
         *
         * 参数1 要请求的地址的url  必填项
         * 参数2 响应数据的类型 是String 还是 Map等 必填项
         * 参数3 请求携带参数 选填
         */
        restTemplate.getForObject("http://localhost:8802/testRestGet?username=zhangsan", String.class);

        /**
         * get 请求
         *
         * 参数1 要请求的地址的url  必填项
         * 参数2 响应数据的类型 是String 还是 Map等 必填项
         * 参数3 请求携带参数 选填
         */
        Map<String, String> uriVariables = new HashMap<>();
        uriVariables.put("name", "zhengsan");
        restTemplate.getForObject("http://localhost:8802/testRestGet?username={name}", String.class, uriVariables);

        /**
         * get 请求
         *
         * getForEntity 方法 得到 返回值类型为 ResponseEntity
         * 参数1 要请求的地址的url  必填项
         * 参数2 响应数据的类型 是String 还是 Map等 必填项
         * 参数3 请求携带参数 选填
         */
        ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8802/testRestGet?username={name}", String.class, uriVariables);

        System.out.println("获取响应的状态:" + responseEntity.getStatusCode());
        System.out.println("获取响应的数据:" + responseEntity.getBody());


        /**
         * post 请求
         *
         * 参数1 要请求的地址的url  必填项
         * 参数2 通过LinkedMultiValueMap对象封装请求参数  模拟表单参数,封装在请求体中
         * 参数3 响应数据的类型 是String 还是 Map等 必填项
         * 参数4 请求携带参数 选填
         */
        LinkedMultiValueMap<String, String> request = new LinkedMultiValueMap<>();
        request.set("username", "zhangsan");
        restTemplate.postForObject("http://localhost:8002/testRestPost", request, Map.class);


        /**
         * post 请求
         *
         * 参数1 要请求的地址的url  必填项
         * 参数2 通过LinkedMultiValueMap对象封装请求参数  模拟表单参数,封装在请求体中
         * 参数3 响应数据的类型 是String 还是 Map等 必填项
         * 参数4 请求携带参数 选填
         */
        Map<String, String> uriVariables2 = new HashMap<>();
        uriVariables.put("address", "china");
        restTemplate.postForObject("http://localhost:8802/testRestPost?address={address}", request, Map.class, uriVariables2);


        /**
         * post 请求
         *
         * getForEntity 方法 得到 返回值类型为 ResponseEntity
         * 参数1 要请求的地址的url  必填项
         * 参数2 通过LinkedMultiValueMap对象封装请求参数  模拟表单参数,封装在请求体中
         * 参数3 响应数据的类型 是String 还是 Map等 必填项
         * 参数4 请求携带参数 选填
         */
        ResponseEntity<String> responseEntity2 = restTemplate.postForEntity("http://localhost:8002/testRestPost", request, String.class, uriVariables2);
        System.out.println("获取响应的状态:" + responseEntity2.getStatusCode());
        System.out.println("获取响应的数据:" + responseEntity2.getBody());


        /**
         * post 请求
         *
         * 登录or注册都是post请求,而这些操作完成之后呢?大部分都是跳转到别的页面去了,这种场景下,就可以使用 postForLocation 了,提交数据,并获取返回的URI
         * 响应参数要跳转的地址
         */
        //uri : "redirect:/success.html"
        URI uri = restTemplate.postForLocation("http://localhost:8802/testRestPostLocation", request);
        System.out.println("postForLocation请求到的地址为:" + uri);


        return null;
    }

设置请求header

方法1 先配置http的request拦截器

public class RestTemplateIntercepor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] body, ClientHttpRequestExecution execution) throws IOException {

      HttpHeaders headers =  httpRequest.getHeaders();

        headers.add(HttpHeaders.USER_AGENT,
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36");

        //add自己的header

        return execution.execute(httpRequest, body);
    }
}

设置 Interceptors


 restTemplate.setInterceptors(Collections.singletonList(new RestTemplateIntercepor()));

        restTemplate.getForObject("http://localhost:8802/testRestGet?username=zhangsan", String.class);

方法2

        //1. 设置请求头参数
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add(HttpHeaders.USER_AGENT,
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36");

        //2. 模拟表单参数 请求体携带参数
        LinkedMultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
        requestBody.add("username", "zhangsan");

        //3. 封装HttpEntity对象
        HttpEntity<MultiValueMap> requestEntity = new HttpEntity<MultiValueMap>(requestBody, requestHeaders);

        //4.获取 restTemplate
        RestTemplate restTemplate2 = new RestTemplate();


        //5.请求url
        ResponseEntity<String> responseEntity =restTemplate2.postForEntity("http://localhost:8802/testRestPost",requestEntity,String.class);
        System.out.println("获取响应的状态:" + responseEntity.getStatusCode());
        System.out.println("获取响应的数据:" + responseEntity.getBody());

http 协议参考文档:
http2协议(英文)
w3cschool介绍

restTemplate参考:
HttpClient、RestTemplate和Feign相关知识
使用RestTemplate和Feign进行微服务通信
restTemplate使用指南
基于springboot的RestTemplate、okhttp和HttpClient对比

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容