项目中使用RestTemplate调用第三方系统void接口下载附件

  • 背景介绍
    新项目开发,需要将老项目的历史数据迁移过来,出于种种原因,最终决定不真正迁移老项目的附件,而是在新项目中调用老项目的接口下载附件、查看附件。

  • 分析
    新老项目的服务端都是基于SpringMvc的java web项目,因此考虑在新项目的服务端使用RestTemplate去调用老项目的下载接口,获取到附件的byte[]
    这个过程中主要考虑两个问题:
    1.需要解决访问老项目下载接口的权限问题
    2.需要了解老项目下载接口返回的数据格式,以便新项目接收数据后进行处理

  • 解决步骤
    针对问题1有两个解决方法:
    1.在老项目中放开下载接口的权限验证,比如在过滤器中将下载接口URL设置为免验证,此方法不安全
    2.在老项目中提供外部系统访问下载接口的专用用户,在新项目中首先使用此专用用户通过权限验证(比如登录),然后再访问下载接口

  • 下面提供方法2的具体实现代码:

1.首先配置RestTemplate到Spring容器中,可以指定远程调用的超时时间

<!-- 配置RestTemplate -->
    <!--Http client Factory-->
    <bean id="httpClientFactory" class="org.springframework.http.client.SimpleClientHttpRequestFactory">
        <property name="connectTimeout" value="${restTemplate.connectTimeout}"/>
        <property name="readTimeout" value="${restTemplate.readTimeout}"/>
    </bean>

    <!--RestTemplate-->
    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
        <constructor-arg ref="httpClientFactory"/>
    </bean>

2.使用RestTemplate先登录获取cookie再请求下载接口

//1.先登录,获取权限验证后的cookie
        String loginUrl = "http://localhost:8888/plat/login";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> loginMap = new LinkedMultiValueMap<>();//POST方式传参
        loginMap.add("username", "xxx");
        loginMap.add("password", "xxx");
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(loginMap, headers);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(loginUrl, request, String.class);
        String cookie = responseEntity.getHeaders().get("Set-Cookie").get(0);//拿到登录的cookie

        //2.携带cookie再请求下载接口
        List<String> cookies = new ArrayList<>();
        cookies.add(cookie);
        HttpHeaders downHeaders = new HttpHeaders();
        downHeaders.put(HttpHeaders.COOKIE, cookies);//请求下载接口时携带cookie
        HttpEntity<MultiValueMap<String, Integer>> downRequest = new HttpEntity<>(null, downHeaders);//GET请求,这里即使把null改为map传参,服务端也获取不到数据
        String url = "http://localhost:8888/plat/attach/download?id=" + 888;//GET请求,在url后拼接传参
        ResponseEntity<byte[]> exchange = restTemplate.exchange(url, HttpMethod.GET, downRequest, byte[].class);
        byte[] data = exchange.getBody();//附件数据

3.老项目中下载接口返回值类型是void,通过OutputStream流输出数据,因此使用RestTemplate的exchange方法。如果老项目下载接口返回值类型是ResponseEntity,可能就不是调exchange方法了(本人未再继续测试验证,欢迎大家在评论区给出答案~~)

   OutputStream outputStream = null;
   try {
    
    
       outputStream = response.getOutputStream();
       outputStream.write(data);
       outputStream.flush();
   } catch (IOException e) {
    
    
       throw new RuntimeException("文件下载失败", e);
   } finally {
    
    
       IOUtils.close(outputStream);
   }

ps:如果不需要header与传参,requestEntity可以传递null,没有问题。

//exchange方法源码
@Override
	public <T> ResponseEntity<T> exchange(String url, HttpMethod method,
			HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) throws RestClientException {
    
    

		RequestCallback requestCallback = httpEntityCallback(requestEntity, responseType);
		ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
		return execute(url, method, requestCallback, responseExtractor, uriVariables);
	}
//实际调用
ResponseEntity<byte[]> response = restTemplate.exchange(url, HttpMethod.GET, null, byte[].class);//传递null

Guess you like

Origin blog.csdn.net/csdnklsdm/article/details/120375202