Spring RestTemplate远程调用过程

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Spring RestTemplate远程调用过程

盛世如恋   2022-11-22 我要评论

Spring RestTemplate远程调用 

之前在一个服务中调用另一个服务的请求,可以使用UrlConnection类来拼接Http请求头,这个时候就会发现,很麻烦,使用SpringRestTemplate的话 进一步封装了拼接的代码,相对于来说较为便捷。

Spring RestTemplate封装了http请求,可以较为方便的在一个服务中调用另一个服务的请求。
 

说明: 下面的例子是 使用端口为 8075的服务 ,通过get/id来远程调用端口8086的服务的请求。

1、pom.xml加入

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2、调用服务中的SpringBoot启动类注入RestTemplate

 @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

3、在需要使用的Controller类中自动导入RestTemplate

 	@Autowired
    RestTemplate restTemplate;

4、根据调用某服务的ip拼接 url

调用RestTemplate的api获取响应内容

    @RequestMapping("get/{id}")
    public User getById(@PathVariable("id") Integer id ){
        String url = "http://localhost:8086/get/"+id;
        User s = restTemplate.getForObject(url,User.class);
        return s;
    }

5、测试

调用成功

5、出现的问题和解决

如果使用RestTemplate的话,虽然为我们封装了http请求头等信息,但是url需要自己写,不够灵活。

1、如果调用的服务是一个集群呢,固定了ip地址是否不妥,解决方案是使用ribbon,保证多个服务集群用的服务名是一致的,拼接的url 的ip地址用服务名来拼接,这个时候就可以用一个url访问多个端口号不一样的相同服务了,ribbon会将服务名转换成可以用的端口号。但是调用的服务有多个,如何来选择一个服务请求呢?这个时候就需要一个负载均衡算法,常用的负载均衡的算法有 轮询等。 

2、用于拼接的http还是感觉不够简便,还需要自己去拼接,可不可以更加灵活?可以使用feign来代替RestTemplate,feign是一个声明式的远程调用,集成了ribbon和hystrix。

RestTemplate远程调用时遇到的问题

最近公司给了个任务,让我跟第三方接口联调,正好项目使用的是SpringBoot那我自然而然想到了SpringMVC提供的RestTemplate 来进行远程调用,但是在使用RestTemplate远程调用时出现了点问题…

提示:以下是本篇文章正文内容,下面案例可供参考

1.引入代码

代码如下(示例):

  ResponseEntity<String> responseEntity = restTemplate.postForEntity(activityParameterConfig.getPakageProvide() + "?sign=" + sign, jsonValue, String.class);
  String body = responseEntity.getBody();
  System.out.println("body = " + body);

在将结果转化为String时成功获取到了结果:

body = {"status":100,"msg":"发送成功","info":{"telphonenum":"*******1272","list":[{"ticketnum":"94330075353","start_use_date":"2021-03-09","end_use_date":"2031-03-09"}],"serial":"fa6b0592741a4d838c6a4737323c0c34","serial_number":"202103091614452220"}}

但是直接转换为String还要再将其转换为DTO,所以索性就选择直接选择在RestTemplate封装结果时直接装换为对应DTO

2.引入代码

代码如下(示例):

   ResponseEntity<GiftDistributeResDTO> entity = restTemplate.postForEntity(activityParameterConfig.getPakageProvide() + "?sign=" + sign, jsonValue, GiftDistributeResDTO.class);
   GiftDistributeResDTO distributeResDTO = entity.getBody();
   System.out.println("distributeResDTO = " + distributeResDTO);

结果报错了…提示没有对应的HttpMessageConverter处理类型为Content Type [text/html;charset=utf-8]] 的数据。

2021-03-09 16:14:47.221 ERROR 13548 --- [nio-8082-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.UnknownContentTypeException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.example.demo.user.dto.GiftDistributeResDTO] and content type [text/html;charset=utf-8]] with root cause
org.springframework.web.client.UnknownContentTypeException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.example.demo.user.dto.GiftDistributeResDTO] and content type [text/html;charset=utf-8]

小结

于是Debug了下发现RestTemplate中存在7种转换器:


其中将结果转换为我们要的DTO的是MappingJackson2HttpMessageConverter这个转换器,再进去看看这个转换器属性:


结果发现这个转换器所支持的MediaTypes不存在上述text/html这种类型,所以才会报错,既然找到了问题那就在创建RestTemplate时给它多加一些支持的类型:

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
        for (HttpMessageConverter<?> httpMessageConverter : converters) {
            if(httpMessageConverter instanceof MappingJackson2HttpMessageConverter){
                ArrayList<MediaType> mediaTypes = new ArrayList<>();
                mediaTypes.add(MediaType.ALL);
                ((MappingJackson2HttpMessageConverter) httpMessageConverter).setSupportedMediaTypes(mediaTypes);
            }
        }
        return restTemplate;
    }

再次调试发现结果已经可以正常封装到我们需要的DTO了:

distributeResDTO = GiftDistributeResDTO(status=100, msg=发送礼包成功!, info=GiftDistributeInfo(telphonenum=*******1272, serial_number=202103091641391875, serial=27c66dbdce6a476481e895b852d82fd3, list=[GiftDistributeList(ticketnum=94330070661, start_use_date=2021-03-09, end_use_date=2031-03-09)]), url=null)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们