美文网首页
springboot2.x | restTemplate 的简单

springboot2.x | restTemplate 的简单

作者: hk_faith | 来源:发表于2021-01-11 14:55 被阅读0次

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对比

相关文章

网友评论

      本文标题:springboot2.x | restTemplate 的简单

      本文链接:https://www.haomeiwen.com/subject/ziddaktx.html