retrofit:一套RESTful架构的Android(Java)客户端实现。
好处:
- 基于注解
- 提供JSON to POJO,POJO to JSON,网络请求(POST,GET,PUT,DELETE等)封装
- 可以看做是对HttpClient的再次封装
1、为了做测试,建立了一个新的springboot项目"myboot2",项目结构如下:
1.1、pom.xml
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>com.xxx</groupId> 8 <artifactId>myboot2</artifactId> 9 <version>1.0-SNAPSHOT</version> 10 11 <properties> 12 <java.version>1.8</java.version><!-- 官方推荐 --> 13 </properties> 14 15 <parent> 16 <groupId>org.springframework.boot</groupId> 17 <artifactId>spring-boot-starter-parent</artifactId> 18 <version>1.2.5.RELEASE</version> 19 </parent> 20 21 <!-- 引入实际依赖 --> 22 <dependencies> 23 <dependency> 24 <groupId>org.springframework.boot</groupId> 25 <artifactId>spring-boot-starter-web</artifactId> 26 </dependency> 27 <!-- 使用swagger --> 28 <dependency> 29 <groupId>io.springfox</groupId> 30 <artifactId>springfox-swagger2</artifactId> 31 <version>2.2.2</version> 32 </dependency> 33 <dependency> 34 <groupId>io.springfox</groupId> 35 <artifactId>springfox-swagger-ui</artifactId> 36 <version>2.2.2</version> 37 </dependency> 38 </dependencies> 39 40 <build> 41 <plugins> 42 <plugin> 43 <groupId>org.springframework.boot</groupId> 44 <artifactId>spring-boot-maven-plugin</artifactId> 45 </plugin> 46 </plugins> 47 </build> 48 </project>
1.2、Application.java
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 package com.xxx.secondboot; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; 6 import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; 7 8 import springfox.documentation.swagger2.annotations.EnableSwagger2; 9 10 @SpringBootApplication 11 @EnableSwagger2 12 public class Application implements EmbeddedServletContainerCustomizer{ 13 14 public static void main(String[] args) { 15 SpringApplication.run(Application.class, args); 16 } 17 18 /** 19 * EmbeddedServletContainerCustomizer接口的未实现方法 20 * 指定容器的启动端口,之后再浏览器输入localhost:8081/swagger-ui.html即可 21 */ 22 public void customize(ConfigurableEmbeddedServletContainer container) { 23 container.setPort(8081); 24 } 25 26 }
说明:
- 实现了EmbeddedServletContainerCustomizer接口,并实现了其方法customize(ConfigurableEmbeddedServletContainer container),指定了该服务的启动端口是8081,这样在服务myboot(启动端口:8080)启动时,就不会存在端口冲突问题了.
1.3、Hotel.java
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 package com.xxx.secondboot.domain; 2 3 public class Hotel { 4 private int id; 5 private String hotelname; 6 7 public Hotel() { 8 } 9 10 public Hotel(int id, String hotelname) { 11 this.id = id; 12 this.hotelname = hotelname; 13 } 14 15 public int getId() { 16 return id; 17 } 18 19 public void setId(int id) { 20 this.id = id; 21 } 22 23 public String getHotelname() { 24 return hotelname; 25 } 26 27 public void setHotelname(String hotelname) { 28 this.hotelname = hotelname; 29 } 30 }
1.4、HotelController.java
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 package com.xxx.secondboot.web; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import org.springframework.web.bind.annotation.RequestBody; 7 import org.springframework.web.bind.annotation.RequestMapping; 8 import org.springframework.web.bind.annotation.RequestMethod; 9 import org.springframework.web.bind.annotation.RequestParam; 10 import org.springframework.web.bind.annotation.RestController; 11 12 import com.xxx.secondboot.domain.Hotel; 13 14 import io.swagger.annotations.Api; 15 import io.swagger.annotations.ApiOperation; 16 17 @RestController 18 @RequestMapping("/hotel") 19 @Api("HotelController相关api") 20 public class HotelController { 21 22 @ApiOperation("获取酒店Hotel信息:getHotelWithQueryParameter") 23 @RequestMapping(value="/getHotelWithQueryParameter",method=RequestMethod.GET) 24 public Hotel getHotelWithQueryParameter(@RequestParam("hotelname") String hotelname) { 25 if(hotelname.equals("nana")){ 26 return new Hotel(777, "假日酒店"); 27 } 28 return new Hotel(1314, "玫瑰酒店"); 29 } 30 31 @ApiOperation("获取酒店Hotel信息:getHotelList") 32 @RequestMapping(value="/getHotelList",method=RequestMethod.POST) 33 public List<Hotel> getHotelList() { 34 List<Hotel> hotelList = new ArrayList<>(); 35 hotelList.add(new Hotel(1314, "玫瑰酒店")); 36 hotelList.add(new Hotel(2046, "2046酒店")); 37 return hotelList; 38 } 39 40 @ApiOperation("获取酒店Hotel信息:getHotelListWithBody") 41 @RequestMapping(value="/getHotelListWithBody",method=RequestMethod.POST) 42 public List<Hotel> getHotelListWithBody(@RequestBody Hotel hotel) { 43 List<Hotel> hotelList = new ArrayList<>(); 44 if(hotel.getHotelname().equals("武林酒店")){ 45 hotelList.add(new Hotel(13141, "玫瑰酒店1")); 46 hotelList.add(new Hotel(20461, "2046酒店1")); 47 return hotelList; 48 } 49 hotelList.add(new Hotel(1314, "玫瑰酒店")); 50 hotelList.add(new Hotel(2046, "2046酒店")); 51 return hotelList; 52 } 53 }
说明:该类提供了三个方法,也是将来myboot服务远程调用的三个方法。
2、myboot项目基于上一节的结构继续编写
2.1、pom.xml
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 <!-- retrofit --> 2 <dependency> 3 <groupId>com.squareup.retrofit</groupId> 4 <artifactId>retrofit</artifactId> 5 <version>1.9.0</version> 6 </dependency>
说明:引入retrofit1.9.0依赖,与2.0的差别很大。
2.2、RestAdapterConfig.java
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 package com.xxx.firstboot.config; 2 3 import org.springframework.context.annotation.Bean; 4 import org.springframework.context.annotation.Configuration; 5 6 import retrofit.RestAdapter; 7 8 @Configuration 9 public class RestAdapterConfig { 10 11 /** 12 * 获取RestAdapter单例Bean 13 * @return 14 */ 15 @Bean 16 public RestAdapter getRestAdapter(){ 17 /** 18 * setEndpoint("http://localhost:8081"):指定基本的URL, 19 * API接口中的URL是相对于该URL的路径的, 20 * 不能少了协议名,例如写成:localhost:8081就不行 21 */ 22 RestAdapter adapter = new RestAdapter.Builder() 23 .setEndpoint("http://localhost:8081") 24 .build(); 25 return adapter; 26 } 27 28 }
说明:
- 使用 @Configuration+@Bean 构建RestAdapter单例。
- 在构建的过程中,一定要有setEndpoint("http://localhost:8081")方法,该方法指定了基本的URL(即:指定协议+IP+port)
2.3、HotelAPI.java
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 package com.xxx.firstboot.retrofit.api; 2 3 import java.util.List; 4 5 import com.xxx.firstboot.domain.Hotel; 6 7 import retrofit.http.Body; 8 import retrofit.http.GET; 9 import retrofit.http.POST; 10 import retrofit.http.Query; 11 12 public interface HotelAPI { 13 14 /** 15 * GET请求带查询参数 16 */ 17 @GET("/hotel/getHotelWithQueryParameter") 18 public Hotel getHotelWithQueryParameter(@Query("hotelname") String hotelname); 19 20 /** 21 * POST请求 22 */ 23 @POST("/hotel/getHotelList") 24 public List<Hotel> getHotelList(); 25 26 /** 27 * POST请求,带参数JavaBean 28 */ 29 @POST("/hotel/getHotelListWithBody") 30 public List<Hotel> getHotelListWithBody(@Body Hotel hotel); 31 32 }
说明:
- 该接口指定了调用远程服务的方法的基本路径与参数以及返回值等
- 路径都是相对路径,相对于setEndpoint("http://localhost:8081")指定的路径
- 方式有@GET/@POST/@PUT/@DELETE等
- 传递参数在get方式中可以直接将参数连到URL上去
- 传递参数使用@Query(服务被调用方使用@RequestParam接收),路径中的传递参数使用@Path(Restful风格),还可以直接传递一个对象@Body(服务被调用方使用@RequestBody接收),参数在请求头中@Header(服务被调用方使用@RequestHeader接收)
- 依旧要建一个Hotel类,最好与myboot2中的相同,不同也没关系
2.4、HotelAPIConfig.java
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 package com.xxx.firstboot.config; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.context.annotation.Bean; 5 import org.springframework.context.annotation.Configuration; 6 7 import com.xxx.firstboot.retrofit.api.HotelAPI; 8 9 import retrofit.RestAdapter; 10 11 @Configuration 12 public class HotelAPIConfig { 13 @Autowired 14 private RestAdapter adapter; 15 16 @Bean 17 public HotelAPI getHotelAPI(){ 18 return adapter.create(HotelAPI.class); 19 } 20 }
说明:
- 使用 @Configuration+@Bean 构建HotelAPI单例。
- HotelAPI接口实例是由RestAdapter来构建的,所以需要注入了RestAdapter
经过以上步骤后,之后就可以直接在其他类中注入HotelAPI实例来像普通的bean进行操作了。
2.5、UserService.java
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 @Autowired 2 private HotelAPI hotelApi; 3 4 public Hotel getHotelFromMyboot2WithQueryParameter(String hotelname){ 5 return hotelApi.getHotelWithQueryParameter(hotelname); 6 } 7 8 public List<Hotel> getHotelFromMyboot2List(){ 9 return hotelApi.getHotelList();//测试post请求 10 } 11 12 public List<Hotel> getHotelFromMyboot2ListWithBody(Hotel hotel){ 13 return hotelApi.getHotelListWithBody(hotel);//测试post请求 14 }
说明:
- service中注入了HotelAPI实例,使用该实例调用接口方法
- 其实,retrofit的接口的注入和使用与mybatis的注解方式的mapper接口的使用相似
2.6、UserController.java
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 @Autowired 2 private UserService userService; 3 4 @ApiOperation("获取酒店信息,测试GETWithQueryParameter") 5 @RequestMapping(value="/getHotelWithQueryParameter",method=RequestMethod.GET) 6 public Hotel getHotel(@RequestParam("hotelname") String hotelname) { 7 return userService.getHotelFromMyboot2WithQueryParameter(hotelname); 8 } 9 10 @ApiOperation("获取酒店信息,测试POST") 11 @RequestMapping(value="/getHotelList",method=RequestMethod.GET) 12 public List<Hotel> getHotelList() { 13 return userService.getHotelFromMyboot2List(); 14 } 15 16 @ApiOperation("获取酒店信息,测试POST") 17 @RequestMapping(value="/getHotelListWithBody",method=RequestMethod.GET) 18 public List<Hotel> getHotelListWithBody() { 19 return userService.getHotelFromMyboot2ListWithBody(new Hotel(888, "武林酒店")); 20 }
测试:
首先,启动服务myboot2,浏览器输入"localhost:8081/swagger-ui.html"可以查看服务是否启动成功。
其次,启动服务myboot,浏览器输入"localhost:8080/swagger-ui.html",再进行相应接口的测试即可。