如何实现手写支持HTTP协议的远程过程调用(RPC)框架?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1135个文字,预计阅读时间需要5分钟。
一、模块划分 + 聚合工程 + 顶级模块:new_rpc
二、父模块:httpclient_rpc
三、子模块:httpclient_rpc_server、httpclient_rpc_client、httpclient_rpc_pojo
四、使用顶级模块的原因:因为rpc协议自定义
一、模块划分
聚合工程
顶级模块:new_rpc
父模块:localhost/params");
//基于单参数传递,构建请求地址
//builder.addParameter("name", "bjsxt");
//builder.addParameter("password", "admin123");
//URI uri = builder.build();
//基于多参数传递,构建请求地址
List<NameValuePair> nvps = new ArrayList<>();
nvps.add(new BasicNameValuePair("name", "bjsxt"));
nvps.add(new BasicNameValuePair("password", "admin123"));
builder.addParameters(nvps);
URI uri = builder.build();
String result = EntityUtils.toString(client.execute(new HttpGet(uri)).getEntity());
System.out.println(result);
}
/**
* 无参数GET请求
* 使用浏览器,访问网站的过程是:
* 1、打开浏览器
* 2、输入网址
* 3、访问
* 4、看结果
* 使用HttpClient,访问WEB服务的过程:
* 1、创建客户端,相当于打开浏览器
* 2、创建请求地址,相当于输入地址
* 3、发起请求,相当于访问网站(回车键)
* 4、处理响应结果,相当于浏览器显示结果
*/
private static void testGetNoParams() throws IOException {
// 创建客户端对象
HttpClient client = HttpClients.createDefault();
// 创建请求地址
HttpGet get = new HttpGet("localhost:80/test");
// 发起请求,接收响应对象
HttpResponse response = client.execute(get);
// 获取响应体,响应数据是一个基于HTTP协议标准字符串封装的对象
HttpEntity entity = response.getEntity();
// 通过HTT实体工具类,转换响应体数据,使用的字符串是UTF-8
String responseString = EntityUtils.toString(entity, "UTF-8");
System.out.println("服务器响应的数据是 - [ " + responseString + "]");
client = null;
}
/**
* POST请求
*/
public static void testPost() throws Exception {
//无参数Post请求
HttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost("localhost/test");
HttpResponse response = client.execute(post);
System.out.println(EntityUtils.toString(response.getEntity(), "UTF-8"));
//有参数的Post请求
//请求头传递参数,和Get请求携带参数的方式一致
URIBuilder builder = new URIBuilder("localhost/params");
builder.addParameter("name", "post");
builder.addParameter("password", "postPassword");
URI uri = builder.build();
HttpResponse postResponse = client.execute(new HttpPost(uri));
System.out.println(EntityUtils.toString(postResponse.getEntity(), "UTF-8"));
//请求体传递参数
HttpPost bodyParamsPost = new HttpPost("localhost/bodyParams");
//定义请求体协议,设置请求参数。使用请求体传递参数的时候,需要定义请求体格式。默认是表单格式
//使用URLBuilder构建的URI对象,就是请求体传递参数的。
User u1 = new User();
u1.setName("zs");
u1.setPassword("123");
User u2 = new User();
u2.setName("ls");
u2.setPassword("456");
//手动json格式化
//String paramsString = "[" + u1.toString() + "," + u2.toString() + "]";
//使用jackson框架格式化
List<User> list = new ArrayList<>();
list.add(u1);
list.add(u2);
String paramsString;
ObjectMapper om = new ObjectMapper();
paramsString = om.writeValueAsString(list);
HttpEntity entity = new StringEntity(paramsString, "application/json", "UTF-8");
bodyParamsPost.setEntity(entity);
System.out.println(EntityUtils.toString(client.execute(bodyParamsPost).getEntity(), "UTF-8"));
String responseString = EntityUtils.toString(client.execute(bodyParamsPost).getEntity(), "UTF-8");
//将一个json格式的对象转换为java对象
String userString = responseString.substring(1, responseString.indexOf("},") + 1);
User responseUser = om.readValue(userString, User.class);
System.out.println(responseUser);
//将以json格式的对象数组转换为java对象数组
JavaType valueType = om.getTypeFactory().constructParametricType(List.class, User.class);
List<User> responseUserList = om.readValue(responseString, valueType);
System.out.println(responseUserList);
}
}
通过页面的ajax请求访问,后端以springboot启动,前端以web启动
注意需要导入jquery.js包才可使用ajax请求,这里如果使用了跨域请求,也就是前后端分离请求,就需要在后端设置@CrossOrigin来允许跨域访问
后端没有设置@CrossOrigin会导致跨域请求而访问失败
<!DOCTYPE html><html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="jquery-3.5.1.min.js"></script>
<script type="text/javascript">
//javascript中默认的,ajax请求不能跨域
//跨域 - ajax所属的站点,和被请求的站点,不是同一个域
//域 - id,端口,域名,主机名,任何一个有变化,都是不同域
function sendBodyParams(){
$.ajax({
"url": "localhost:80/bodyParams",
"type": "post",
"data": "[{\"name\":\"abc\",\"password\":\"123\"},{\"name\":\"def\",\"password\":\"456\"}]",
"contentType": "application/json",//必须设定,代表请求体的格式。默认是text/plain,默认是参数名=参数值&参数名=参数值
"dataType": "json",
"success": function(data){
alert(data);
console.log(data);
}
});
}
</script>
</head>
<body style="text-align: center">
<button onclick="sendBodyParams()">测试ajax请求,请求体传递JSON数据</button>
</body>
</html>
本文共计1135个文字,预计阅读时间需要5分钟。
一、模块划分 + 聚合工程 + 顶级模块:new_rpc
二、父模块:httpclient_rpc
三、子模块:httpclient_rpc_server、httpclient_rpc_client、httpclient_rpc_pojo
四、使用顶级模块的原因:因为rpc协议自定义
一、模块划分
聚合工程
顶级模块:new_rpc
父模块:localhost/params");
//基于单参数传递,构建请求地址
//builder.addParameter("name", "bjsxt");
//builder.addParameter("password", "admin123");
//URI uri = builder.build();
//基于多参数传递,构建请求地址
List<NameValuePair> nvps = new ArrayList<>();
nvps.add(new BasicNameValuePair("name", "bjsxt"));
nvps.add(new BasicNameValuePair("password", "admin123"));
builder.addParameters(nvps);
URI uri = builder.build();
String result = EntityUtils.toString(client.execute(new HttpGet(uri)).getEntity());
System.out.println(result);
}
/**
* 无参数GET请求
* 使用浏览器,访问网站的过程是:
* 1、打开浏览器
* 2、输入网址
* 3、访问
* 4、看结果
* 使用HttpClient,访问WEB服务的过程:
* 1、创建客户端,相当于打开浏览器
* 2、创建请求地址,相当于输入地址
* 3、发起请求,相当于访问网站(回车键)
* 4、处理响应结果,相当于浏览器显示结果
*/
private static void testGetNoParams() throws IOException {
// 创建客户端对象
HttpClient client = HttpClients.createDefault();
// 创建请求地址
HttpGet get = new HttpGet("localhost:80/test");
// 发起请求,接收响应对象
HttpResponse response = client.execute(get);
// 获取响应体,响应数据是一个基于HTTP协议标准字符串封装的对象
HttpEntity entity = response.getEntity();
// 通过HTT实体工具类,转换响应体数据,使用的字符串是UTF-8
String responseString = EntityUtils.toString(entity, "UTF-8");
System.out.println("服务器响应的数据是 - [ " + responseString + "]");
client = null;
}
/**
* POST请求
*/
public static void testPost() throws Exception {
//无参数Post请求
HttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost("localhost/test");
HttpResponse response = client.execute(post);
System.out.println(EntityUtils.toString(response.getEntity(), "UTF-8"));
//有参数的Post请求
//请求头传递参数,和Get请求携带参数的方式一致
URIBuilder builder = new URIBuilder("localhost/params");
builder.addParameter("name", "post");
builder.addParameter("password", "postPassword");
URI uri = builder.build();
HttpResponse postResponse = client.execute(new HttpPost(uri));
System.out.println(EntityUtils.toString(postResponse.getEntity(), "UTF-8"));
//请求体传递参数
HttpPost bodyParamsPost = new HttpPost("localhost/bodyParams");
//定义请求体协议,设置请求参数。使用请求体传递参数的时候,需要定义请求体格式。默认是表单格式
//使用URLBuilder构建的URI对象,就是请求体传递参数的。
User u1 = new User();
u1.setName("zs");
u1.setPassword("123");
User u2 = new User();
u2.setName("ls");
u2.setPassword("456");
//手动json格式化
//String paramsString = "[" + u1.toString() + "," + u2.toString() + "]";
//使用jackson框架格式化
List<User> list = new ArrayList<>();
list.add(u1);
list.add(u2);
String paramsString;
ObjectMapper om = new ObjectMapper();
paramsString = om.writeValueAsString(list);
HttpEntity entity = new StringEntity(paramsString, "application/json", "UTF-8");
bodyParamsPost.setEntity(entity);
System.out.println(EntityUtils.toString(client.execute(bodyParamsPost).getEntity(), "UTF-8"));
String responseString = EntityUtils.toString(client.execute(bodyParamsPost).getEntity(), "UTF-8");
//将一个json格式的对象转换为java对象
String userString = responseString.substring(1, responseString.indexOf("},") + 1);
User responseUser = om.readValue(userString, User.class);
System.out.println(responseUser);
//将以json格式的对象数组转换为java对象数组
JavaType valueType = om.getTypeFactory().constructParametricType(List.class, User.class);
List<User> responseUserList = om.readValue(responseString, valueType);
System.out.println(responseUserList);
}
}
通过页面的ajax请求访问,后端以springboot启动,前端以web启动
注意需要导入jquery.js包才可使用ajax请求,这里如果使用了跨域请求,也就是前后端分离请求,就需要在后端设置@CrossOrigin来允许跨域访问
后端没有设置@CrossOrigin会导致跨域请求而访问失败
<!DOCTYPE html><html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="jquery-3.5.1.min.js"></script>
<script type="text/javascript">
//javascript中默认的,ajax请求不能跨域
//跨域 - ajax所属的站点,和被请求的站点,不是同一个域
//域 - id,端口,域名,主机名,任何一个有变化,都是不同域
function sendBodyParams(){
$.ajax({
"url": "localhost:80/bodyParams",
"type": "post",
"data": "[{\"name\":\"abc\",\"password\":\"123\"},{\"name\":\"def\",\"password\":\"456\"}]",
"contentType": "application/json",//必须设定,代表请求体的格式。默认是text/plain,默认是参数名=参数值&参数名=参数值
"dataType": "json",
"success": function(data){
alert(data);
console.log(data);
}
});
}
</script>
</head>
<body style="text-align: center">
<button onclick="sendBodyParams()">测试ajax请求,请求体传递JSON数据</button>
</body>
</html>

