Retrofit框架集成教程


现如今 Spring Boot 已然成为 Java 开发的不二之选,随着越来越多的项目选择 Spring Boot 框架,如何简单高效的实现不同项目间的通信便尤为关键。

Retrofit 则孕育而生,其核心即为通过 HTTP 网络请求,在此基础之上进行二次封装达到更易上手的目的。

下面介绍如何在 Spring Boot 项目中集成 Retrofit 从而实现网络通讯。

一、工程结构

新建一个工程并在其下创建两个 Spring Boot 项目,其中 retrofit-server 作为服务端用于向外提供接口,retrofit-client 用于模拟客户端请求服务端,项目结构如图:

二、 服务端

1. 接口定义

服务端 retrofit-server 比较简单,通过 @RestController 创建了几个测试接口用于模拟服务,这里仅截取部分控制层接口代码。

@RestController
@RequestMapping("api/server")
public class ServerController {

    @GetMapping("demo1")
    public String demo1() {
        return "You request demo1.";
    }

    @GetMapping("demo2")
    public String demo2(@RequestParam("msg") String msg) {
        return "You request demo2, params is: " + msg;
    }

    @PostMapping("demo3")
    public User demo3(@RequestBody User user) {
        return "You request demo3, params is: " + user.toString();
    }
}

三、客户端

完成服务端的接口服务创建之后新建客户端 retrofit-client 用于模拟服务请求。

1. 依赖导入

在客户端 retrofit-client 中引入 Retrofit 依赖,配置信息如下:

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

2. 配置示例

新建接口类 ClientApi ,并在类上添加 @RetrofitClient 注解标识请求地址。

其中 baseUrl 即为 retrofit-server 中的请求前缀,其允许通过 ${} 方式读取 yml 文件参数。同时也可根据业务场景设置连接超时时间等参数,这里不作详细介绍。

@RetrofitClient(baseUrl = "${address.url}/api/server", readTimeoutMs = 5 * 60 * 1000)
public interface ClientApi {

    @GET("demo1")
    Response<String> test1();

    /**
      * @GET => @GetMapping
      * @Query => @RequestParam
      */
    @GET("demo2")
    Response<String> test2(@Query("msg") String msg);

    /**
      * @POST => @PostMapping
      * @Body => @RequestBody
      */
    @POST("demo3")
    Response<User> test3(@Body User user);
}

3. 注解说明

在上面的例子中可以看到 retrofit 根据不同的接口请求方式定义了系列注解,其与 Spring Boot 中的注解对应关系参考下表。

注解 描述
@GET 作用于方法,对应接口注解中的 @GetMapping。
@POST 作用于方法,对应接口注解中的 @PostMapping。
@Query 作用于方法参数,对应接口注解中的 @RequestParam。
@Body 作用于方法参数,对应接口注解中的 @RequestBody。
@Url 作用于方法参数,用于动态指定服务地址,覆盖 baseUrl 值。

4. 动态服务

在第二点的例子中我们是将请求接口前缀配置在 baseUrl 中同时配置 @GET(value) 等注解使用。在 Retrofit 提供另一种请求方式,通过 @Url 参数注解覆盖 baseUrl 中值。

需要注意使用 @URL@GET 等注解不能带参,此时方法上的 @GET 等参数仅用于指定请求类型。

@RetrofitClient(baseUrl = "${address.url}/api/server", readTimeoutMs = 5 * 60 * 1000)
public interface ClientApi {

    @GET
    Response<String> test4(@Url String url, 
                           @Query("msg") String msg);

}

5. 拦截器

Retrofit 同时提供拦截器功能,如常见的服务请求提前认证拼接,通过继承 BasePathMatchInterceptor 类并重写 doIntercept() 方法即可,其在发送请求之前将会触发。

如下示例中在 Retrofit 发送的请求头新增了当前时间戳。

import com.github.lianjiatech.retrofit.spring.boot.interceptor.BasePathMatchInterceptor;

public class TimestampInterceptor extends BasePathMatchInterceptor {

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

拦截器的使用也十分简单,通过 @Intercept 注解作用于对应的服务类接口,注解包含三个参数,其描述参考下表。

参数 描述
handler 用于指定使用的拦截器类。
include 用于指定拦截器作用范围。
exclude 用于配置拦截器接口白名单。
import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient;
import com.github.lianjiatech.retrofit.spring.boot.interceptor.Intercept;

@RetrofitClient(baseUrl = "${address.url}/api/server", readTimeoutMs = 5 * 60 * 1000)
@Intercept(handler = TestInterceptor.class, include = {"/api/**"}, exclude = "/api/test/")
public interface ClientApi {

}

四、项目配置

1. 启动配置

在工程启动类添加 @RetrofitScan 注解,参数为 Retrofit 接口类所在包路径。

@SpringBootApplication
@RetrofitScan("xyz.ibudai.retrofit")
public class RestfulClientApplication {

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

}

2. 文件配置

在工程 yml 文件添加如下配置,非必须,未配置不影响正常使用。

retrofit:
  # 日志打印拦截器
  logging-interceptor: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor
  # Http异常信息格式化器
  http-exception-message-formatter: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultHttpExceptionMessageFormatter
  # 全局转换器工厂
  global-converter-factories:
    - com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory
    - retrofit2.converter.jackson.JacksonConverterFactory
  # 全局调用适配器工厂
  global-call-adapter-factories:
    - com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory
    - com.github.lianjiatech.retrofit.spring.boot.core.ResponseCallAdapterFactory

3. 服务测试

至此已经完成 Retrofit 的基本配置,在 retrofit-client 模块中新建测试类 ClientController 并通过 @Autowired 注解注入定义的 ClientApi 进行接口调用。

完成配置后启动项目,请求下述中的接口即可通过客户端实现服务端 retrofit-server 的服务访问。

@RestController
@RequestMapping("/api/client")
public class ClientController {

    @Autowired
    private ClientApi clientApi;

    @GetMapping("demo1")
    public String demo1() {
        String data = clientApi.test1().body();
        return data;
    }

    @GetMapping("demo2")
    public String demo2() {
        String msg = "123";
        String data = clientApi.test2(msg).body();
        return data;
    }

    @PostMapping("demo3")
    public String demo3() {
        User user = new User("123", "Alex", "123456");
        User data = clientApi.test3(user).body();
        return data.toString();
    }

    @GetMapping("demo4")
    public String demo4() {
        String url = "http://127.0.0.1:9091/api/server/demo1";
        return clientApi.test4(url).body();
    }
}

文章作者: 烽火戏诸诸诸侯
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 烽火戏诸诸诸侯 !
  目录