retrofit + rxjava 获取网络数据(以获取帆软token作为例子)

柔情痞子 提交于 2020-11-17 03:25:11

retrofit + rxjava 获取网络数据(以获取帆软token作为例子)

技术介绍

本文使用retrofit + rxjava 通过相关url获取数据并处理,语言使用的是kotlin,构建工具使用maven。以帆软接口作为例子,帆软接口返回的其实是jsonp的格式,后端获取时类型为String

过程介绍

1. 创建服务的接口api对象

interface FineReportApi {

    @GET
    fun getFineReportData(@Url url: String, @Nullable @QueryMap map: HashMap<String, String>): Observable<String>

}

其中@GET表示请求接口方式为get,@Url为请求路径的相对url(注意,这里是相对,因为基础地址我们会在另外一个地方配置。),@QueryMap为查询参数,此处我们可以以一个HashMap形式直接传递。

2. retrofit 具体请求过程

// 此处为log日志拦截器,可以显示具体的请求日志信息
private val logInterceptor = HttpLoggingInterceptor().apply {
        this.level = HttpLoggingInterceptor.Level.BODY
    }
    
 private val client = OkHttpClient.Builder()
            .addInterceptor(logInterceptor)
            .callTimeout(1, TimeUnit.MINUTES)
            .connectTimeout(1, TimeUnit.MINUTES)
            .readTimeout(1, TimeUnit.MINUTES)
            .writeTimeout(1, TimeUnit.MINUTES)
            .build()
            
            
private fun buildApi(baseUrl: String): FineReportApi {

        return Retrofit.Builder()
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(ScalarsConverterFactory.create())
                 //此处需要以‘/’结尾
                .baseUrl(baseUrl)
                .client(client)
                .build()
                .create(FineReportApi::class.java)
    }

注意上面创建FineReportApi对象时addCallAdapterFactory方法添加的是RxJavaCallAdapterFactory,因为适配器用的是rxjava,而addConverterFactory用的是ScalarsConverterFactory因为我们在FineReportApi接口中返回的是Observable<String>,此处实际转换的对象是String,不是传统的json,这和接口的返回值有关。而ScalarsConverterFactory类中实际起作用代码如下:

if (type == String.class) {
      return StringResponseBodyConverter.INSTANCE;
    }
/**
     * 获取帆软token
     * @param apiInfo ApiInfo
     * @return String?
     */
    fun getFineReportToken(apiInfo: ApiInfo): String? {


        if (StringUtils.isEmpty(apiInfo.baseUrl)) {
            throw IllegalStateException("base url 信息不能为空!")
        }

        if (StringUtils.isEmpty(apiInfo.credUrl)) {
            throw IllegalStateException("cred url 信息不能为空!")
        }


        // 此处的map参数为帆软接口的固定参数
        val paramMap = hashMapOf<String, String>()
        paramMap["fine_username"] = apiInfo.userName
        paramMap["fine_password"] = apiInfo.password
        paramMap["validity"] = "-2"

        val apiObs: Observable<String> =
                api(apiInfo.baseUrl).getFineReportData(apiInfo.credUrl, paramMap)


        var token: String? = null

        apiObs.observeOn(Schedulers.immediate())
                .subscribe ({
                    val result = it

                    val gson = Gson()
                    // 截取返回的字符串并转成HashMap对象
                    val json = JsonParser().parse(result.substring(result.indexOf("{"),
                            result.lastIndexOf(")"))).asJsonObject

                    val map = gson.fromJson(json, HashMap::class.java)

                    // 对于这个接口,如果有值的话肯定在accessToken里面
                    if (null == map["accessToken"]) {
                        throw IllegalStateException("无法获取token!")
                    }

                    token = map["accessToken"] as String
                },{
                    mLogger.error(it.message)
                    throw Exceptions.propagate(it)
                }, {
                    mLogger.info("获取token完成,【$token】")
                })


        return token

    }

其中ApiInfo类如下:

@JsonIgnoreProperties(ignoreUnknown = true)
public class ApiInfo {
    private String baseUrl;
    private String relaUrl;
    private HashMap<String, String> params;
    private String method;
    private String cred;
    private String credUrl;
    private String userName;
    private String password;
    private String token;
// 省略 get 和 set 方法
}

请求参数如下:

{"baseUrl":"http://ip:port/webreport/decision/","relaUrl":"v10/entries/all","params":{},"method":"GET","credUrl":"login/cross/domain","userName":"yourName","password":"yourPassword"}

其中baseUrl为基础地址,credUrl为要获取token的相对地址,relaUrl是我要采集实际数据的相对地址,但是只有获取token之后才可以访问该接口。

以上,我可以就可以获取帆软获取token接口数据了,将获取的字符串截取并获取实际的token值。

值得一提的是其实这些代码也是在我之前同事写的类似代码的基础上迭代的。

依赖版本

<properties>
    <kotlin.version>1.4.10</kotlin.version>
</properties>

<!--Retrofit2 related start-->
        <dependency>
            <groupId>com.squareup.retrofit2</groupId>
            <artifactId>retrofit</artifactId>
            <version>2.5.0</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.retrofit2</groupId>
            <artifactId>adapter-rxjava</artifactId>
            <version>2.5.0</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.retrofit2</groupId>
            <artifactId>converter-gson</artifactId>
            <version>2.5.0</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.retrofit2</groupId>
            <artifactId>converter-jackson</artifactId>
            <version>2.5.0</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>logging-interceptor</artifactId>
            <version>3.12.0</version>
        </dependency>

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.12.0</version>
        </dependency>

        <dependency>
            <groupId>com.squareup.retrofit2</groupId>
            <artifactId>converter-scalars</artifactId>
            <version>2.2.0</version>
        </dependency>
        <!--Retrofit2 related end-->


        <!--kotlin support-->
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-allopen</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test-junit</artifactId>
            <version>${kotlin.version}</version>
        </dependency>

        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test</artifactId>
            <version>${kotlin.version}</version>
            <scope>test</scope>
        </dependency>
        <!-- kotlin end-->
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!