OpenFeign是一种声明式的Web服务客户端,它使得编写HTTP客户端变得更加简单和直观。它使用了注解方式来描述HTTP API,使得开发者可以使用Java接口来调用远程HTTP服务。
OpenFeign的核心特点包括:
声明式API: 您可以使用注解声明要调用的远程API,然后使用Java接口调用它们。
定制化接口: 您可以使用FeignBuilder类定制客户端接口的行为。
支持编码器和解码器: Feign支持多种编码器和解码器,可以将请求和响应转换为Java对象。
支持请求和响应压缩: OpenFeign支持gzip和deflate压缩算法。
支持负载均衡: OpenFeign可以与负载均衡组件(如Ribbon)一起使用,以实现服务调用的负载均衡。
总之,OpenFeign是一个方便易用的Web服务客户端,可以帮助开发者快速、灵活地调用远程HTTP服务。
业务场景:获取下游服务的文件下载流,然后上传到minio,获取分享链接
场景复现
代码
rpc类
@FeignClient(url = "ip:port", name = "infer")
public interface InferRpcService {@GetMapping(value = "/download", consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)Response download(@RequestParam("text") String text);
}
调用类
@Slf4j
@Service
public class InferServiceImpl implements InferService {@Resourceprivate InferRpcService inferRpcService;@Resourceprivate MinioClient minioClient;@Overridepublic CommonResponse<String> tts(InferRequest inferRequest, HttpServletResponse response) {if (!CollectionUtils.isEmpty(userRecords) && Objects.nonNull(inferRequest) && StringUtils.isNoneEmpty(inferRequest.getText())) {try {Response transferred = inferRpcService.transferString(inferRequest.getText());Response.Body body = transferred.body();if (Objects.nonNull(body) && !body.isRepeatable()) {record.setTtsStatus(InferStatusConstant.SYNTHESIS_SUCCESSFUL);InputStream in = body.asInputStream();String filename = UUID.randomUUID().toString().replaceAll("-",""); String sharedWavUrl = MinioUtils.uploadFile(minioClient, in, MinioConstant.VITS_BUCKET, allFilename);record.setSharedWavUrl(sharedWavUrl);return CommonResponse.ok(sharedWavUrl);}} catch (IOException e) {throw new RuntimeException(e);}}return CommonResponse.error("合成失败");}
}
工具类
@Slf4j
public class MinioUtils {public static String uploadFile(MinioClient minioClient, InputStream inputStream, String bucket, String filename) {try {log.info("返回的字节流大小: {}",inputStream.available());boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket("public").build());if (!found) {minioClient.makeBucket(MakeBucketArgs.builder().bucket("public").build());}ObjectWriteResponse response = minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(filename).stream(inputStream, inputStream.available(), -1).contentType(InferStatusConstant.WAV_CONTENT_TYPE).build());String url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucket).expiry(7 * 24 * 60 * 60).object(filename).method(Method.GET).build());log.info("分享地址:" + url);return url;} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException |InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException |XmlParserException e) {throw new RuntimeException(e);}}
}
现象
比如获取下又服务的音频的时候,会出现不完整的情况,我这边的现象是只有前五秒的音频
解决
借助restTemplate
代码
@Configuration
public class RestTemplateConfiguration {@Beanpublic RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {RestTemplate restTemplate = restTemplateBuilder.build();return restTemplate;}
}
public CommonResponse<String> download(InferRequest inferRequest, HttpServletResponse response, int a) {String url = "you_url";ResponseEntity<byte[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null,byte[].class);byte[] bytes = responseEntity.getBody();if (!ArrayUtils.isEmpty(bytes)) {record.setTtsStatus(InferStatusConstant.SYNTHESIS_SUCCESSFUL);String filename = UUID.randomUUID().toString().replaceAll("-", "");String allFilename = "/" + openId + "/" + filename + MinioConstant.WAV_SUFFIX;String sharedWavUrl = MinioUtils.uploadFile(minioClient, new ByteArrayInputStream(bytes), MinioConstant.VITS_BUCKET, allFilename);return CommonResponse.ok(sharedWavUrl);return CommonResponse.error("失败");}
下载没有问题