开发者

Spring RestTemplate远程调用过程

开发者 https://www.devze.com 2022-11-28 13:55 出处:网络 作者: 盛世如恋
目录SpringRestTemplate远程调用1、pom.xml加入2、调用服务中的SpringBoot启动类注入RestTemplate3、在需要使用的Controller类中自动导入RestT...
目录
  • Spring RestTemplate远程调用 
    • 1、pom.XML加入
    • 2、调用服务中的SpringBoot启动类注入RestTemplate
    • 3、在需要使用的Controller类中自动导入RestTemplate
    • 4、根据调用某服务的ip拼接 url
    • 5、测试
    • 5、出现的问题和解决
  • RestTemplate远程调用时遇到的问题
    • 1.引入代码
    • 2.引入代码
    • 小结

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

Spring RestTemplate远程调用过程

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

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

Spring RestTemplate远程调用过程

 	@Autowired
    RestTemplate restTemplate;

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

调用RestTemplate的api获取响应内容

Spring RestTemplate远程调用过程

    @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、测试

调用成功

Spring RestTemplate远程调用过程

5、出现的问题和解决

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

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

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

RestTemplate远程调用时遇到的问题

最近公司给了个任务,让我跟第三方接口联调,正android好项目使用的是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种转换器:

Spring RestTemplate远程调用过程

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

Spring RestTemplate远程调用过程

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

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

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

distributeResDTO = GiftDistributeResDTO(status=100, msg=发送礼包成功!, infjavascripto=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)

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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号