需求:
- 现在有两个系统,一个是SSM架构系统,一个是SpringCloud架构系统
- 现在SpringCloud系统要求下载SSM系统的文件,采取调用SSM系统接口的方式
- 通过调用SpringCloud接口实现下载
主要操作可以分成三步:
- 获取token
- 请求SSM系统获取文件的字节流和文件信息
- 将请求的字节流重新装配在SpringCloud系统的返回参数里
这样就完成了接口的穿透转载了。
token的获取就不说了,不同的系统获取的方式也不同,下面说一下获取SSM系统的字节流:
@Override
public void downloadFile(HttpServletResponse response, String fileId) {
HttpHeaders headers = new HttpHeaders();
String url = "http://xxxxxxxx/file/download?fileId=" + fileId;
String token = "bearer " + this.sendToken();
headers.add("Authorization", token);
//请求SSM系统获取要下载的文件流
ResponseEntity<byte[]> responseNew = Singleton.INSTANCE.getRestTemplate().exchange(url, HttpMethod.GET, new HttpEntity<byte[]>(headers), byte[].class);
logger.info("=================状态码=================");
logger.info(CommonConstant.LOG_LOG_PARAM, responseNew.getStatusCodeValue());
logger.info("================返回信息================");
logger.info(CommonConstant.LOG_LOG_PARAM, responseNew.getHeaders().getContentType());
logger.info(CommonConstant.LOG_LOG_PARAM, responseNew.getHeaders().getContentType().getSubtype());
logger.info("=======================================");
// 下载文件
this.sendFile(response, responseNew);
}
this.sendToken()
是获取token的方法;
this.sendFile(response, responseNew)
是重新装配字节流的方法:
private void sendFile(HttpServletResponse response, ResponseEntity<byte[]> responseNew) {
//获取请求SSM系统返回报文中文件字节码
byte[] result = responseNew.getBody();
//将数据回写到SpringCloud系统返回参数
response.setHeader("content-type", String.valueOf(responseNew.getHeaders().getContentType()));
response.setHeader("Content-Disposition", String.valueOf(responseNew.getHeaders().getContentDisposition()));
response.setHeader("Accept-Ranges", "bytes");
response.setContentType(String.valueOf(responseNew.getHeaders().getContentType()));
try (InputStream inputStream = new ByteArrayInputStream(result); OutputStream outputStream = response.getOutputStream()) {
byte[] buff = new byte[1024];
// 读取字节流
int read = inputStream.read(buff);
//通过while循环写入到指定了的对象中
while (read != -1) {
outputStream.write(buff, 0, buff.length);
outputStream.flush();
read = inputStream.read(buff);
}
} catch (IOException e) {
e.printStackTrace();
throw new CommonException(MessagesConstant.PTP_COMMON_FILE_DOWNLOAD_ERROR);
}
}
这时候就完成了文件接口的穿透了。我这个接口只要一个文件的id就可以下载了。
@ApiOperation(value = "通用PTP文件下载")
@GetMapping("/all/download/{fileId}")
public ResponseEntity downloadPtpFile(@ApiParam(value = "文件ID", required = true, name = "fileId") @PathVariable String fileId, HttpServletResponse response) {
fileService.downloadFile(response, fileId);
return Results.success();
}
调用这个接口,就可以下载SSM系统的文件了。
这里要注意一点,在springCloud中RestTemplate原来的配置可能用做Feign调用了,这是要重新创建一个RestTemplate来使用。这里给一个单例的写法
public enum RestTemplateSingleton {
INSTANCE;
public RestTemplate getRestTemplate() {
// 长连接保持时长30秒
PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(
30, TimeUnit.SECONDS);
// 最大连接数
pollingConnectionManager.setMaxTotal(3000);
// 单路由的并发数
pollingConnectionManager.setDefaultMaxPerRoute(100);
HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setConnectionManager(pollingConnectionManager);
// 重试次数2次,并开启
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(2, true));
// 保持长连接配置,需要在头添加Keep-Alive
httpClientBuilder
.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());
HttpClient httpClient = httpClientBuilder.build();
// httpClient连接底层配置clientHttpRequestFactory
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
clientHttpRequestFactory.setReadTimeout(15000);
clientHttpRequestFactory.setConnectTimeout(15000);
return new RestTemplate(clientHttpRequestFactory);
}
}
这样就创建一个可以使用的RestTemplate对象了。