欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

RestTemplate填坑记录

程序员文章站 2022-03-04 20:10:46
...

背景

由于公司的项目是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;
    }

结束

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

相关标签: RestTemplate