diff --git a/README.md b/README.md index 8ecf44c..a28782e 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ gitee项目地址:[https://gitee.com/lianjiatech/retrofit-spring-boot-starter] com.github.lianjiatech retrofit-spring-boot-starter - 2.3.3 + 2.3.4 ``` @@ -59,7 +59,7 @@ gitee项目地址:[https://gitee.com/lianjiatech/retrofit-spring-boot-starter] com.github.lianjiatech retrofit-spring-boot-starter - 2.3.3 + 2.3.4 com.squareup.okhttp3 @@ -432,6 +432,17 @@ retrofit: 如果需要修改日志打印行为,继承`LoggingInterceptor`,并将其配置成Spring bean即可! +#### 聚合日志打印 + +如果需要将同一个请求的日志聚合在一起打印,可配置`AggregateLoggingInterceptor`。 + +```java + @Bean +public LoggingInterceptor loggingInterceptor(RetrofitProperties retrofitProperties){ + return new AggregateLoggingInterceptor(retrofitProperties.getGlobalLog()); + } +``` + ### 请求重试 组件支持支持全局重试和声明式重试。 diff --git a/pom.xml b/pom.xml index 0307e88..5163ebc 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.github.lianjiatech retrofit-spring-boot-starter - 2.3.3 + 2.3.4 retrofit-spring-boot-starter retrofit-spring-boot-starter diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/AggregateLoggingInterceptor.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/AggregateLoggingInterceptor.java new file mode 100644 index 0000000..8834c9a --- /dev/null +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/AggregateLoggingInterceptor.java @@ -0,0 +1,55 @@ +package com.github.lianjiatech.retrofit.spring.boot.log; + +import java.io.IOException; + +import okhttp3.Response; +import okhttp3.logging.HttpLoggingInterceptor; + +/** + * 同一个请求的日志聚合在一起打印。 The logs of the same request are aggregated and printed together. + * @author 陈添明 + * @since 2022/5/31 10:49 上午 + */ +public class AggregateLoggingInterceptor extends LoggingInterceptor { + + public AggregateLoggingInterceptor(GlobalLogProperty globalLogProperty) { + super(globalLogProperty); + } + + @Override + public Response intercept(Chain chain) throws IOException { + Logging logging = findLogging(chain); + if (!needLog(logging)) { + return chain.proceed(chain.request()); + } + LogLevel logLevel = logging == null ? globalLogProperty.getLogLevel() : logging.logLevel(); + LogStrategy logStrategy = logging == null ? globalLogProperty.getLogStrategy() : logging.logStrategy(); + BufferingLogger bufferingLogger = new BufferingLogger(matchLogger(logLevel)); + HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(bufferingLogger) + .setLevel(HttpLoggingInterceptor.Level.valueOf(logStrategy.name())); + Response response = httpLoggingInterceptor.intercept(chain); + bufferingLogger.flush(); + return response; + } + + private static class BufferingLogger implements HttpLoggingInterceptor.Logger { + + private StringBuilder buffer = new StringBuilder(System.lineSeparator()); + + private final HttpLoggingInterceptor.Logger delegate; + + public BufferingLogger(HttpLoggingInterceptor.Logger delegate) { + this.delegate = delegate; + } + + @Override + public void log(String message) { + buffer.append(message).append(System.lineSeparator()); + } + + public void flush() { + delegate.log(buffer.toString()); + buffer = new StringBuilder(System.lineSeparator()); + } + } +} diff --git a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/LoggingInterceptor.java b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/LoggingInterceptor.java index 4f7a621..52b1f66 100644 --- a/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/LoggingInterceptor.java +++ b/src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/LoggingInterceptor.java @@ -8,7 +8,6 @@ import lombok.extern.slf4j.Slf4j; import okhttp3.Interceptor; -import okhttp3.Request; import okhttp3.Response; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Invocation; @@ -28,19 +27,22 @@ public LoggingInterceptor(GlobalLogProperty globalLogProperty) { @Override public Response intercept(Chain chain) throws IOException { - Request request = chain.request(); - Method method = Objects.requireNonNull(request.tag(Invocation.class)).method(); - Logging logging = AnnotationExtendUtils.findMergedAnnotation(method, method.getDeclaringClass(), Logging.class); + Logging logging = findLogging(chain); if (!needLog(logging)) { - return chain.proceed(request); + return chain.proceed(chain.request()); } LogLevel logLevel = logging == null ? globalLogProperty.getLogLevel() : logging.logLevel(); LogStrategy logStrategy = logging == null ? globalLogProperty.getLogStrategy() : logging.logStrategy(); - HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(matchLogger(logLevel)); - httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.valueOf(logStrategy.name())); + HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(matchLogger(logLevel)) + .setLevel(HttpLoggingInterceptor.Level.valueOf(logStrategy.name())); return httpLoggingInterceptor.intercept(chain); } + protected Logging findLogging(Chain chain) { + Method method = Objects.requireNonNull(chain.request().tag(Invocation.class)).method(); + return AnnotationExtendUtils.findMergedAnnotation(method, method.getDeclaringClass(), Logging.class); + } + protected boolean needLog(Logging logging) { if (globalLogProperty.isEnable()) { if (logging == null) { diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitStarterTest.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitStarterTest.java index fc465d4..0c971fc 100644 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitStarterTest.java +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitStarterTest.java @@ -8,6 +8,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; +import java.util.stream.IntStream; import org.junit.After; import org.junit.Assert; @@ -19,6 +20,7 @@ import org.springframework.test.context.junit4.SpringRunner; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.lianjiatech.retrofit.spring.boot.test.entity.Person; @@ -107,6 +109,40 @@ public void testGetPersonBody() throws Exception { System.out.println(personBody); } + @Test + public void testAggregateLoggingInterceptor() { + IntStream.range(1, 1000) + .parallel() + .forEach(i -> { + // mock + Person mockPerson = new Person().setId(1L) + .setName("test") + .setAge(10); + Result mockResult = new Result<>() + .setCode(0) + .setMsg("ok") + .setData(mockPerson); + MockResponse response = null; + try { + response = new MockResponse() + .setResponseCode(200) + .addHeader("Content-Type", "application/json; charset=utf-8") + .addHeader("Cache-Control", "no-cache") + .setBody(objectMapper.writeValueAsString(mockResult)); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + server.enqueue(response); + + Person person = new Person(); + person.setId(100L) + .setAge(10) + .setName("xx"); + Result personBody = httpApi2.getPersonBody(person); + System.out.println(personBody); + }); + } + @Test public void testRetrofitConfigRef() throws IOException { diff --git a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitTestApplication.java b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitTestApplication.java index de7c7d0..43270fd 100644 --- a/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitTestApplication.java +++ b/src/test/java/com/github/lianjiatech/retrofit/spring/boot/test/RetrofitTestApplication.java @@ -3,6 +3,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.context.annotation.Bean; +import com.github.lianjiatech.retrofit.spring.boot.config.RetrofitProperties; +import com.github.lianjiatech.retrofit.spring.boot.log.AggregateLoggingInterceptor; +import com.github.lianjiatech.retrofit.spring.boot.log.LoggingInterceptor; + import lombok.extern.slf4j.Slf4j; import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.jaxb.JaxbConverterFactory; @@ -32,4 +36,10 @@ public JaxbConverterFactory jaxbConverterFactory() { public InvalidRespErrorDecoder invalidRespErrorDecoder() { return new InvalidRespErrorDecoder(); } + + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + @Bean + public LoggingInterceptor loggingInterceptor(RetrofitProperties retrofitProperties) { + return new AggregateLoggingInterceptor(retrofitProperties.getGlobalLog()); + } }