Spring Resttemplate post方法踩坑记录

Spring Resttemplate post方法踩坑记录

项目中有处地方需要通过http post构造restful请求,且需要携带正确的header域,自然而然想到了用Spring自带的restTemplate,对应post,put,get,delete它都有对应的封装方法。
由于我用的项目框架是SpringBoot,所以使用Resttemplate很简单,在启动类XXXApplication类上注入resttemplate即可,如下代码:

    @Inject
    private RestTemplateBuilder builder;
    @Bean
    public RestTemplate restTemplate() {
        return builder.build();
    }

然后在业务类上注入这个bean即可:

    @Inject
    private RestTemplate restTemplate;
    public void sendPost() {
        .........
        //xxpojo是个pojo类,post请求中要放在http request body域中
        String requestBody = JSONObject.toJSONString(xxpojo);
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        HttpEntity<String> httpEntity = new HttpEntity<String>(requestBody, headers);
        restTemplate.postForEntity(toUrl, httpEntity, String.class);
        .............
    }

运行之后,对端服务报body域中的json解析失败,一脸懵逼。各种百度各种调试,中间的艰辛就不记录了(中途还换过java原生的Http Connection,是OK的)
后来换了另一种resttemplate注入来获得resttemplate实例:

RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
restTemplate.postForEntity(toUrl, httpEntity, String.class);

然后debug这两者之间的区别,发现第一种注入的restemplate是通过SimpleClientHttpRequestFactory获取实例的,第二种是通过BufferingClientHttpRequestFactory。百度了下网上说SimpleClientHttpRequestFactory是ClientHttpRequestFactory的装饰器方法,用来创建ClientHttpRequest。BufferingClientHttpRequestFactory用了JDK原生的方法(java.net包),不依赖于第三方库,例如Appache的Http相关的库。
然鹅 我还是没明白为什么第一种方式json会解析失败,最后在debug resttemplate.doWithRequest代码的时候,第一种方式比第二种多了一个fastjson转换器,第一种有八个,第二种是七个(我在项目中用了fastJson注入到了HttpMessageConverters中):
Spring Resttemplate post方法踩坑记录_第1张图片

然后我推断是fastJson的原因,把fastJson注入移除,用第一种方法就好了!!!
还有然后!!第一种方法中,HttpEntity构造方法中,直接传入pojo对象代替原先的json字符串也是可以的,不用JSONObject.toJSONString()方法转!

总结

归根结底的原因其实我还是没找到,一般情况下,如果要用restTemplate发restful post请求,且要携带header域,body中的内容是最好要转成json字符串的,然而~~如果项目中用了fastJson,restTemplate内部会用fastjson去转这个字符串作为http body域内容,这时发过去的body域内容就不对了。

PS:找问题过程中,一直想抓包,试了fiddler,抓不到本地代码运行发出去的post请求,用了wireshark,抓的太底层了,抓 的是tcp/udp层的,目前还在寻找方案中~~

你可能感兴趣的:(Spring Resttemplate post方法踩坑记录)