HTTP请求-【RestTemplate】

发布于:2023-09-14 ⋅ 阅读:(85) ⋅ 点赞:(0)

1、常见的http请求方式

  • RestTemple是Spring提供的用于访问Http请求的客户端
  • Apache的HttpClient
  • 原生HttpURLConnection

1.1 什么是RestTemple

【1】RestTemplate是Spring提供的进行远程调用客户端的工具
【2】调用RestTemplate的默认构造函数时,底层通过使用java.net包下实现创建HTTP请求访问
【3】RestTemplate创建需要ClientHttpRequestFactory,主要是如下三种(底层执行引擎

  1. SimpleClientHttpRequestFactory 默认实现,使用J2SE提供的方式创建底层的Http请求连接
    RestTemplate restTemplate = new RestTemplate();
  2. HttpComponentsClientHttpRequestFactory 底层使用HttpClient请求http服务
    RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
  3. OkHttp3ClientHttpRequestFactory 底层使用OkHttp访问远程的Http服务

1.2 HttpMessageConverter

RestTemplate默认使用HttpMessageConverter进行住消息转换;
调用restful接口数据传递格式为json,返回数据格式也是json字符串,然而restTemplate.postForObject方法的请求参数和返回参数都是java类,是由于RestTemplate通过HttpMessageConverter自动进行转换

在创建RestTemplate的时候会默认添加一组HttpMessageConveter的实现。

【HttpMessageConveter源码】

    public interface HttpMessageConverter<T> {
        //指示此转换器是否可以读取给定的类。
        boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
        //指示此转换器是否可以写给定的类。
        boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
        //返回List<MediaType>
        List<MediaType> getSupportedMediaTypes();
        //读取一个inputMessage
        T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
            throws IOException, HttpMessageNotReadableException;
        //往output message写一个Object
        void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException;
    }  
  • StringHttpMessageConverter来处理text/plain;
  • MappingJackson2HttpMessageConverter来处理application/json;
  • MappingJackson2XmlHttpMessageConverter来处理application/xml

定义转换器HttpMessageConverter如何注册到RestTemplate?

        RestTemplate restTemplate = new RestTemplate();
        //获取RestTemplate默认配置好的所有转换器
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        //默认的MappingJackson2HttpMessageConverter在第7个 先把它移除掉
        messageConverters.remove(6);
        //添加上GSON的转换器,下标从0开始
        messageConverters.add(6, new GsonHttpMessageConverter());

1.3 简单的restful接口实例

@RestController
public class TestController
{
    @RequestMapping(value = "testPost", method = RequestMethod.POST)
    public ResponseBean testPost(@RequestBody RequestBean requestBean)
    {
        ResponseBean responseBean = new ResponseBean();
        responseBean.setRetCode("0000");
        responseBean.setRetMsg("succ");
 
        return responseBean;
    }
}

使用RestTemplate访问该服务
        //请求地址
        String url = "http://localhost:8080/testPost";
        //入参
        RequestBean requestBean = new RequestBean();
        requestBean.setTest1("1");
        requestBean.setTest2("2");
        requestBean.setTest3("3");
 
        RestTemplate restTemplate = new RestTemplate();
        ResponseBean responseBean = restTemplate.postForObject(url, requestBean, ResponseBean.class);

2、RestTemplate方法

2.1 RestTemplate之Get请求

RestTemplate有两个核心方法执行Get请求
1)RestTemplate.getForObject()可以获取对象
2)RestTemplate.getForEntity()可以获取对象,获取http状态码、请求头等

springboot集成RestTemplate

@Configuration
public class RestConfig {

    @Bean
    public RestTemplate restTemplate(){

        // 默认底层执行HttpurlConnection
        return new RestTemplate();
    }
}

在这里插入图片描述

【RestTemplate.getForObject()样例程序】

 @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/getForObject")
    public Object getForObject(){
        String url = "http://localhost:8080/addUser/100/mimimi";
        Map<String, Integer> map = new HashMap<>();
        UserDTO result = restTemplate.getForObject(url, UserDTO.class,map);
        return result;  //{"id":100,"name":"mimimi"}
    }

2.2 restTemplate之Post请求

Post请求包括两个核心方法:
1)RestTemplate.postForObject()
2)RestTemplate.postForEntity()
Post方法方法传参Map必须是MutiValueMap;MutiValueMap支持基本类型分开传参,也支持实体传参

一、postForObject

  // post请求:基本类型/实体传参
    @GetMapping("/postForObject")
    public UserDTO postForObject(){
        String url= "http://localhost:8080/addUser1";
        MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();

        map.add("id",12);
        map.add("name","小黑");
        // 返回UserDTO对象
        UserDTO userDTO = restTemplate.postForObject(url,map, UserDTO.class);
        return userDTO; //{"id":12,"name":"小黑"}

    }

二、postForEntity

 // post请求:postForEntity
    @GetMapping("/postForEntity1")
    public UserDTO postForEntity1(){
        String url="http://localhost:8080/addUser1";

        // 提交参数:使用 map 装载参数
        MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
        map.add("id",1000);
        map.add("name","hello restTemplate");
        //发送post请求
        ResponseEntity<UserDTO> userDTOResponseEntity= restTemplate.postForEntity(url,map, UserDTO.class);

        // postForEntity可以获取响应码、响应对象、响应头等
        HttpStatus status = userDTOResponseEntity.getStatusCode();
        int code = userDTOResponseEntity.getStatusCodeValue();
        HttpHeaders headers = userDTOResponseEntity.getHeaders();
        log.info("http响应码:{},响应状态码:{},headers信息:{}",status,code,headers);
        return userDTOResponseEntity.getBody();//{"id":1000,"name":"hello restTemplate"}
    }

postForEntity()和getForObject()唯一的区别是:返回的时候使用ResponseEntity<>

2.3 restTemplate.exchange()

2.1 restTemplate.exchange()方法:
在这里插入图片描述

参数说明:url: 请求地址
method:请求类型( POST 、GET等)
requestEntity: 请求实体,封装请求头,请求内容
responseType: 请求响应对象的类型
uriVariables: url中的@PathVariable参数,可变长度参数列表

 // exchange
    @GetMapping("/exchange")
    public UserDTO exchange(){
        String url = "";
        // 传参使用MultiValueMap
        MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
        map.add("id",10);
        map.add("name","xixixi");

        // 请求使用HttpEntity,包装map
        HttpEntity<MultiValueMap> requestEntity = new HttpEntity<>(map);
        // 返回使用ResponseEntity
        ResponseEntity<UserDTO> response = restTemplate.exchange(url, HttpMethod.POST,requestEntity, UserDTO.class);
        return response.getBody();
    }


restTemplate使用实践

2.2 RestTemplate底层连接方式

对于一个请求来说,超期时间,请求连接时间等都是必不可少的参数,为了更好的适应业务需求,所以可以自己修改restTemplate的配置
restTemplate简书

        //生成一个设置了连接超时时间、请求超时时间、异常最大重试次数的httpClient
        RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(10000).setConnectTimeout(10000).setSocketTimeout(30000).build();
        HttpClientBuilder builder = HttpClientBuilder.create().setDefaultRequestConfig(config).setRetryHandler(new DefaultHttpRequestRetryHandler(5, false));
        HttpClient httpClient = builder.build();
        //使用httpClient创建一个ClientHttpRequestFactory的实现
        ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
         //ClientHttpRequestFactory作为参数构造一个使用作为底层的RestTemplate
        RestTemplate restTemplate = new RestTemplate(requestFactory);

RestTemplate总结