RestTemplate填坑记录

版权声明:本文为博主原创文章,如需转载请注明出处 https://blog.csdn.net/linghuanxu/article/details/88937918

背景

由于公司的项目是udp服务器需要调用外部接口读取配置,否则耦合划分就会存在问题。前期考虑简单实现,就没有引入rpc框架。虽然都是springboot项目,但是暂时还是先不考虑引入springcloud,复杂度会陡然上升。于是,就有了这次尝试。
  我这里有两个项目,其中一个是中规中矩的springboot web项目,提供rest接口,另一个也是springboot项目,但是,我们剔除了web启动,使用的是netty的udp服务进行监听,所以,这个里面是没有spring.web.client依赖的。其它的,暂时就不重要了,我们开始记录填坑记录。

引入

这里我们需要在udp服务中引入RestTemplate这个类,但是我又不想引入web的autoconfig,添加web服务器,所以,我添加了如下依赖:

<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-web</artifactId>
		<version>${spring.version}</version>
</dependency>

这里,我的spring的版本是5.0.8.RELEASE,我的springboot是2.0.4.RELEASE的。另外,RestTemplate是一个单独的类,并不需要进行配置就可以直接使用。我开始,调用的是postForEntity。

填坑

List泛型丢失

这里坑就开始了,第一个坑是List。进入断点调试可以看到,直接返回list或者带list的返回值,list里的内容都会变成LinkedHashMap。这事我找了老半天才找到原因。本质上的原因是因为在Json中并没有携带类型信息,而反序列化给的类型也給不进list里的泛型,所以解析后就都是LinkedHashMap。然后,你就会发现,虽然你能拿到response但是无法遍历。解决方法说来也简单,使用exchange方法就可以了。先看我最终的调用代码吧:

result=restTemplate.exchange(url, HttpMethod.POST, null, new ParameterizedTypeReference<DefaultResponse<SensorListResponse>>() {}).getBody();

但是,这里又有另外一个坑。ParameterizedTypeReference中的泛型不可以是方法或者类泛型里的T,而必须是你要的那个类型。原因应该和java的类型擦出有关,这里坑了我很久。这里因为new了ParameterizedTypeReference实例,所以会有类型信息进行反序列化,就不会有类型丢失的问题了。

序列化格式

我这里为了适应web端,在接口提供方将Date类型序列化成了yyyy-MM-dd HH:mm:ss。然后,过了上面那关后就报这个错误了。这个问题的解决其实和我web端的解决差不多。总体思路就是,提供一个restTemplate工厂方法,在工厂方法里将自定义序列化配置好。我这里采用的是将RestTemplate注册成一个bean,然后获取这个bean来进行调用。具体配置如下:

    @Bean
    public RestTemplate createRestTemplate() {

        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        objectMapper.setDateFormat(dateFormat);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);

        RestTemplate restTemplate = new RestTemplate();
        List<HttpMessageConverter<?>> converters = new ArrayList<>();
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        jsonConverter.setObjectMapper(objectMapper);
        converters.add(jsonConverter);
        restTemplate.setMessageConverters(converters);
        return restTemplate;
    }

结束

总体来说,都是些会用不会用,知道和不知道的事。记录在此,备查。

猜你喜欢

转载自blog.csdn.net/linghuanxu/article/details/88937918