本文介绍在http协议中,使用protobuf格式进行二进制数据通信。双方需设置http的header中ContentType为application/x-protobuf。
1、springboot下实现protobuf:
1)pom.xml
html
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- protobuf -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.11.0</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.11.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.protobuf-java-format</groupId>
<artifactId>protobuf-java-format</artifactId>
<version>1.2</version>
</dependency>
<!-- 网络请求依赖 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4</version>
</dependency>
2)user_login.proto
bash
syntax = "proto3";
// 转成java后所在包
option java_package = "com.tencent.rating.audi_model_api.pb";
// 转成java后的类名
option java_outer_classname = "MessageUserLogin";
// 转java后生成一个java文件
option java_multiple_files = false;
message MessageUserLoginRequest {
string username = 1;
string password = 2;
}
message MessageUserLoginResponse {
string access_token = 1;
string username = 2;
}
编译:
bash
protoc --proto_path=/data/ --java_out=./ /data/user_login.proto
3)创建springboot工程,编写config:
java
@Configuration
public class WebConfig {
@Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
/**
* protobuf 反序列化 可以不用配置
*/
// @Bean
// RestTemplate restTemplate(ProtobufHttpMessageConverter protobufHttpMessageConverter) {
// return new RestTemplate(Collections.singletonList(protobufHttpMessageConverter));
// }
}
4)编写contorller:
java
import java.util.UUID;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.tencent.rating.audi_model_api.pb.MessageUserLogin;
@Controller
public class PbTestController {
@RequestMapping(value = "/pbtest", produces = "application/x-protobuf")
@ResponseBody
public MessageUserLogin.MessageUserLoginResponse getPersonProto(@RequestBody MessageUserLogin.MessageUserLoginRequest request) {
System.out.println("request:" + request.toString());
MessageUserLogin.MessageUserLoginResponse.Builder builder = MessageUserLogin.MessageUserLoginResponse.newBuilder();
builder.setAccessToken(UUID.randomUUID().toString()+"_res");
builder.setUsername(request.getUsername()+"_res");
return builder.build();
}
}
然后启动sprinboot工程。监听8080端口
5)编写客户端请求:
java
public class PbTest {
public static void main(String...strings) {
try {
String uri = "http://127.0.0.1:8080/clue/pbtest";
MessageUserLogin.MessageUserLoginRequest.Builder builder = MessageUserLogin.MessageUserLoginRequest.newBuilder();
builder.setUsername("tom");
builder.setPassword("123456");
HttpResponse response = doPost(uri, builder.build().toByteArray());
MessageUserLogin.MessageUserLoginResponse messageUserLoginResponse = MessageUserLogin.MessageUserLoginResponse.parseFrom(response.getEntity().getContent());
System.out.println("response:" + messageUserLoginResponse.toString());
System.err.println(messageUserLoginResponse.getAccessToken());
} catch (Exception e) {
}
}
private static HttpResponse doPost(String uri, byte[] bytes) throws Exception {
CloseableHttpResponse closeableHttpResponse = null;
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost post = new HttpPost(uri);
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
InputStreamEntity inputStreamEntity = new InputStreamEntity(inputStream);
post.setEntity(inputStreamEntity);
post.addHeader("Content-Type", "application/x-protobuf");
closeableHttpResponse = httpclient.execute(post);
} catch (IOException e) {
e.printStackTrace();
} finally {
// httpclient.close();
}
return closeableHttpResponse;
}
}
2、servlet下实现protobuf:
1)创建servlet项目,编写servlet代码:
java
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import servlet_test.pb.MessageUserLogin;
import servlet_test.pb.MessageUserLogin.MessageUserLoginRequest;
import servlet_test.pb.MessageUserLogin.MessageUserLoginResponse.Builder;
@WebServlet(urlPatterns = {"/syncServlet2"})
public class SyncServlet2 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
//解析请求
InputStream stream=request.getInputStream();
MessageUserLoginRequest mlr = MessageUserLogin.MessageUserLoginRequest.parseFrom(stream);
System.out.println(mlr.toString());
//创建响应
Builder newBuilder = MessageUserLogin.MessageUserLoginResponse.newBuilder();
newBuilder.setAccessToken(UUID.randomUUID().toString()+"_res");
newBuilder.setUsername(mlr.getUsername()+"_res");
response.setCharacterEncoding("UTF-8");
ServletOutputStream out = response.getOutputStream();
out.write(newBuilder.build().toByteArray());
out.flush();
out.close();
}
}
2)客户端测试:
同上。