zoukankan      html  css  js  c++  java
  • Spring Boot之发送HTTP请求(RestTemplate详解)

    RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法

    1.简述RestTemplate

    RestTemplate能大幅简化了提交表单数据的难度,并且附带了自动转换JSON数据的功能
    HTTP方式 RestTemplate方法

    HTTP方式 RestTemplate方法
    GET getForObject()
    getForObject()
    POST postForLocation()
    postForObject
    PUT put
    DELETE delete

    在内部,RestTemplate默认使用HttpMessageConverter实例将HTTP消息转换成POJO或者从POJO转换成HTTP消息。

    默认情况下会注册主mime类型的转换器,但也可以通过setMessageConverters注册其他的转换器。

    在内部,RestTemplate默认使用SimpleClientHttpRequestFactory和DefaultResponseErrorHandler来分别处理HTTP的创建和错误,但也可以通过setRequestFactory和setErrorHandler来覆盖。

    2.get请求实践(我们在java后台的HTTP发送中最最常用的就是GET请求了)

    2.1.getForObject()方法

      public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables){}  
      public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)  
      public <T> T getForObject(URI url, Class<T> responseType)  
    

    getForObject()其实比getForEntity()多包含了将HTTP转成POJO的功能,但是getForObject没有处理response的能力。因为它拿到手的就是成型的pojo。省略了很多response的信息。

      public class Notice {  
          private int status;  
          private Object msg;  
          private List<DataBean> data;  
      }  
      public  class DataBean {  
        private int noticeId;  
        private String noticeTitle;  
        private Object noticeImg;  
        private long noticeCreateTime;  
        private long noticeUpdateTime;  
        private String noticeContent;  
      }  
    
    

    2.1.2 不带参的get请求

           /**  
            * 不带参的get请求  
            */  
          @Test  
          public void restTemplateGetTest(){  
              try {  
                  RestTemplate restTemplate = new RestTemplate();  
             //将指定的url返回的参数自动封装到自定义好的对应类对象中  
                  Notice notice = restTemplate.getForObject("http://xxx.top/notice/list/1/5",Notice.class);  
                  System.out.println(notice);  
              }catch (HttpClientErrorException e){  
                  System.out.println("http客户端请求出错了!");  
                  //开发中可以使用统一异常处理,或者在业务逻辑的catch中作响应  
              }  
          }  
    
    

    控制台打印:

       
     INFO 19076 --- [           main] c.w.s.c.w.c.HelloControllerTest           
    
    : Started HelloControllerTest in 5.532 seconds (JVM running for 7.233)  
    
    Notice{status=200, msg=null, data=[DataBean{noticeId=21, noticeTitle='aaa', noticeImg=null,  
    
    noticeCreateTime=1525292723000, noticeUpdateTime=1525292723000, noticeContent='<p>aaa</p>'},  
    
    DataBean{noticeId=20, noticeTitle='ahaha', noticeImg=null, noticeCreateTime=1525291492000,  
    
    noticeUpdateTime=1525291492000, noticeContent='<p>ah.......'  
    
    

    2.1.3 带参数的get请求1

    Notice notice = restTemplate.getForObject("http://fantj.top/notice/list/{1}/{2}", Notice.class,1,5);
    

    上面使用了占位符,将1和5作为参数传入的请求URL中的第一个参数{1}处和第二个参数{2}处

    2.1.4 带参数的get请求2

       Map<String,String> map = new HashMap();  
               map.put("start","1");  
               map.put("page","5");  
               Notice notice = restTemplate.getForObject("http://fantj.top/notice/list/"  
                       , Notice.class,map);  
    

    利用map装载参数,不过它默认解析的是PathVariable的url形式

    2.2 getForEntity()方法

     public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables){}  
     public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables){}  
     public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType){}  
    

    与getForObject()方法不同的是,getForEntity()方法返回的是ResponseEntity对象,如果需要转换成pojo,还需要json工具类的引入。可以引入FastJson等工具类解析json。

    然后我们就研究一下ResponseEntity下面有啥方法。

    ResponseEntity、HttpStatus、BodyBuilder结构

    ResponseEntity.java

     
       public HttpStatus getStatusCode(){}  
       public int getStatusCodeValue(){}  
       public boolean equals(@Nullable Object other) {}  
       public String toString() {}  
       public static BodyBuilder status(HttpStatus status) {}  
       public static BodyBuilder ok() {}  
       public static <T> ResponseEntity<T> ok(T body) {}  
       public static BodyBuilder created(URI location) {}  
       ...  
     
    

    HttpStatus.java

      
        public enum HttpStatus {  
        public boolean is1xxInformational() {}  
        public boolean is2xxSuccessful() {}  
        public boolean is3xxRedirection() {}  
        public boolean is4xxClientError() {}  
        public boolean is5xxServerError() {}  
        public boolean isError() {}  
        }  
      
    

    BodyBuilder.java

      
        public interface BodyBuilder extends HeadersBuilder<BodyBuilder> {  
            //设置正文的长度,以字节为单位,由Content-Length标头  
              BodyBuilder contentLength(long contentLength);  
            //设置body的MediaType 类型  
              BodyBuilder contentType(MediaType contentType);  
            //设置响应实体的主体并返回它。  
              <T> ResponseEntity<T> body(@Nullable T body);  
        }  
      
    

    可以看出来,ResponseEntity包含了HttpStatus和BodyBuilder的这些信息,这更方便我们处理response原生的东西。

      
        @Test  
        public void rtGetEntity(){  
                RestTemplate restTemplate = new RestTemplate();  
                ResponseEntity<Notice> entity = restTemplate.getForEntity("http://fantj.top/notice/list/1/5"  
                        , Notice.class);  
           
                HttpStatus statusCode = entity.getStatusCode();  
                System.out.println("statusCode.is2xxSuccessful()"+statusCode.is2xxSuccessful());  
           
                Notice body = entity.getBody();  
                System.out.println("entity.getBody()"+body);  
           
           
                ResponseEntity.BodyBuilder status = ResponseEntity.status(statusCode);  
                status.contentLength(100);  
                status.body("我在这里添加一句话");  
                ResponseEntity<Class<Notice>> body1 = status.body(Notice.class);  
                Class<Notice> body2 = body1.getBody();  
                System.out.println("body1.toString()"+body1.toString());  
            }  
      
    

    控制台结果:

       statusCode.is2xxSuccessful()true  
       entity.getBody()Notice{status=200, msg=null, data=[DataBean{noticeId=21, noticeTitle='aaa', ...  
       body1.toString()<200 OK,class com.waylau.spring.cloud.weather.pojo.Notice,{Content-Length=[100]}>  
    

    同样的,post请求也有postForObject和postForEntity。

    3. post请求实践

    同样的,post请求也有postForObject和postForEntity。

      
        public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables)  
                    throws RestClientException {}  
        public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables)  
                    throws RestClientException {}  
        public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException {}  
      
    

    示例

    我用一个验证邮箱的接口来测试。

      
        @Test  
        public void rtPostObject(){  
            RestTemplate restTemplate = new RestTemplate();  
            String url = "http://47.xxx.xxx.96/register/checkEmail";  
            HttpHeaders headers = new HttpHeaders();  
            headers.setContentType(MediaType.APPLICATION\_FORM\_URLENCODED);  
            MultiValueMap<String, String> map= new LinkedMultiValueMap<>();  
            map.add("email", "844072586@qq.com");  
           
            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);  
            ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );  
            System.out.println(response.getBody());  
        }  
      
    

    执行结果:

    {"status":500,"msg":"该邮箱已被注册","data":null}
    

    转自:url

    --欢迎大家来交流反馈。
  • 相关阅读:
    centos7.6 使用yum安装mysql5.7
    解决hadoop本地库问题
    docker-compose 启动警告
    docker 安装zabbix5.0 界面乱码问题解决
    docker 部署zabbix问题
    zookeeper 超时问题
    hbase regionserver异常宕机
    (转载)hadoop 滚动升级
    hadoop Requested data length 86483783 is longer than maximum configured RPC length
    zkfc 异常退出问题,报错Received stat error from Zookeeper. code:CONNECTIONLOSS
  • 原文地址:https://www.cnblogs.com/hhyl/p/14651359.html
Copyright © 2011-2022 走看看