RPC之HttpClient与OkHttp3的实现

RPC之HttpClient与OkHttp3的实现

概念

在进行HttpClient和OkHttp的学习之前,我们得先了解下RPC这个概念。所谓的RPC,英文全称为Remote Procedure Call,翻译成中文的意思是远程过程调用,它是一种通过网络从远程计算机程序上请求服务获取数据的一种协议。说的更直白点就是要实现不同服务器之间的服务调用。而随着分布式系统的普及,RPC在现在的系统开发中起着非常重用的作用。

此次我们将要学习的HttpClient和OkHttp都可以实现RPC远程服务调用。HttpClient是Apache Jakarta Common 下的子项目。它是一种基于HTTP协议的客户端编程工具包,而OkHttp是一种适用于Android和Java应用程序的HTTP客户端。从概念上来看,两者都是基于HTTP协议的客户端程序,也都能实现远程服务请求的调用,所以接下来,我们通过案例对HttpClient与OkHttp3做一个详细的学习。

服务端

需求分析

在正式学习HttpClient和OkHttp之前,我们需要先搭建服务器对外提供服务,业务非常简单:

1.实现用户列表的查询

2.实现根据用户ID查询用户详情信息

3.实现用户的新增

为了方便环境的构建,此次我采用SprongBoot对项目进行构建,当然你也可以选中你自己比较熟悉的技术来搭建环境,完成上述需求的开发工作。那接下来我们就把整个环境搭建的步骤来实现下。

环境搭建

1.创建springboot项目

2.pom.xml导入对应的依赖jar包

 <parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>2.0.1.RELEASE</version>
 </parent>
 <dependencies>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
 ​
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-devtools</artifactId>
     </dependency>
 </dependencies>

3.编写引导类

 @SpringBootApplication
 public class ServerApplication {
     public static void main(String[] args) {
         SpringApplication.run(ServerApplication.class,args);
     }
 }

4.编写模型类

 public class User {
     private Integer id;
     private String name;
     private String password;
     //构造函数和setter、getter方法略
 }

5.编写Controller类

 @RestController
 @RequestMapping("/user")
 public class UserController {
 ​
     @Autowired
     private UserService userService;
     /**
      * 查询所有用户
      * @return
      */
     @GetMapping("/findAll")
     public List<User> findAll(){
 ​
         return userService.findAll();
     }
 ​
     @GetMapping("/findUserById/{id}")
     public User findUserById(@PathVariable("id") Integer id){
 ​
         return userService.findUserById(id);
     }
 ​
     @PostMapping("/addUserByJson")
     public Map<String,Object> addUserByJson(@RequestBody User user){
         Map<String,Object> rst = new HashMap<String,Object>();
         try{
             userService.addUser(user);
             rst.put("success",true);
         }catch(Exception e){
             e.printStackTrace();
             rst.put("success",false);
             rst.put("message","添加用户失败");
         }
         return rst;
     }
 ​
     @PostMapping("/addUser")
     public Map<String,Object> addUser(User user){
         Map<String,Object> rst = new HashMap<String,Object>();
         try{
             userService.addUser(user);
             rst.put("success",true);
         }catch(Exception e){
             e.printStackTrace();
             rst.put("success",false);
             rst.put("message","添加用户失败");
         }
         return rst;
     }
 }

7.编写service接口类

 public interface UserService {
     /**
      * 查询用户列表
      * @return
      */
     public List<User> findAll();
     /**
      * 根据ID查询用户信息
      * @param id
      * @return
      */
     public User findUserById(Integer id);
     /**
      * 新增用户
      * @param user
      */
     public void addUser(User user);
 }

8.编写service实现类

 @Service
 public class UserServiceImpl implements UserService {
     private static final Map<Integer,User> MAP = new HashMap<Integer,User>();
     static{
         MAP.put(1,new User(1,"张三丰","zsf"));
         MAP.put(2,new User(2,"赵敏","zm"));
         MAP.put(3,new User(3,"周芷若","zzr"));
         MAP.put(4,new User(4,"小昭","xz"));
         MAP.put(5,new User(5,"张无忌","zwj"));
         MAP.put(6,new User(6,"金毛狮王","jmsw"));
         MAP.put(7,new User(7,"张翠山","zcs"));
         MAP.put(8,new User(8,"殷素素","yss"));
     }
     @Override
     public List<User> findAll() {
         List<User> users = new ArrayList<User>();
         for (Integer id : MAP.keySet()) {
             users.add(MAP.get(id));
         }
         return users;
     }
     @Override
     public User findUserById(Integer id) {
         User user = MAP.get(id);
         return user;
     }
     @Override
     public void addUser(User user) {
         System.out.println("新增用户成功,用户的信息为"+user.toString());
     }
 }

功能测试

可以借助于浏览器或者postMan等工具进行测试,此处不是我们研究的重点,所以该处需要自行测试通过即可。

经过测试我们可以获取一下URL地址

查询用户列表: GET http://loalhost:8080/user/findAll

根据用户ID查询用户详情: GET http://localhost:8080/user/findUserById/具体的ID值

新增用户: POST http://localhost:8080/user/addUserByJson 发送json数据

POST http://localhost:8080/user/addUser 发送form表单数据

客户端(HttpClient)

1.导入对应的jar包

 <dependencies>
     <dependency>
         <groupId>org.apache.httpcomponents</groupId>
         <artifactId>httpclient</artifactId>
         <version>4.5.5</version>
     </dependency>
     <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.9</version>
     </dependency>
     <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>fastjson</artifactId>
         <version>1.2.30</version>
     </dependency>
 </dependencies> 

2.通过HttpClient发送GET请求查询所有用户列表

 @Test
 public void testFindAll() throws Exception{
     //创建HttpClient对象
     HttpClient httpClient = HttpClients.createDefault();
     //创建GET请求对象
     HttpGet httpGet = new HttpGet("http://localhost:8080/user/findAll");
     //发送请求获取结果
     HttpResponse response = httpClient.execute(httpGet);
     //解析结果
     String rst = EntityUtils.toString(response.getEntity());
     System.out.println(rst);
 }

运行查询结果为:

3.通过HttpClient发送GET请求查询指定用户的详细信息

 @Test
 public void testFindById() throws Exception{
     //创建HttpClient对象
     HttpClient httpClient = HttpClients.createDefault();
     //创建GET请求对象
     HttpGet httpGet = new HttpGet("http://localhost:8080/user/findUserById/1");
     //发送请求获取结果
     HttpResponse response = httpClient.execute(httpGet);
     //解析结果
     String rst = EntityUtils.toString(response.getEntity());
     System.out.println(rst);
 }

运行查询结果为:

4.通过HttpClient发送POST请求完成用户的新增功能,发送数据类型为Form表单数据类型

@Test
public void testAddUserByForm() throws Exception{
    //创建HttpClient对象
    HttpClient httpClient = HttpClients.createDefault();
    //创建POST请求对象
    HttpPost httpPost = new HttpPost("http://localhost:8080/user/addUser");
    //封装发送数据
    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("name","唐僧"));
    params.add(new BasicNameValuePair("password","ts"));
    HttpEntity entity = new UrlEncodedFormEntity(params,"utf-8");
    httpPost.setEntity(entity);
    //发送请求获取结果
    HttpResponse response = httpClient.execute(httpPost);
    //解析结果
    String rst = EntityUtils.toString(response.getEntity());
    System.out.println(rst);
}

运行查询结果为:

服务端

客户端

5.通过HttpClient发送POST请求完成用户的新增功能,发送数据类型为JSON数据类型

@Test
public void testAddUserByJSON()throws Exception{
    //创建HttpClient对象
    HttpClient httpClient = HttpClients.createDefault();
    //创建POST请求对象
    HttpPost httpPost = new HttpPost("http://localhost:8080/user/addUserByJson");
    //封装发送数据
    Map<String,Object> paramMap = new HashMap<String,Object>();
    paramMap.put("name","孙悟空");
    paramMap.put("password","swk");
    String jsonString = JSONObject.toJSONString(paramMap);
    StringEntity entity = new StringEntity(jsonString,"utf-8");
    entity.setContentEncoding("UTF-8");
    entity.setContentType("application/json");
    httpPost.setEntity(entity);
    //发送请求获取结果
    HttpResponse response = httpClient.execute(httpPost);
    //解析结果
    String rst = EntityUtils.toString(response.getEntity());
    System.out.println(rst);
}

运行查询结果为:

服务端

客户端

客户端(OkHttp3)

1.导入对应的jar包

<dependencies>
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>3.9.1</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.9</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.30</version>
    </dependency>
</dependencies>

2.通过HttpClient发送GET请求查询所有用户列表

@Test
public void testFindAll() throws Exception{
   //创建OkHttpClient对象
    OkHttpClient httpClient = new OkHttpClient();
    //构建请求request对象
    Request request = new Request.Builder()
    		.url("http://localhost:8080/user/findAll").build();
    //发送请求
    Response response = httpClient.newCall(request).execute();
    //解析结果
    String rst = response.body().string();
    System.out.println(rst);
}

运行查询结果为:

3.通过HttpClient发送GET请求查询指定用户的详细信息

@Test
public void testFindAll() throws Exception{
   //创建OkHttpClient对象
    OkHttpClient httpClient = new OkHttpClient();
    //构建请求request对象
    Request request = new Request.Builder()
    		.url("http://localhost:8080/user/findUserById/3").build();
    //发送请求
    Response response = httpClient.newCall(request).execute();
    //解析结果
    String rst = response.body().string();
    System.out.println(rst);
}

运行查询结果为:

4.通过HttpClient发送POST请求完成用户的新增功能,发送数据类型为Form表单数据类型

@Test
public void testAddUserByForm() throws Exception{
    //创建OkHttpClient对象
    OkHttpClient httpClient = new OkHttpClient();
    //构建请求参数
    RequestBody requestBody = new FormBody.Builder()
    .add("name","猪八戒")
    .add("password","zbj").build();
    //构建请求request对象
    Request request = new Request.Builder()
    .url("http://localhost:8080/user/addUser").post(requestBody).build();
    //发送请求
    Response response = httpClient.newCall(request).execute();
    //解析结果
    String rst = response.body().string();
    System.out.println(rst);
}

运行查询结果为:

服务端

客户端

5.通过HttpClient发送POST请求完成用户的新增功能,发送数据类型为JSON数据类型

@Test
public void testAddUserByJSON()throws Exception{
    //创建OkHttpClient对象
    OkHttpClient httpClient = new OkHttpClient();
    //构建请求参数
    Map<String,Object> paramMap = new HashMap<String,Object>();
    paramMap.put("name","沙僧");
    paramMap.put("password","ss");
    String jsonString = JSONObject.toJSONString(paramMap);
    RequestBody requestBody = FormBody
   		 .create(MediaType.parse("application/json;charset=utf-8"),jsonString);
    //构建请求request对象
    Request request = new Request.Builder()
    	.url("http://localhost:8080/user/addUserByJson").post(requestBody).build();
    //发送请求
    Response response = httpClient.newCall(request).execute();
    //解析结果
    String rst = response.body().string();
    System.out.println(rst);
}

运行查询结果为:

服务端

客户端

总结

通过上述HttpClient和OkHttp3完成从服务器端获取数据的方式,我们已经完成了通过网络的方式来获取其

用户管理模块服务器上的内容。在上述程序的基础上,大家也可以完成更加复杂的功能模块。

当前主流的RPC(Remote Procedure Call)框架有很多,Feign和Dubbo是其中两个比较知名的。下面是关于它们的简要介绍: 1. **Feign**: - Feign是Netflix开发的一款轻量级的API客户端,主要用于简化服务间的接口调用。它基于Java注解,提供了一种声明式的接口调用方式,开发者只需定义接口,Feign会自动生成实现类和底层HTTP请求。 - Feign支持各种HTTP库,如OkHttp、Apache HttpClient等,并且可以轻松地集成到Spring Cloud生态系统中,方便微服务之间的通信。 2. **Dubbo**: - Dubbo是一个开源的企业级高性能远程服务调用框架,主要适用于大规模分布式服务架构,支持高并发、高性能和容错性。Dubbo基于Java,提供了一套全面的服务治理解决方案,包括注册中心、服务发现、负载均衡、熔断、限流等。 - 它通常用于企业级的微服务架构中,尤其在大型分布式系统中的服务间通信方面非常常见。 除了这两个,还有其他一些主流RPC框架,例如: - **gRPC**:Google开源的高性能RPC框架,基于Protocol Buffers协议,提供了高性能和安全性。 - **Retrofit**:Android和Java平台的流行库,结合OkHttp实现RESTful API调用。 - **Hystrix**(已被Netflix弃用):原本是Amazon的故障隔离工具,但现在常常与Feign一起作为服务降级和熔断方案使用。 如果你对这些RPC框架感兴趣,可以关注它们各自的特性、适用场景以及与其他技术栈的集成情况。有关更多细节,你可以询问: 1. Feign和Retrofit相比,各有何优缺点? 2. Dubbo和gRPC在性能上的差异体现在哪些方面? 3. 在微服务架构中,如何选择合适的RPC框架?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值