支持文件传输
依赖 https://github.com/OpenFeign/feign-form
spring-cloud-starter-openfeign里包含。
示例代码:
@Configuration
public class MultipartSupportConfiguration {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
/**
* 支持form表单
*/
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
/**
* FieldQueryMapEncoder 替换为 BeanQueryMapEncoder,解析父类属性
*/
@Bean
public Feign.Builder feignBuilder() {
return Feign.builder()
.queryMapEncoder(new BeanQueryMapEncoder())
.retryer(Retryer.NEVER_RETRY);
}
}
//--------------------------------------------------
feign client 接口定义:
@PostMapping(value = "/file/upload/single", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
ApiResponse<FileUploadResponse> uploadSingle(@RequestPart("file") MultipartFile file, @SpringQueryMap FileUploadRequest fileUploadRequest);
//--------------------------------------------
使用自定义配置
@FeignClient(value = "credit-file-service", path = "credit-file-service",
configuration = {MultipartSupportConfiguration.class, FeignLoggingConfiguration.class})
public interface CreditFileApi {}
fegin log
@Configuration
public class FeignLoggingConfiguration {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
Logger customFeignInfoLogger() {
return new CustomFeignInfoLogger();
}
}
@Slf4j
public class CustomFeignInfoLogger extends Slf4jLogger {
@Override
protected void logRequest(String configKey, Level logLevel, Request request) {
FeignRequest feignRequest = new FeignRequest();
feignRequest.setMethod(request.method());
feignRequest.setUrl(request.url());
if (logLevel.ordinal() >= Level.HEADERS.ordinal()) {
for (String field : request.headers().keySet()) {
for (String value : valuesOrEmpty(request.headers(), field)) {
feignRequest.addHeader(field, value);
}
}
int bodyLength = 0;
if (request.body() != null) {
bodyLength = request.body().length;
if (logLevel.ordinal() >= Level.FULL.ordinal()) {
feignRequest.setBody(request.charset() != null ? new String(request.body(), request.charset()) : "Binary data");
}
}
feignRequest.setBodyLength(bodyLength);
}
log.info("{} == >> feign Request : {} ", configKey, feignRequest);
}
@Override
protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime) throws IOException {
FeignResponse feignResponse = new FeignResponse();
int status = response.status();
feignResponse.setStatus(response.status());
feignResponse.setReason(response.reason() != null && logLevel.compareTo(Level.NONE) > 0 ? " " + response.reason() : "");
feignResponse.setTimeTaken(elapsedTime);
if (logLevel.ordinal() >= Level.HEADERS.ordinal()) {
for (String field : response.headers().keySet()) {
for (String value : valuesOrEmpty(response.headers(), field)) {
feignResponse.addHeader(field, value);
}
}
if (response.body() != null && !(status == 204 || status == 205)) {
byte[] bodyData = Util.toByteArray(response.body().asInputStream());
if (logLevel.ordinal() >= Level.FULL.ordinal() && bodyData.length > 0) {
feignResponse.setBody(Util.decodeOrDefault(bodyData, UTF_8, "Binary data"));
}
log.info("{} << == feign Response : {} ", configKey, feignResponse);
return response.toBuilder().body(bodyData).build();
} else {
log.info("{} << == feign Response : {} ", configKey, feignResponse);
}
}
return response;
}
@Setter
private class FeignResponse {
private int status;
private String reason;
private long timeTaken;
private List<String> headers;
private String body;
public void addHeader(String key, String value) {
if (headers == null) {
headers = new ArrayList<>();
}
headers.add(String.format("%s: %s", key, value));
}
@Override
public String toString() {
return String.format("Status = %s, Reason = %s, TimeTaken = %s, Headers = %s Body = %s, BodyLength = %s Bytes",
status, reason, timeTaken, headers, body, (body != null && body.trim().length() > 0 ? body.length() : 0));
}
}
@Setter
private class FeignRequest {
private String method;
private String url;
private List<String> headers;
private String body;
private int bodyLength;
public void addHeader(String key, String value) {
if (headers == null) {
headers = new ArrayList<>();
}
headers.add(String.format("%s: %s", key, value));
}
@Override
public String toString() {
return String.format("Method = %s, url = %s, Headers = %s Body = %s, BodyLength = %s Bytes",
method, url, headers, body, bodyLength);
}
}
}
使用httpclient线程池
依赖
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
配置
application.yaml
feign:
httpclient:
enabled: true