Retrofit2x简介:
Retrofit2
是一个 RESTful 的 HTTP 网络请求框架的封装。注意这里并没有说它是网络请求框架,主要原因在于网络请求的工作并不是
Retrofit2
来完成的。
我们的应用程序通过
Retrofit2
请求网络,实际上是使用
Retrofit2
接口层封装请求参数、Header、Url 等信息,之后由
OkHttp
完成后续的请求操作,在服务端返回数据之后,
OkHttp
将原始的结果交给
Retrofit2
,后者根据用户的需求对结果进行解析的过程。
讲到这里,你就会发现所谓
Retrofit2
,其实就是
一个封装了 OkHttp
的框架了。
OkHttp简介
okHttp是一款
android网络框架,一个处理网络请求的开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献,用于替代HttpUrlConnection和Apache HttpClient,有关于它的使用,可以观看 OkHttp3博客教程:http://blog.csdn.net/lmj623565791/article/details/47911083
Spring整合Retrofit2x
第一步:新建maven工程,在pom.xml引入相关依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.2.5.RELEASE</spring.version>
<junit.version>4.12</junit.version>
<druid.version>1.1.0</druid.version>
<fastjson.version>1.2.8</fastjson.version>
<commons-lang3.version>3.3.2</commons-lang3.version>
<mybaitsplus.version>2.1-gamma</mybaitsplus.version>
<mysql.version>5.1.38</mysql.version>
<log4j.version>1.2.17</log4j.version>
<servlet-api.version>2.5</servlet-api.version>
<jsp-api.version>2.0</jsp-api.version>
<slf4j.version>1.7.19</slf4j.version>
<aspectjweaver.version>1.8.8</aspectjweaver.version>
<fileupload.version>1.3.1</fileupload.version>
<jstl.version>1.2</jstl.version>
</properties>
<dependencies>
<!-- retrofit2:OkHttp框架 -->
<dependency>
<groupId>com.github.msimw</groupId>
<artifactId>retrofit2-spring</artifactId>
<version>1.1</version>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp-api.version}</version>
<scope>provided</scope>
</dependency>
<!-- JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- apache工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- 整合测试包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
注意:引入retrofit2-spring依赖相当于引入:retrofit2-spring-1.1.jar +okhttp-3.8.0.jar + okio-1.13.0.jar + fastjson-1.2.38.jar 这四个jar包
第二步:配置spring相关配置文件applicationContent.xml
<!-- 引入属性文件 -->
<context:property-placeholder location="classpath:config.properties"/>
<!--http连接池配置-->
<bean id="connectionPool" class="okhttp3.ConnectionPool">
<constructor-arg index="0" value="100"/>
<constructor-arg index="1" value="100"/>
<constructor-arg index="2" value="MINUTES"/>
</bean>
<!--http扫包配置-->
<bean class="com.msimw.retrofit2x.spring.HttpApiScannerConfigurer">
<property name="connTimeOut" value="15"></property>
<property name="writeTimeOut" value="15"></property>
<property name="readTimeOut" value="15"></property>
<property name="connectionPool" ref="connectionPool"></property>
<!--与spring扫包配置一样-->
<property name="basePackage" value="自定义基础扫描包"></property>
</bean>
<!-- Service包(自动注入) -->
<context:component-scan base-package="自定义基础扫描包"/>
注意:如需搭建完整ssm项目,实现访问数据库等操作,还需手动加上mybatis及springMVC的相关配置文件,这里只演示Retrofit2,就不做详细配置了
第三步:创建一个API访问接口(无需编写实现类)
@HttpApi("http://localhost:8080/api/")
public interface ImApi {
@GET("{version}/items/")
public Call<ResponseContent> getItems(@Path("version") String version);
@GET("v1/items/")
public ResponseContent getNoCall();
}
注意:
0、@HttpApi注解的类必须在http扫描包下,注解中的value值为请求的BaseUrl
1、当getItems()方法的version参数值为"v1"时,它将和getNoCall()方法的请求路径一致,均为(http://localhost:8080/api/v1/items/).该请求路径的返回值类型为ResponseContent类型的json形式数据。
2、getItems()方法的返回值的类型为Call<ResponseContent>,其中Call<T>是Retrofit2给出的类,使用Call<T>封装返回数据可用对整个请求过程进行监控,而没有特殊需求的情况下,可用直接使用ResponseContent接收返回的数据(如:getNoCall()方法)
3、ResponseContent类的代码如下
public class ResponseContent {
private Object data;
private Meta meta;
private Pagination pagination;
public void setMeta(Meta meta) {
this.meta = meta;
}
public Meta getMeta() {
return this.meta;
}
public void setData(Object data) {
this.data = data;
}
public Object getData() {
return this.data;
}
public Pagination getPagination() {
return pagination;
}
public void setPagination(Pagination pagination) {
this.pagination = pagination;
}
}
Meta类代码如下:
public class Meta {
/** 响应码 */
private int respCode;
/** 响应信息 */
private String respMsg;
/** 响应描述 */
private String detail;
/** 访问url */
private String url;
public int getRespCode() {
return respCode;
}
/** 响应码 */
public void setRespCode(int respCode) {
this.respCode = respCode;
}
public String getRespMsg() {
return respMsg;
}
/** 响应信息 */
public void setRespMsg(String respMsg) {
this.respMsg = respMsg;
}
public String getDetail() {
return detail;
}
/** 响应描述 */
public void setDetail(String detail) {
this.detail = detail;
}
public String getUrl() {
return url;
}
/** 访问url */
public void setUrl(String url) {
this.url = url;
}
}
Pagination类的代码如下:
public class Pagination {
/** 页码 */
private int page;
/** 每页记录数 */
private int size;
/** 总页数 */
private Integer totalPage;
/** 总记录数 */
private Long totalCode;
public Integer getTotalPage() {
return totalPage;
}
public void setTotalPage(Integer totalPage) {
this.totalPage = totalPage;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public Long getTotalCode() {
return totalCode;
}
public void setTotalCode(Long totalCode) {
this.totalCode = totalCode;
}
@Override
public String toString() {
return "Pagination [page=" + page + ", size=" + size + ", totalPage=" + totalPage + ", totalCode=" + totalCode
+ "]";
}
}
第四步创建service层
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.lmsq.shaxuntech.api.response.ResponseContent;
import com.msimw.retrofit2x.retrofit.Call;
import com.msimw.retrofit2x.retrofit.Response;
import com.test.demo.api.ImApi;
@Service
public class Retrofit2Service {
@Autowired
private ImApi imApi;
public ResponseContent getItems() throws IOException{
System.out.println("getItems()方法开始执行!");
Call<ResponseContent> items = imApi.getItems("v1");
// 执行请求
Response<ResponseContent> response = items.execute();
// 是否成功响应数据
System.out.println("success ? " + response.isSuccessful());
// 响应结果描述
System.out.println("msg ? " + response.message());
// 响应部分信息
System.out.println("msg ? " + Response.success(ResponseContent.class).toString());
// 响应body
ResponseContent content = response.body();
// 转换为string类型数据
String jsonString = JSON.toJSONString(content);
// 响应内容输出
System.out.println("response : " + response);
System.out.println("resp-str : " + jsonString);
System.out.println("getItems()方法执行完毕!");
// 返回结果
return content;
}
public ResponseContent getNoCall() throws IOException{
System.out.println("getNoCall()方法执行了!");
ResponseContent noCall = imApi.getNoCall();
String jsonString = JSON.toJSONString(noCall);
// 响应内容输出
System.out.println("resp-str : " + jsonString);
System.out.println("getNoCall()方法执行完毕!");
return noCall;
}
}
0、本service类必须创建在<context:component-scan />元素配置的基础扫描包下
1、为实现面向接口编程,可用考虑先创建service接口,再编写实现类,这里就不做演示了
第五步:整合JUnit4测试
编写测试类代码如下:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring/spring配置文件的名字.xml"})
public class Demo {
@Autowired
private Retrofit2Service service;
@Test
public void demp1() throws IOException{
System.out.println("准备执行/n");
service.getItems();
service.getNoCall();
System.out.println("执行完毕/n");
}
注意:这里使用的测试方式是spring-JUnit整合的方法,如果不会的可以手动百度了解。
第五步:整合测试准备工作
1、启动数据源项目:为了保证(在访问 : http://localhost:8080/api/v1/items/ 时能返回ResponseContent类型的数据) ,我使用SSM框架搭建了另一个maven项目,由于比较简单,这里就不做实现,如有认为有需要,可在评论区说明,我可以将SSM框架的搭建和大家说下
第六步,整合测试,查看控制台打印结果!
准备执行/n
getItems()方法开始执行!
success ? true
msg ? OK
msg ? Response{protocol=http/1.1, code=200, message=OK, url=http://localhost/}
response : Response{protocol=http/1.1, code=200, message=OK, url=http://localhost:8080/api/v1/items/}
resp-str : {"data":[{"createTime":"2017-09-18 11:48:40","itemMsg":"蓝皮果仁","featured":1,"transportCost":0,"itemId":"d1c328ae-522e-4db1-8650-f9a96969d971","url":"http://owxmrb4qi.bkt.clouddn.com/guoren-a.png","currPrice":10.00,"initPrice":12.00,"unit":"元","num":10,"name":"混合果仁A款","volume":2,"brand":"道远","temp":6},{"createTime":"2017-09-18 11:48:41","itemMsg":"绿皮果仁","featured":1,"transportCost":0,"itemId":"8ed338f1-8993-437a-938c-752103e79b87","url":"http://owxmrb4qi.bkt.clouddn.com/guoren-b.png","currPrice":11.00,"initPrice":12.00,"unit":"元","num":28,"name":"混合果仁B款","volume":3,"brand":"道远","temp":20},{"createTime":"2017-09-18 11:48:41","itemMsg":"香脆松子","featured":1,"transportCost":0,"itemId":"1f9f58f1-1328-43d4-a052-c2206c13a587","url":"http://owxmrb4qi.bkt.clouddn.com/happy-seeds.png","currPrice":12.00,"initPrice":12.00,"unit":"元","num":6,"name":"开心松子","volume":0,"brand":"道远","temp":3},{"createTime":"2017-09-19 16:06:54","itemMsg":"坚果美食","featured":1,"transportCost":0,"itemId":"423e91ed-ac4e-4627-be56-bf56610f35c2","url":"http://owxmrb4qi.bkt.clouddn.com/original-Cashew.png","currPrice":13.00,"initPrice":14.00,"unit":"元","num":10,"name":"原味腰果","volume":0,"brand":"道远","temp":6},{"createTime":"2017-09-21 15:11:18","itemMsg":"蔬菜混搭","featured":1,"transportCost":0,"itemId":"8623bb60-cb80-4692-8a89-8c043117d35e","url":"http://owxmrb4qi.bkt.clouddn.com/blendVegetable.png","currPrice":16.00,"initPrice":16.00,"unit":"元","num":11,"name":"综合蔬菜脆","volume":0,"brand":"道远","temp":8}],"meta":{"detail":"OK","respCode":0},"pagination":{"page":1,"size":5,"totalCode":5,"totalPage":1}}
getItems()方法执行完毕!
--------------------------
getNoCall()方法执行了!
resp-str : {"data":[{"createTime":"2017-09-18 11:48:40","itemMsg":"蓝皮果仁","featured":1,"transportCost":0,"itemId":"d1c328ae-522e-4db1-8650-f9a96969d971","url":"http://owxmrb4qi.bkt.clouddn.com/guoren-a.png","currPrice":10.00,"initPrice":12.00,"unit":"元","num":10,"name":"混合果仁A款","volume":2,"brand":"道远","temp":6},{"createTime":"2017-09-18 11:48:41","itemMsg":"绿皮果仁","featured":1,"transportCost":0,"itemId":"8ed338f1-8993-437a-938c-752103e79b87","url":"http://owxmrb4qi.bkt.clouddn.com/guoren-b.png","currPrice":11.00,"initPrice":12.00,"unit":"元","num":28,"name":"混合果仁B款","volume":3,"brand":"道远","temp":20},{"createTime":"2017-09-18 11:48:41","itemMsg":"香脆松子","featured":1,"transportCost":0,"itemId":"1f9f58f1-1328-43d4-a052-c2206c13a587","url":"http://owxmrb4qi.bkt.clouddn.com/happy-seeds.png","currPrice":12.00,"initPrice":12.00,"unit":"元","num":6,"name":"开心松子","volume":0,"brand":"道远","temp":3},{"createTime":"2017-09-19 16:06:54","itemMsg":"坚果美食","featured":1,"transportCost":0,"itemId":"423e91ed-ac4e-4627-be56-bf56610f35c2","url":"http://owxmrb4qi.bkt.clouddn.com/original-Cashew.png","currPrice":13.00,"initPrice":14.00,"unit":"元","num":10,"name":"原味腰果","volume":0,"brand":"道远","temp":6},{"createTime":"2017-09-21 15:11:18","itemMsg":"蔬菜混搭","featured":1,"transportCost":0,"itemId":"8623bb60-cb80-4692-8a89-8c043117d35e","url":"http://owxmrb4qi.bkt.clouddn.com/blendVegetable.png","currPrice":16.00,"initPrice":16.00,"unit":"元","num":11,"name":"综合蔬菜脆","volume":0,"brand":"道远","temp":8}],"meta":{"detail":"OK","respCode":0},"pagination":{"page":1,"size":5,"totalCode":5,"totalPage":1}}
getNoCall()方法执行完毕!
执行完毕/n