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 {
@Resource
private InferRpcService inferRpcService;
@Resource
private MinioClient minioClient;
@Override
public 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 {
@Bean
public 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("失败");
}
下载没有问题