• REST 客户端——细读RestTemplate


    使用Spring MVC创建REST API

    四、REST 客户端——细读RestTemplate

    RestTemplate概述

    spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。

    在Spring应用程序中访问第三方REST服务与使用Spring RestTemplate类有关。

    RestTemplate类的设计原则与许多其他Spring *模板类(例如JdbcTemplate、JmsTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。

    RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。

    根据源码结构

    RestTemplate类中定义了大约四十个与 REST 资源交互的方法,其中大多数都对应于HTTP的方法。但是仔细分析,里面只有十二种方法。其余都是这12种方法的重载形式。下表描述了RestTemplate的12个独立方法。

    序号 方法 重载方法数 描述
    1 delete() 3 在特定的 URL 上对资源执行 HTTP DELETE 操作
    2 exchange() 8 在 URL上执行特定的 HTTP 方法,返回包含对象的 ResponseEntity,这个对象是在响应体中映射得到的
    3 excute() 3 在 URL上执行特定的 HTTP 方法,返回从响应体中映射得到的对象
    4 getForObject() 3 发送一个 HTTP GET请求,返回的 请求体将映射成一个对象
    5 getForEntity() 3 发送一个 HTTP GET请求,返回的 ResponseEntity包含了响应体所映射成的对象
    6 HeadForHeaders() 3 发送一个 HTTP HEAD请求,返回包含特定资源URL的HTTP头
    7 optionsForAllow() 3 发送一个 HTTP OPTIONS请求,返回对特定URL的Allow头信息
    8 postForObject() 3 POST数据到一个URL,返回根据响应体匹配形成的对象
    9 postForEntity() 3 POST数据到一个URL,返回包含一个对象的ResponseEntiry,这个对象是从响应体中映射得到的
    10 postForLocation() 3 POST数据到一个URL,返回新创建资源的URL
    11 put() 3 PUT资源到一个URL
    12 patchForObject() 3 PATCH数据到一个URL,返回根据响应体匹配形成的对象

    简单分析源码可以看出以下几个特点

    1. 除了TRACE意外,RestTemplate涵盖了所有的HTTP动作。除此之外,exchange()和excute()提供了较低层次的通用方法来使用任意的HTP方法,特定的方法其实最后都是走的excete()方法;

    2. 大多数操作都是以三种方式进行了重载:

    • 使用java.net.URI作为URL的形式,不支持参数化URI;
    • 使用String作为URL格式,并使用Map指明URL参数;
    • 使用Strig作为URL格式,并使用可变擦书列表指明URL参数。
    1. RestTemplate包含以下几个部分:

      • HttpMessageConverter 对象转换器
      • ClientHttpRequestFactory 默认是JDK的HttpURLConnection
      • ResponseErrorHandler 异常处理
      • ClientHttpRequestInterceptor 请求拦截器
    2. api位于org.springframework.web.client包下

    3. xxForObject()与xxForEntity()方法区别与联系

      1. 返回类型不同,xxForObject直接返回匹配的,而xxForEntity()方法返回一个ResponseEntity对象。该对象的body里存着映射成的对象,除此之外还有本次响应相关的额外信息,如状态码、HttpHeader信息等。
      2. 参数类型是一致的

    RestTemplate官方 最新 API

    使用示例

    Get

    源码接口:

    <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException;
    
    <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
    
    <T> T getForObject(URI url, Class<T> responseType) throws RestClientException;
    <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
    			throws RestClientException;
    
    <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
    			throws RestClientException;
    
    <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException;
    
    1. 简单查询,uri里不带参数

      public static void testGet1() {
          final String uri = "http://localhost:8080/students";
      
          RestTemplate restTemplate = new RestTemplate();
          String object = restTemplate.getForObject(uri, String.class);
      
          System.out.println(object);
      }
      
    2. url参数

      public static void testGet2() {
          String uri = "http://localost:8080/student/{studentId}";
          RestTemplate restTemplate = new RestTemplate();
      
          int studentId = 1;
      
          Student student = restTemplate.getForObject(uri, Student.class, studentId);
          System.out.println(student);
      }
      
      public static void testGet3() {
          String uri = "http://localost:8080/student/{studentId}";
          RestTemplate restTemplate = new RestTemplate();
      
          int studentId = 1;
          Map<String, Integer> params = new HashMap<String, Integer>();
          params.put("studentId", studentId);
      
          Student student = restTemplate.getForObject(uri, Student.class, params);
          System.out.println(student);
      }
      
    3. 如果GET方法请求参数需要添加认证、Header头信息等,则需要使用exchange()方法,见下文。

    Post

    Put

    Patch

    Options

    Delete

    exchange()

    上文中提到,xxForObject()方法与xxForEntity()方法的区别是后者可以同时返回对象和响应头、状态码。能在响应中读取到这头信息是很有用的。但是如果想在发送给服务器的请求中设置头信息的话,怎么办呢?这就是RestTemplate的exchange()的用武之地。

    exchange()的 8 个接口 源码:

    <T> ResponseEntity<T> exchange(String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity,
    			Class<T> responseType, Object... uriVariables) throws RestClientException;
    
    <T> ResponseEntity<T> exchange(String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity,
    			Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
    
    <T> ResponseEntity<T> exchange(URI url, HttpMethod method, @Nullable HttpEntity<?> requestEntity,
    			Class<T> responseType) throws RestClientException;
    
    <T> ResponseEntity<T> exchange(String url,HttpMethod method, @Nullable HttpEntity<?> requestEntity,
    			ParameterizedTypeReference<T> responseType, Object... uriVariables) throws RestClientException;
    
    <T> ResponseEntity<T> exchange(String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity,
    			ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
    
    <T> ResponseEntity<T> exchange(URI url, HttpMethod method, @Nullable HttpEntity<?> requestEntity,
    			ParameterizedTypeReference<T> responseType) throws RestClientException;
    
    <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, Class<T> responseType)
    			throws RestClientException;
    
    <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, ParameterizedTypeReference<T> responseType)
    			throws RestClientException;
    

    exchange()方法使用HttpMethod参数来表明要使用的HTTP动作。根据此参数,该方法可以与上文具体的HTTP方法一样的工作。

    public void testGet4() {
        HttpHeaders headers = new HttpHeaders();
        headers.set("kbn-xsrf", "true");
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
    
        // 手动添加认证
        String userName = "root";
        String password = "123456";
        String str = userName + ":" + password;
        String auth = "Basic " + Base64GeneratorUtil.str2Base64(str);
        headers.set("Authorization", auth);
    
        // 如果需要 还可以在这里添加一些json字符串信息
        String jsonObj = "{}";
        HttpEntity<String> request = new HttpEntity<>(jsonObj, headers);
    
        String uri = "http://localost:8080/student/{studentId}";
    
        RestTemplate restTemplate = new RestTemplate();
        int studentId = 1;
        ResponseEntity<Student> entity = restTemplate.exchange(uri, HttpMethod.PUT, request, Student.class, studentId);
        Student student = entity.getBody();
        HttpStatus statusCode = entity.getStatusCode();
        HttpHeaders headers1 = entity.getHeaders();
    }
    

    excute()

    略。

  • 相关阅读:
    小朋友的责任 转自点妈文集
    amazon.cn, 感觉不错
    团队作业1——团队展示&选题
    如何解决mysql中的账户添加后不能登录的问题
    目标检测中常见指标
    latex知识点
    考研复试建议
    论文写作经验
    Git
    Python编程知识
  • 原文地址:https://www.cnblogs.com/kjgym/p/11767337.html
Copyright © 2020-2023  润新知