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-->
来源:oschina
链接:https://my.oschina.net/itazi/blog/4720499