zl程序教程

您现在的位置是:首页 >  后端

当前栏目

SpringBoot 整合 RestTemplate

SpringBoot 整合 RestTemplate
2023-09-11 14:20:02 时间

目录

一、概述

1. 介绍

二、整合 RestTemplate

1. RestTemplateConfig 配置类

2. 工具类

3. RestTemplate 方法

4. getForEntity 方法

4.  exchange 方法

5.  postForEntity 方法

三、测试案例

1. RestTemplateController

2. 测试开始


如果发现本文有错误的地方,请大家毫不吝啬,多多指教,欢迎大家评论,谢谢! 

 


一、概述

当我们业务需求上,需要调用第三方外部接口数据,使用 RestTemplate 调用是一个不错的选择,调用起来比较灵活。

1. 介绍

Spring 框架提供的 RestTemplate 类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接,我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。

二、整合 RestTemplate

1. RestTemplateConfig 配置类

/**
 * RestTemplate配置
 * 这是一种JavaConfig的容器配置,用于spring容器的bean收集与注册,并通过参数传递的方式实现依赖注入。
 * "@Configuration"注解标注的配置类,都是spring容器配置类,springboot通过"@EnableAutoConfiguration"
 * 注解将所有标注了"@Configuration"注解的配置类,"一股脑儿"全部注入spring容器中。
 * 
 * @author Zou.LiPing
 *
 */
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(@Qualifier("simpleClientHttpRequestFactory") ClientHttpRequestFactory factory){
        return new RestTemplate(factory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(15000);
        // 获取数据超时时间 毫秒
        factory.setReadTimeout(5000);
        return factory;
    }

}

2. 工具类


/**
 * 从配置文件获取URL
 * @date: 2021/4/29 14:48
 */
@Data
@Component
@ConfigurationProperties("remote.call")
public class RemoteCallProperties {

    private String productUrl;


}




@Slf4j
public class UrlUtils {

    /** 
     * url拼接参数
     * @param url
     * @param object
     * @date: 2020/6/19 11:51
     * @return: java.lang.String 
     */
    public static String getUrlAppendParm(String url, Object object) {
        StringBuffer stringBuffer = new StringBuffer(url);
        if (object instanceof Map) {
            Iterator iterator = ((Map) object).entrySet().iterator();
            if (iterator.hasNext()) {
                stringBuffer.append("?");
                Object element;
                while (iterator.hasNext()) {
                    element = iterator.next();
                    Map.Entry<String, Object> entry = (Map.Entry) element;
                    //过滤value为null,value为null时进行拼接字符串会变成 "null"字符串
                    if (entry.getValue() != null) {
                        stringBuffer.append(element).append("&");
                    }
                    url = stringBuffer.substring(0, stringBuffer.length() - 1);
                }
            }
        } else {
            throw new RuntimeException("url请求:" + url + "请求参数有误不是map类型");
        }
        log.info("url请求:" + url);
        return url;
    }
}



/**
 * 商品服务URL常量
 */
public interface ProductApiUrlConstants {

	/**
	 * 获取商品信息
	 */
	String GET_PRODUCT = "/product/getProduct";

    String INSERT_PRODUCT = "/product/insertProduct";
}


3. RestTemplate 方法

RestTemplate 定义了36个与 REST 资源交互的方法,其中的大多数都对应于HTTP的方法。
其实,这里面只有 11 个独立的方法,其中有十个有三种重载形式,而第十一个则重载了六次,这样一共形成了 36 个方法。

  • delete() 在特定的URL上对资源执行HTTP DELETE操作
  • exchange() 在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中映射得到的
  • execute() 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象
  • getForEntity() 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
  • getForObject() 发送一个HTTP GET请求,返回的请求体将映射为一个对象
  • postForEntity() POST 数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的
  • postForObject() POST 数据到一个URL,返回根据响应体匹配形成的对象
  • headForHeaders() 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
  • optionsForAllow() 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息
  • postForLocation() POST 数据到一个URL,返回新创建资源的URL
  • put() PUT 资源到特定的URL

4. getForEntity 方法

@Override
    public ProductResp getByProductId(Long productId) {

        log.info("getProduct.req productId={}", productId);
        ProductResp productResp = new ProductResp();
        Map<String, Object> mapPram = new HashMap<>(1);
        mapPram.put("productId", productId);
        String urlAppendParm = UrlUtils.getUrlAppendParm(remoteCallProperties.getProductUrl() + ProductApiUrlConstants.GET_PRODUCT, mapPram);
        ResponseEntity<Result> response = restTemplate.getForEntity(urlAppendParm, Result.class, productId);
        if (HttpStatus.OK.equals(response.getStatusCode())) {
            Result<Product> result = response.getBody();
            // java.util.LinkedHashMap cannot be cast to com.zlp.dto.Product
            Product product = dataConverObj(result);
            BeanUtils.copyProperties(product,productResp);
        }
        return productResp;
    }

    private Product dataConverObj(Result<Product> result) {
        return new Gson().fromJson(new Gson().toJson(result.getData()), new TypeToken<Product>(){}.getType());
    }

4.  exchange 方法

@SneakyThrows
    @Override
    public ProductResp getProduct(Long productId) {

        log.info("getProduct.req productId={}", productId);
        ProductResp productResp = new ProductResp();
        Map<String, Object> mapPram = new HashMap<>(1);
        mapPram.put("productId", productId);
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add("Authorization", UUID.randomUUID().toString());
        HttpEntity<String> requestEntity = new HttpEntity<>(null, requestHeaders);
        // 请求调用
        String urlAppendParm = UrlUtils.getUrlAppendParm(remoteCallProperties.getProductUrl() + ProductApiUrlConstants.GET_PRODUCT, mapPram);
        log.info("getProduct  resp={}", urlAppendParm);
        ResponseEntity<String> response = restTemplate.exchange(urlAppendParm, HttpMethod.GET, requestEntity, String.class);
        HttpStatus statusCode = response.getStatusCode();
        if (HttpStatus.OK.equals(statusCode)) {
            String body = response.getBody();
            if (StringUtils.isNotBlank(body)) {
                String data = JSON.parseObject(body).getString("data");
                productResp = JSON.parseObject(data, ProductResp.class);
                log.info("getProduct.urlAppendParm={}  resp={}", ProductApiUrlConstants.GET_PRODUCT, JSON.toJSONString(productResp));
            }
        } else {
            throw new Exception(String.format("远程调用 [%s] 接口失败!", urlAppendParm));
        }
        return productResp;
    }

5.  postForEntity 方法

 @Override
    public Boolean insertProduct(ProductResp productResp) throws Exception {

        log.info("insertProduct.req productResp={}", JSON.toJSONString(productResp));
        HttpEntity<String> httpEntity = RestTemplateUtils.buildPostForEntity(JSON.toJSONString(productResp));
        String insertPorductUrl = "";
        try {
            insertPorductUrl = remoteCallProperties.getProductUrl() + ProductApiUrlConstants.INSERT_PRODUCT;
            ResponseEntity<String> response = restTemplate.postForEntity(insertPorductUrl, httpEntity, String.class);
            HttpStatus statusCode = response.getStatusCode();
            if (HttpStatus.OK.equals(statusCode)) {
                log.info("insertProduct.resp={}", response.getBody());
            }
        } catch (Exception e) {
            throw new Exception(String.format("远程调用 [%s] 接口失败!", insertPorductUrl));
        }
        return Boolean.TRUE;
    }

三、测试案例

1. RestTemplateController


@RestController
@RequestMapping("remote")
@RequiredArgsConstructor
@Api(value = "远程调用模块", tags = "远程调用模块")
@Slf4j(topic = "RestTemplateController")
public class RestTemplateController {

    private final RemoteService remoteService;

    @GetMapping("/getProduct")
    @ApiOperation(value = "获取商品信息")
    public ProductResp getProduct(@RequestParam (value = "productId") Long productId) {

        return remoteService.getProduct(productId);
    }

    @PostMapping("/insertProduct")
    @ApiOperation(value = "新增商品信息")
    public Boolean insertProduct(@RequestBody ProductResp productResp) throws Exception {

        return remoteService.insertProduct(productResp);
    }

    @GetMapping("/getByProductId")
    @ApiOperation(value = "获取商品信息根据商品ID")
    public ProductResp getByProductId(@RequestParam (value = "productId") Long productId) {

        return remoteService.getByProductId(productId);
    }

}

2. 测试开始

服务名称端口访问地址
product-service (生产者)8300http://127.0.0.1:8300
user-service (调用方)8200http://127.0.0.1:8200

 

swagger 接口测试   http://127.0.0.1:8200/doc.html

/remote/getByProductId

 

 

参考文档
1. springboot 2.0 整合 RestTemplate 与使用教程