• Spring的RestTemplata使用


    spring-web的RestTemplata是对java底层http的封装,使用RestTemplata用户可以不再关注底层的连接建立,并且RestTemplata不仅支持Rest规范,还可以定义返回值对象类型。

    在使用中可以直接new一个RestTemplate对象,在我们创建的RestTemplate对象中会有一些返回消息的消息转换器,可以根据返回数据的MediaType寻找对应的转换器并进行MediaType转换。自己也可以创建消息转换器,创建一个类继承AbstractGenericHttpMessageConverter<T>类或者实现HttpMessageConverter<T>接口,需要注意的是canRead方法和canWrite方法最好自己做判断,在writeInternal或write方法中将参数写入到流,在readInternal或read方法中将返回结果从流的body中获取并进行类型映射。

    RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式。
    ClientHttpRequestFactory接口主要提供了两种实现方式:

    • 一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接。
    • 一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息。

    RestTemplate默认是使用SimpleClientHttpRequestFactory,内部是调用jdk的HttpConnection,默认超时为-1,我们可以自己定义超时时间

    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    //设置连接超时,单位毫秒
    factory.setConnectTimeout(5000);
    //设置读取超时,单位毫秒
    factory.setReadTimeout(10000);
    RestTemplate restTemplate = new RestTemplate(factory);

    使用GET请求: 

      String url = "http://localhost:80/mandy/login.json?account=123456&password=123456";
      Result res = restTemplate.getForObject(url, Result.class);

    RestTemplate源码:

      @Override
        public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) throws RestClientException {
            RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
            HttpMessageConverterExtractor<T> responseExtractor =
                    new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
            return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables);
        }

    使用get请求直接将参数拼接到地址上最好,不知道什么原因如果使用第三个参数,即便是MultiValueMap类型也不行(网上有人说用MultiValueMap类型可以,我试了不行)

    使用POST请求: 

    HashMap<String, Object> map = new HashMap<String, Object>();
    map.put("name", "测试");
    map.put("account", "qwer");
    map.put("password", "qwer");
    ObjectMapper mapper = new ObjectMapper();
    String jsonStr = null;
    try {
      jsonStr = mapper.writeValueAsString(map);
    } catch (Exception e) {
      e.printStackTrace();
    }
    //创建HTTP头部实体,填充头部信息,比如数据格式
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);

    //创建HTTP实体,可以直接利用构造方法将请求体和请求头放进去
    HttpEntity<String> httpEntity = new HttpEntity<String>(jsonStr2, httpHeaders);

    String url = "http://localhost:80/mandy/user_enable.json";

    //调用方法进行请求
    Result res2 = restTemplate.postForObject(url, httpEntity, Result.class);

     RestTemplate源码:

      @Override
        public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
                throws RestClientException {
    
            RequestCallback requestCallback = httpEntityCallback(request, responseType);
            HttpMessageConverterExtractor<T> responseExtractor =
                    new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
            return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
        }

    使用PUT请求: 

    HashMap<String, Object> map = new HashMap<String, Object>();
    map.put("user_id", "1");
    map.put("enable", 0);
    ObjectMapper mapper = new ObjectMapper(); String jsonStr
    = null; try { jsonStr = mapper.writeValueAsString(map); } catch (JsonProcessingException e) { e.printStackTrace(); }
    //创建HTTP头部实体,填充头部信息,比如数据格式 HttpHeaders httpHeaders
    = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
    //创建HTTP实体,可以直接利用构造方法将请求体和请求头放进去 HttpEntity
    <String> httpEntity = new HttpEntity<String>(jsonStr, httpHeaders); String url = "http://localhost:80/mandy/user_enable.json"; restTemplate.put(url , httpEntity);

     RestTemplate源码:

      @Override
        public void put(String url, Object request, Object... urlVariables) throws RestClientException {
            RequestCallback requestCallback = httpEntityCallback(request);
            execute(url, HttpMethod.PUT, requestCallback, null, urlVariables);
        }

    这个方法有个小的缺点就是没有请求结果的返回值,如果需要用到返回值,就不能用这个方法。

    如果要使用delete类型的请求,RestTemplate的put方法的参数列中只有下面几种

    @Override
    public void delete(String url, Object... urlVariables) throws RestClientException {
      execute(url, HttpMethod.DELETE, null, null, urlVariables);
    }
    
    @Override
    public void delete(String url, Map<String, ?> urlVariables) throws RestClientException {
      execute(url, HttpMethod.DELETE, null, null, urlVariables);
    }
    
    @Override
    public void delete(URI url) throws RestClientException {
      execute(url, HttpMethod.DELETE, null, null);
    }

    这些方法并没有给我们参数让我们放请求体内容,所以如果要直接使用RestTemplate提供的Delete方法,接口必须使用restful风格,将参数放在地址中,通过@PathVariable(value="")注解将参数获取到。

    重点:其实我们可以直接使用RestTemplate的exchange方法,如下

    @Override
    public <T> ResponseEntity<T> exchange(String url, HttpMethod method,
      HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) throws RestClientException {
    
      RequestCallback requestCallback = httpEntityCallback(requestEntity, responseType);
      ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
      return execute(url, method, requestCallback, responseExtractor, uriVariables);
    }

    这里只列举了一个方法,其他的可以看源码,这个方法可以进行所有类型的请求。

    在这个方法中,method参数可以通过HTTPMethod枚举来进行获取,requestEntity参数是自己封装的HttpEntity实体,包含请求体和请求头,responseType参数是返回结果的映射类,uriVariables这个参数给我的印象就是鸡肋(个人看法),获取请求返回接口可以通过方法返回值的getBody()方法获取。

    ============================================================================

    请原谅我的无知,最近又研究了下spring的restTemplate类的方法,突然间发现uriVariables这个参数的用法,如下所示:

    RestTemplate template = new RestTemplate();
    Map result = template.getForObject("http://localhost:8080/login.json?account={param1}&password={param2}", Map.class, "123456", "654123");
    HashMap<String, String> map = new HashMap<>();
    map.put("param2", "654123");
    map.put("param1", "123456");
    Map result2 = template.getForObject("http://localhost:8080//login.json?account={param1}&password={parma2}", Map.class, map);
    // result与result2的结果是一致的

    在URL中我们可以先定义好需要拼接在URL中的参数以及将要被代替的参数(使用花括号进行包含),uriVariables参数如果使用可变数组的形式,要保证替换参数和将要被替换的参数顺序要一致,如果使用Map的形式,要保证被替代的参数名在传入的map中有相应的key,不然会在参数替换的抛出异常。

  • 相关阅读:
    首个融合场景图知识的多模态预训练模型 ERNIE-ViL
    RAKE 快速、简单的关键词抽取算法
    3种常用的词向量训练方法的代码,Word2Vec, FastText, GloVe快速训练
    关键词提取新方法-YAKE! Collection-independent Automatic Keyword Extractor
    输入一个正整数,按照从小到大的顺序输出它的所有质因子(如180的质因子为2 2 3 3 5 )
    textRank算法
    不允许有匹配 "[xX][mM][lL]" 的处理指令目标
    idea: package下面的XML文件沒有複製
    delphi:调用java webservice时,传参始终为空
    tomcat:指定JDK运行
  • 原文地址:https://www.cnblogs.com/zzw-blog/p/8360512.html
Copyright © 2020-2023  润新知