봄 부팅 프로젝트의 우아한 http 클라이언트 도구, 정말 향기 롭습니다!

okhttp가 square company에서 오픈 소스로 제공하는 http 클라이언트 도구의 자바 버전이라는 것을 누구나 알고 있습니다. 사실 square는 인터페이스를 통한 http 요청의 시작을 지원하기 위해 추가로 캡슐화하기 위해 okhttp를 기반으로하는 개조 도구를 오픈 소스로 제공했습니다. 프로젝트에서 여전히 RestTemplate 또는 okhttp를 직접 사용하거나이를 기반으로하는 HttpUtils를 사용하는 경우 Retrofit을 사용해 볼 수 있습니다.

retrofit-spring-boot-starter는 Retrofit 및 spring-boot 프레임 워크의 신속한 통합을 실현하고 일부 기능 향상을 지원하여 spring-boot 프로젝트에서 http 인터페이스 호출의 개발을 크게 단순화합니다. 다음으로 retrofit-spring-boot-starter를 직접 사용하여 http 요청을 spring-boot 프로젝트에 보내는 것이 얼마나 쉬운 지 확인합니다.

Retrofit은 공식적으로 스프링 부트와의 빠른 통합을위한 스타터를 제공하지 않습니다. Retrofit-spring-boot-starter는 작성자가 패키지로 제공하며 프로덕션 환경에서 사용되었으며 매우 안정적입니다.

프로젝트 소스 코드 : retrofit-spring-boot-starter
는 종속성을 도입합니다.

<dependency>
    <groupId>com.github.lianjiatech</groupId>
    <artifactId>retrofit-spring-boot-starter</artifactId>
    <version>2.0.2</version>
</dependency>

@RetrofitScan 주석 구성

@Configuration을 사용하여 클래스에 대해 @RetrofitScan을 구성하거나 다음과 같이 스프링 부팅 시작 클래스에 직접 구성 할 수 있습니다.

@SpringBootApplication
@RetrofitScan("com.github.lianjiatech.retrofit.spring.boot.test")
public class RetrofitTestApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(RetrofitTestApplication.class, args);
    }
}

http 인터페이스 정의

인터페이스는 @RetrofitClient 주석으로 표시되어야합니다! http 관련 솔루션은 공식 문서 : 개조 공식 문서를 참조 할 수 있습니다.

@RetrofitClient(baseUrl = "${test.baseUrl}")
public interface HttpApi {
    
    

    @GET("person")
    Result<Person> getPerson(@Query("id") Long id);
}

주입 사용

다른 서비스에 인터페이스를 삽입하여 사용할 수 있습니다.

@Service
public class TestService {
    
    

    @Autowired
    private HttpApi httpApi;

    public void test() {
    
    
        // 通过httpApi发起http请求
    }
}

위의 단계를 수행하는 한 인터페이스를 통해 http 요청을 보낼 수 있습니다. 이것은 정말 간단합니다. spring-boot 프로젝트에서 mybatis를 사용한 적이 있다면 이런 사용 방법에 더 익숙 할 것이라고 믿습니다. 다음으로 retrofit-spring-boot-starter의 고급 기능을 계속 소개합니다.

주석이 달린 인터셉터

대부분의 경우 특정 인터페이스에서 특정 http 요청이 통합 차단 처리 로직을 수행하기를 바랍니다. 이때 주석이 달린 인터셉터를 사용할 수 있습니다. 사용되는 단계는 주로 두 단계로 나뉩니다.

차단 프로세서를 작성하려면 BasePathMatchInterceptor를 상속하고
인터페이스를 표시하려면 @Intercept를 사용하십시오.
다음은 어노테이션 인터셉터 사용 방법을 소개하기 위해 지정된 요청의 URL 뒤에 타임 스탬프를 스 플라이 싱하는 예입니다.

차단 프로세서를 작성하려면 BasePathMatchInterceptor를 상속하십시오.

@Component
public class TimeStampInterceptor extends BasePathMatchInterceptor {
    
    

    @Override
    public Response doIntercept(Chain chain) throws IOException {
    
    
        Request request = chain.request();
        HttpUrl url = request.url();
        long timestamp = System.currentTimeMillis();
        HttpUrl newUrl = url.newBuilder()
                .addQueryParameter("timestamp", String.valueOf(timestamp))
                .build();
        Request newRequest = request.newBuilder()
                .url(newUrl)
                .build();
        return chain.proceed(newRequest);
    }
}

@Intercept를 사용하여 인터페이스 표시

@RetrofitClient(baseUrl = "${test.baseUrl}")
@Intercept(handler = TimeStampInterceptor.class, include = {
    
    "/api/**"}, exclude = "/api/test/savePerson")
public interface HttpApi {
    
    

    @GET("person")
    Result<Person> getPerson(@Query("id") Long id);

    @POST("savePerson")
    Result<Person> savePerson(@Body Person person);
}

위의 @Intercept 구성은 HttpApi 인터페이스에서 / api / ** 경로 (/ api / test / savePerson 제외)에서 요청을 가로 채고 가로 채 프로세서는 TimeStampInterceptor를 사용함을 의미합니다.

확장 된 주석 인터셉터

때때로 인터 셉션 주석의 일부 매개 변수를 동적으로 전달한 다음 인터 셉션을 수행 할 때이 매개 변수를 사용해야합니다. 이 시점에서 우리는 커스텀 인터셉트 어노테이션의 구현을 확장 할 수 있습니다. 사용자 정의 인터셉트 어노테이션은 @InterceptMark 마크를 사용해야하며 어노테이션에는 include (), exclude (), handler () 속성 정보가 포함되어야합니다. 사용되는 단계는 주로 3 단계로 나뉩니다.

사용자 정의 차단 주석은
BasePathMatchInterceptor를 상속하여 차단 프로세서
인터페이스 를 작성 하고 사용자 정의 차단 주석을 사용합니다.
예를 들어 http 요청을 정상적으로 시작하려면 요청 헤더에 accessKeyId 및 accessKeySecret 서명 정보를 동적으로 추가해야합니다. 이때 서명 인터셉터 주석을 사용자 정의 할 수 있습니다. @ 달성하려면 서명하십시오. 다음은 사용자 정의 @Sign 인터 셉션 어노테이션의 예입니다.

사용자 정의 @Sign 주석

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@InterceptMark
public @interface Sign {
    
    
    /**
     * 密钥key
     * 支持占位符形式配置。
     *
     * @return
     */
    String accessKeyId();

    /**
     * 密钥
     * 支持占位符形式配置。
     *
     * @return
     */
    String accessKeySecret();

    /**
     * 拦截器匹配路径
     *
     * @return
     */
    String[] include() default {
    
    "/**"};

    /**
     * 拦截器排除匹配,排除指定路径拦截
     *
     * @return
     */
    String[] exclude() default {
    
    };

    /**
     * 处理该注解的拦截器类
     * 优先从spring容器获取对应的Bean,如果获取不到,则使用反射创建一个!
     *
     * @return
     */
    Class<? extends BasePathMatchInterceptor> handler() default SignInterceptor.class;
}

사용자 정의 차단 주석을 확장 할 때 다음 두 가지 사항에주의해야합니다.

사용자 정의 인터셉트 어노테이션은 @InterceptMark로 표시되어야합니다.
주석에는 include (), exclude (), handler () 속성 정보가 포함되어야합니다.
SignInterceptor 구현

@Component
public class SignInterceptor extends BasePathMatchInterceptor {
    
    

    private String accessKeyId;

    private String accessKeySecret;

    public void setAccessKeyId(String accessKeyId) {
    
    
        this.accessKeyId = accessKeyId;
    }

    public void setAccessKeySecret(String accessKeySecret) {
    
    
        this.accessKeySecret = accessKeySecret;
    }

    @Override
    public Response doIntercept(Chain chain) throws IOException {
    
    
        Request request = chain.request();
        Request newReq = request.newBuilder()
                .addHeader("accessKeyId", accessKeyId)
                .addHeader("accessKeySecret", accessKeySecret)
                .build();
        return chain.proceed(newReq);
    }
}

위의 accessKeyId 및 accessKeySecret 필드 값은 @Sign으로 주석이 달린 accessKeyId () 및 accessKeySecret () 값에 따라 자동으로 삽입됩니다. @Sign이 자리 표시 자 형식의 문자열을 지정하는 경우 구성 속성 값은 다음과 같습니다. 주입에 사용됩니다. 또한 accessKeyId 및 accessKeySecret 필드는 setter 메소드를 제공해야합니다.

인터페이스에서 @Sign 사용

@RetrofitClient(baseUrl = "${test.baseUrl}")
@Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", exclude = {
    
    "/api/test/person"})
public interface HttpApi {
    
    

    @GET("person")
    Result<Person> getPerson(@Query("id") Long id);

    @POST("savePerson")
    Result<Person> savePerson(@Body Person person);
}

이러한 방식으로 서명 정보가 지정된 URL의 요청에 자동으로 추가 될 수 있습니다.

연결 풀 관리

기본적으로 Retrofit을 통해 전송 된 모든 http 요청은 max-idle-connections = 5 keep-alive-second = 300의 기본 연결 풀을 사용합니다. 물론 구성 파일에서 여러 사용자 지정 연결 풀을 구성한 다음 @RetrofitClient의 poolName 속성을 통해 사용을 지정할 수도 있습니다. 예를 들어 특정 인터페이스의 모든 요청이 poolName = test1 인 연결 풀을 사용하도록하려면 코드 구현은 다음과 같습니다.

1. 연결 풀을 구성합니다.

retrofit:
   # 连接池配置
   pool:
       test1:
       max-idle-connections: 3
       keep-alive-second: 100
       test2:
       max-idle-connections: 5
       keep-alive-second: 50

2. @RetrofitClient의 poolName 속성을 통해 사용할 연결 풀을 지정합니다.

@RetrofitClient(baseUrl = "${test.baseUrl}", poolName="test1")
public interface HttpApi {
    
    

   @GET("person")
   Result<Person> getPerson(@Query("id") Long id);
}

로그 인쇄

대부분의 경우 http 요청 로그를 기록하려고합니다. @RetrofitClient의 logLevel 및 logStrategy 속성을 통해 각 인터페이스의 로그 인쇄 수준 및 로그 인쇄 전략을 지정할 수 있습니다. retrofit-spring-boot-starter는 5 개의 로그 인쇄 수준 (ERROR, WARN, INFO, DEBUG, TRACE), 기본 정보를 지원합니다 .4 개의 로그 인쇄 전략 (NONE, BASIC, HEADERS, BODY), 기본 BASIC을 지원합니다. 4 가지 로그 인쇄 전략의 의미는 다음과 같습니다.

NONE : 로그 없음
BASIC : 요청 및 응답 라인을 기록합니다.
HEADERS : 요청 및 응답 라인과 해당 헤더를 기록합니다.
BODY : 요청 및 응답 라인과 해당 헤더 및 본문 (있는 경우)을 기록합니다.
retrofit-spring-boot-starter 기본적으로 DefaultLoggingInterceptor는 실제 로그 인쇄 기능을 수행하는 데 사용되며 맨 아래 계층은 okhttp의 기본 HttpLoggingInterceptor입니다. 물론 자체 로그 인쇄 인터셉터를 사용자 정의 할 수도 있습니다. BaseLoggingInterceptor (자세한 내용은 DefaultLoggingInterceptor 구현 참조)를 상속 한 다음 구성 파일에서 구성하기 만하면됩니다.

retrofit:
  # 日志打印拦截器
  logging-interceptor: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor

HTTP 예외 정보 포맷터

HTTP 요청 예외가 발생하면 원래 예외 정보를 읽기가 쉽지 않을 수 있습니다. 따라서 retrofit-spring-boot-starter는 http 요청 매개 변수의 출력을 아름답게하기 위해 Http 예외 정보 포맷터를 제공합니다. DefaultHttpExceptionMessageFormatter는 기본적으로 사용됩니다. 요청 데이터 형식화. 이를 사용자 정의하고 BaseHttpExceptionMessageFormatter를 상속 한 다음 구성 할 수도 있습니다.

retrofit:
  # Http异常信息格式化器
  http-exception-message-formatter: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultHttpExceptionMessageFormatter

통화 어댑터 CallAdapter

Retrofit은 어댑터 CallAdapterFactory를 호출하여 Call 개체를 인터페이스 메서드의 반환 값 유형에 적용 할 수 있습니다. Retrofit-spring-boot-starter는 두 개의 CallAdapterFactory 구현을 확장합니다.

BodyCallAdapterFactory

기본적으로 활성화되어 있으며 retrofit.enable-body-call-adapter = false를 구성하여 비활성화
하여 http 요청을 동 기적 으로 실행하고 응답 본문 콘텐츠를 인터페이스 메서드의 반환 값 유형 인스턴스에 맞게 조정할 수 있습니다.
Retrofit.Call, Retrofit.Response, java.util.concurrent.CompletableFuture를 제외하고 다른 반환 유형에서이 어댑터를 사용할 수 있습니다.
ResponseCallAdapterFactory

기본적으로 활성화되어 있으며
, http 요청을 동기식 으로 실행 하도록 retrofit.enable-response-call-adapter = false를 구성하여 비활성화 할 수 있으며 , 응답 본문 내용을 Retrofit.Response로 조정하여 반환 할 수 있습니다.
메서드의 반환 값 유형이 Retrofit.Response 인 경우이 어댑터를 사용할 수 있습니다.
Retrofit은 해당 CallAdapterFactory를 자동으로 선택하여 메서드 반환 값 유형에 따라 적응 처리를 수행합니다! Retrofit의 기본 CallAdapterFactory 외에도 다양한 유형의 메서드 반환 값을 지원할 수 있습니다.

Call : 적응 처리가 수행되지 않고 Call 객체가 직접 반환됩니다.
CompletableFuture : 응답 본문 내용이 CompletableFuture 객체에 적응됩니다. Return
Void : 반환 유형에 관계없이 Void를 사용할 수 있습니다. http 상태 코드가 2xx가 아니면 그냥 오류를 던지십시오!
응답 : 응답 내용을 응답 객체에
적용하고 다른 Java 유형을 반환 합니다. 응답 본문 내용을 해당 Java 유형 객체에 적용하고 반환합니다. http 상태 코드가 2xx가 아니면 오류를 발생시킵니다!

 /**
     * Call<T>
     * 不执行适配处理,直接返回Call<T>对象
     * @param id
     * @return
     */
    @GET("person")
    Call<Result<Person>> getPersonCall(@Query("id") Long id);

    /**
     *  CompletableFuture<T>
     *  将响应体内容适配成CompletableFuture<T>对象返回
     * @param id
     * @return
     */
    @GET("person")
    CompletableFuture<Result<Person>> getPersonCompletableFuture(@Query("id") Long id);

    /**
     * Void
     * 不关注返回类型可以使用Void。如果http状态码不是2xx,直接抛错!
     * @param id
     * @return
     */
    @GET("person")
    Void getPersonVoid(@Query("id") Long id);

    /**
     *  Response<T>
     *  将响应内容适配成Response<T>对象返回
     * @param id
     * @return
     */
    @GET("person")
    Response<Result<Person>> getPersonResponse(@Query("id") Long id);

    /**
     * 其他任意Java类型
     * 将响应体内容适配成一个对应的Java类型对象返回,如果http状态码不是2xx,直接抛错!
     * @param id
     * @return
     */
    @GET("person")
    Result<Person> getPerson(@Query("id") Long id);

CallAdapter.Factory를 확장하여 자체 CallAdapter를 구현 한 다음 사용자 정의 CallAdapterFactory를 스프링 빈으로 구성 할 수도 있습니다!

사용자 정의 구성이있는 CallAdapter.Factory가 더 높은 우선 순위를 갖습니다!

데이터 트랜스 코더 변환기

Retrofi는 Converter를 사용하여 @Body 주석이 달린 객체를 요청 본문으로, 응답 본문 데이터를 Java 객체로 변환합니다. 다음 변환기를 사용할 수 있습니다.

Gson : com.squareup.Retrofit : converter-gson
Jackson : com.squareup.Retrofit : converter-jackson
Moshi : com.squareup.Retrofit : converter-
moshi Protobuf : com.squareup.Retrofit : converter-protobuf
와이어 : com.squareup. Retrofit : converter-wire
간단한 XML : com.squareup.Retrofit : converter-simplexml
retrofit-spring-boot-starter는 기본적으로 직렬화 변환에 jackson을 사용합니다! 다른 직렬화 방법을 사용해야하는 경우 프로젝트에 해당 종속성을 도입 한 다음 해당 ConverterFactory를 스프링 빈으로 구성하십시오.

Converter.Factory를 확장하여 자체 Converter를 구현할 수도 있습니다. 그런 다음 사용자 정의 Converter.Factory를 스프링 빈으로 구성 할 수도 있습니다!

사용자 정의 구성 Converter.Factory가 더 높은 우선 순위를 갖습니다!

BaseGlobalInterceptor

전체 시스템의 http 요청에 대해 통합 인터 셉션 처리를 수행해야하는 경우 글로벌 인터셉터 BaseGlobalInterceptor의 구현을 사용자 정의하고 봄에 Bean으로 구성 할 수 있습니다! 예를 들어 전체 시스템에서 시작된 모든 http 요청에 대한 소스 정보를 가져와야합니다.

@Component
public class SourceInterceptor extends BaseGlobalInterceptor {
    
    
    @Override
    public Response doIntercept(Chain chain) throws IOException {
    
    
        Request request = chain.request();
        Request newReq = request.newBuilder()
                .addHeader("source", "test")
                .build();
        return chain.proceed(newReq);
    }
}

추천

출처blog.csdn.net/ncw8080/article/details/114007662