RestTemplate 实践和踩坑日记

话不多说

场景就是 我调用外部需要鉴权的接口, 需要按照对方的格式写参数。呜呜呜

官网 说这个东西 5.0后 处于维护阶段。
大概下面这个意思

As of 5.0 the RestTemplate is in maintenance mode, with only minor requests for changes and bugs to be accepted going forward. Please, consider using the WebClient which offers a more modern API and supports sync, async, and streaming scenarios.

先直接贴配置

@Configuration
public class RestTemplateConfig {

    private static final Logger logger= LoggerFactory.getLogger(RestTemplateConfig.class);

    @Bean
    public RestTemplate restTemplate() {
        // 添加内容转换器,使用默认的内容转换器
        RestTemplate restTemplate = new RestTemplate(httpRequestFactory());
        // 设置编码格式为UTF-8
        List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
        HttpMessageConverter<?> converterTarget = null;
        for (HttpMessageConverter<?> item : converterList) {
            if (item.getClass() == StringHttpMessageConverter.class) {
                converterTarget = item;
                break;
            }
        }
        if (converterTarget != null) {
            converterList.remove(converterTarget);
        }
        HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
        converterList.add(1,converter);
        // 为啥加这个。 理解了 mvc 的消息转换器可以🈶️多个。
        // 坑1
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.TEXT_HTML));
        restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);

        logger.info("-----restTemplate-----初始化完成");
        return restTemplate;
    }

    @Bean
    public ClientHttpRequestFactory httpRequestFactory() {
        return new HttpComponentsClientHttpRequestFactory(httpClient());
    }

    @Bean
    public HttpClient httpClient() {
        // 长连接保持30秒
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
        //设置整个连接池最大连接数 根据自己的场景决定
        connectionManager.setMaxTotal(100);
        //同路由的并发数,路由是对maxTotal的细分
        connectionManager.setDefaultMaxPerRoute(100);

        //requestConfig
        RequestConfig requestConfig = RequestConfig.custom()
                //服务器返回数据(response)的时间,超过该时间抛出read timeout
                .setSocketTimeout(3000)
                //连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
                .setConnectTimeout(2000)
                //从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
                .setConnectionRequestTimeout(500)
                .build();
        //headers
        List<Header> headers = new ArrayList<>();
        headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36"));
        headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));
        headers.add(new BasicHeader("Accept-Language", "zh-CN"));
        headers.add(new BasicHeader("Connection", "Keep-Alive"));
        headers.add(new BasicHeader("Content-type", "application/json;charset=UTF-8"));

        return HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .setDefaultHeaders(headers)
                // 保持长连接配置,需要在头添加Keep-Alive
                .setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy())
                //重试次数,默认是3次,没有开启
                .setRetryHandler(new DefaultHttpRequestRetryHandler(2, true))
                .build();
    }
}

坑1 为啥 我返回的字符串转不了对象。

org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class [xx.xx.xx.Employee;] and content type [text/html] ... 

他喵的 返回报文媒体格式 竟然 text/html ,我转了几个小时 也没有转处理 气死我了。 多谢下面的博客
思路大概就是让你支持 这个转换器就好了。

参考
https://www.technicalkeeda.com/spring-tutorials/could-not-extract-response-no-suitable-httpmessageconverter-found-for-response-type

坑2 RestTemplate 传递 form 表单 的参数

得 自己设置头 和参数格式

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
map.add("xxxx", "f哈哈哈");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );

贴下我的代码

        GtwShippingRequest shippingRequest = new GtwShippingRequest();
        shippingRequest.setBillNo("1");
        shippingRequest.setTrafName("1");
        shippingRequest.setVoyage("1");
        shippingRequest.setIeFlag("E");
        shippingRequest.setRegion("sh");
        Gson gson = new Gson();
        String content = gson.toJson(shippingRequest);
        String timestamp = String.valueOf(System.currentTimeMillis());
        String sign = getSign(bizCode92, bizId, content, timestamp, appKey);
        MultiValueMap<String, String> parameters= new LinkedMultiValueMap<String, String>();
        parameters.add("appId", appId);
        parameters.add("bizCode", bizCode92);
        parameters.add("bizId", bizId);
        parameters.add("content", content);
        parameters.add("timestamp", timestamp);
        parameters.add("sign", sign);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(parameters,headers);
        ParameterizedTypeReference<GtwResponse<GtwShippingInfo>> ptr = new ParameterizedTypeReference<GtwResponse<GtwShippingInfo>>(){};
        try {
            ResponseEntity<GtwResponse<GtwShippingInfo>> response = restTemplate.exchange(url, HttpMethod.POST, request, ptr);
            System.out.println(response.getBody());
        } catch ( Exception e) {
            e.printStackTrace();
        }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值