retrofit

项目中导入Maven

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.lianjiatech</groupId>
            <artifactId>retrofit-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>
启动8080的项目,接口如下

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
	List<User> list = new ArrayList<>();
	@GetMapping
	public List<User> getUser() {

		list.add(new User(1, "张三"));
		list.add(new User(2, "李四"));
		return list;
	}

	@GetMapping("/{id}")
	public User getUserById(@PathVariable Integer id) {
		return new User(id, "法外狂徒张三");
	}

	@PostMapping
	public Boolean add(@RequestBody User user) {
		return list.add(user);
	}

	@PutMapping("/{id}")
	public Boolean update(@RequestBody User user, @PathVariable Integer id) {
		list.forEach(x ->{
			if(x.getId().equals(id)){
				x.setUsername(user.getUsername());
			}
		});
		return true;
	}

	@DeleteMapping("/{id}")
	public Boolean delete(@PathVariable Integer id) {
		return list.remove(id);

	}
启动8081的项目,接口如下

@RestController
public class TestController {
	@Resource
	private UserApi userApi;

	@GetMapping("/list")
	public Object getList() {
		return userApi.getUser();
	}

	@GetMapping("/{id}")
	public Object getUserById(@PathVariable Integer id) {
		return userApi.getUserById(id);
	}

	@PostMapping("/add")
	public Object add(@RequestParam("username") String username,@RequestParam("id") Integer id){
	return userApi.addUser(new User(id, username));
	}

	@PutMapping("/update")
	public Object update(@RequestParam Integer id){
		return userApi.updateUser(new User(4, "lisi"),id);
	}

	@DeleteMapping("/delete")
	public Object delete(@RequestParam Integer id){
		return userApi.deleteUserById(id);
	}

8081的项目中创建接口


@RetrofitClient(baseUrl = "http://localhost:8080/") //其他服务的请求地址
public interface UserApi {

	@GET("user")  // 与@GetMapping("/user") 请求路径对应
	List<User> getUser(); 

	@GET("user/{id}") //与@GetMapping("/user/{id}") 请求路径对应
	User getUserById(@Path("id")Integer id);

	@POST("user") //与@PostMapping("/user") 请求路径对应
	Boolean addUser(@Body User user);

	@PUT("user/{id}") // 同理
	Boolean updateUser(@Body User user,@Path("id") Integer id);

	@DELETE("user/{id}") // 同理
	Boolean deleteUserById(@Path("id") Integer id);

}

测试在这里插入图片描述

Forest

Forest 是一个开源的 Java HTTP 客户端框架,用来访问第三方服务 RESTful 接口。
它能够将 HTTP 的请求参数绑定到 Java 接口上,之后调用 Java 接口就等于在发送 HTTP 请求。一切面向于接口。

  • 很多公司需要在 Java 后台调用许多第三方 HTTP 接口,比如微信支付、友盟等等第三方平台。

  • 公司内部还有很多服务是用世界最好语言写的,接口自然也只能通过 HTTP 接口来调用。于是日积月累下来,在 Java 代码中就有许许多多各式各样的 HTTP 调用接口,而且调用方式也不统一,有 HttpClient 写的、有 OkHttp 写的、有自己包装的,光公司内部不同人包装的 HTTP 工具类就有两三种。而且 url 基本写死在代码中,很难维护,不同接口又有不同的参数传输方式,有 GET 、有 POST,有 JSON 传输的、有 XML 传输的。当有一个接口需要修改,完了,光找到代码在什么地方就要花半天时间。而 Forest 能帮助我很好地将 HTTP 代码和业务代码解耦开来,请求调用者不必关心 HTTP 相关的细节。

  • 自动拼接 HTTP 的各种参数
    包括 URL、Header、Body 等等参数都能依靠 Java 注解来声明。这里就举一个高德地图的栗子,来看看 Forest 是如何优雅的声明 HTTP 请求接口的:

/**
 * 高德地图服务客户端接口
 */
@BaseRequest(baseURL = "http://ditu.amap.com")
public interface Amap {

/**
     * 根据经纬度获取详细地址
     * @param longitude 经度
     * @param latitude 纬度
     * @return 详细地址信息
     */
@Get("/service/regeo")
    Map getLocation(@Query("longitude") String longitude, @Query("latitude") String latitude);

}

......

Amap amap = Forest.client(Amap.class);
// 发送请求查询经纬度
Map locationInfo = amap.getLocation("32.1242832", "56.3290434");
  • 自动 JSON 和 XML 转换
    其实,我们处理 HTTP 的工作时,除了浪费在组装各种请求参数外,大部分时间都花了在序列化和反序列化各种格式的数据上,如 JSON 和 XML。

以前用 HttpClient,这些重复的机械性工作都要自己来搞,很是麻烦。
用 Forest 就方便多了,比如要 POST 一个 JSON 对象,直接挂个 @JSONBody 就好了,就是这么清爽。
// 直接将 MyUserInfo 转换成 JSON
// 将服务端响应返回的 JSON 数据转换成 Result 类对象

@Post("http://localhost:8080/user")
Result<Booelean> createUser(@JSONBody MyUserInfo user);

和 Retrofit 以及 Feign 的比较
之前也用过这两款开源框架,都很强大,但各有优缺点。

Retrofit 的主要的问题时和 OkHttp 绑的太死,有些功能被 OkHttp 限制住了,比如我想处理 Get 请求传输 Body 数据这种非标准的 HTTP 请求就很难办到,而 Forest 可以随意切换 OkHttp 和 HttpClient 作为后端,需要用哪个时用哪个。

Retrofit 注解的丰富性也不如 Forest,比如要实现 HTTP 网络代理就要自己去写代码,而 Forest 提供了 @HTTPProxy 注解,设置一下就完事了。

如果要扩展自定义注解都是基于 OkHttp 的拦截器,不是特别方便,而 Forest 拦截器要比 OkHttp 的方便很多,提供 onInvoke, beforeExecute, onSccuess, onError 等回调方法,等于把一个请求的生老病死都涵盖了。

而 Feign 的问题则是和 Spring 绑的太紧,很多功能需要依赖 Spring 去做,太加了 Spring 相关包又太重了。

Forest 的核心包基本涵盖了所有 HTTP 所需功能和注解,不依赖 Spring,要轻量许多,但又不失方便性。

想要了解更多请参考:https://gitee.com/dromara/forest

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐