Spring Resttemplate post方法踩坑记录

来源:互联网 发布:标书制作软件 编辑:程序博客网 时间:2024/05/19 20:48

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中):
这里写图片描述

然后我推断是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层的,目前还在寻找方案中~~

原创粉丝点击