序列化和反序列化
- Maven:Pom.xml
- <dependencies>
- <dependency>
- <groupId>org.apache.avro</groupId>
- <artifactId>avro</artifactId>
- <version>1.8.2</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.avro</groupId>
- <artifactId>avro-maven-plugin</artifactId>
- <version>1.8.1</version>
- <executions>
- <execution>
- <phase>generate-sources</phase>
- <goals>
- <goal>schema</goal>
- </goals>
- <configuration>
- <sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
- <outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
- </plugins>
- </build>
- Avro:MapAvro.avsc
- {
- "type":"record",
- "namespace":"com.qidai",
- "name":"Employee",
- "doc":"Test Employee bean",
- "fields":[
- {"name":"id","type":["null","int"]},
- {"name":"name","type":["null","string"]},
- {"name":"age","type":["null","int"]},
- {"name":"gender","type":["null","string"]}
- ]
- }
添加完依赖后直接点击 maven 插件 install 即可, 就会产生对应的 class
序列化和反序列化 (使用 javaclass)
- @Test
- public void ser() throws Exception {
- Employee employee = Employee.newBuilder().setAge(12).setGender("NAN").setId(1).setName("tom").build();
- DatumWriter<Employee> employeeDatumWriter = new SpecificDatumWriter<>(Employee.class);
- DataFileWriter<Employee> dataFileWriter = new DataFileWriter<>(employeeDatumWriter);
- dataFileWriter.create(employee.getSchema(), new File("emp.avro"));
- dataFileWriter.append(employee);
- dataFileWriter.close();
- }
- @Test
- public void deSer() throws Exception {
- DatumReader<Employee> employeeDatumReader = new SpecificDatumReader<>(Employee.class);
- DataFileReader<Employee> dataFileReader = new DataFileReader<>(new File("emp.avro"), employeeDatumReader);
- Employee employee = null;
- while (dataFileReader.hasNext()) {
- employee = dataFileReader.next();
- System.out.println(employee);
- }
- }
序列化反序列化 (直接使用 avro 文件)
- @Test
- public void ser() throws Exception {
- Schema schema = new Schema.Parser().parse(new File("emp.avsc"));
- GenericRecord empRecord1 = new GenericData.Record(schema);
- empRecord1.put("id", 1);
- empRecord1.put("name", "Ben");
- empRecord1.put("age", 7);
- empRecord1.put("gender", "nv");
- File file = new File("empser.avro");
- DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(schema);
- DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<>(datumWriter);
- dataFileWriter.create(schema, file);
- dataFileWriter.append(empRecord1);
- dataFileWriter.close();
- }
- @Test
- public void deSer() throws Exception {
- // 指定 avro 格式文件
- Schema schema = new Schema.Parser().parse(new File("emp.avsc"));
- // 指定序列化好的数据文件
- File file = new File("empser.avro");
- DatumReader<GenericRecord> datumReader = new GenericDatumReader<>(schema);
- DataFileReader<GenericRecord> dataFileReader = new DataFileReader<>(file, datumReader);
- GenericRecord emp = null;
- while (dataFileReader.hasNext()) {
- emp = dataFileReader.next();
- System.out.println(emp);
- }
- }
RPC 实现
编写 avsc 文件: user.avsc, 作为要发送的实体类
- {
- "namespace":"com.qidai.bean",
- "name":"User",
- "doc":"test rpc class",
- "type":"record",
- "fields":[
- {"name":"name","type":["string","null"]},
- {"name":"age","type":["int","null"]},
- {"name":"date","type":["string","null"]}
- ]
- }
编写协议文件: protomes.avdl
- @namespace("com.qidai.proto")
- protocol UserProtocol{
- import schema "user.avsc";
- string sendMes(com.qidai.bean.User user); // 对应协议中的方法
- }
编写完毕之后检查 maven pom 文件
- <dependencies>
- <dependency>
- <groupId>org.apache.avro</groupId>
- <artifactId>avro</artifactId>
- <version>1.8.2</version>
- </dependency>
- <dependency>
- <groupId>org.apache.avro</groupId>
- <artifactId>avro-ipc</artifactId>
- <version>1.8.2</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.avro</groupId>
- <artifactId>avro-maven-plugin</artifactId>
- <version>1.8.1</version>
- <executions>
- <execution>
- <phase>generate-sources</phase>
- <goals>
- <goal>schema</goal>
- <goal>idl-protocol</goal>
- </goals>
- <configuration>
- <sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
- <outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
- </plugins>
- </build>
检查没错之后, 直接插件 install 生成 avro 类
生成之后会看到一个 User 的传输类, 还有一个 proto 包下的协议接口
实现协议接口, 重写自己的逻辑: server
- public class UserProtocolImpl implements UserProtocol {
- @Override
- public CharSequence sendMes(User user) throws AvroRemoteException {
- System.out.println("Server --> 接收" + user.toString());
- return "Client sendMes" + user.toString();
- }
- }
实现协议接口, 重写自己的逻辑: client
- public class UserProtocolImpl implements UserProtocol {
- @Override
- public CharSequence sendMes(User user) throws AvroRemoteException {
- System.out.println("Client --> 发送" + user.toString());
- return "Client sendMes" + user.toString();
- }
- }
编写 serverApp
- public class ServerApp {
- public static void main(String[] args) throws IOException, InterruptedException {
- Responder responder = new SpecificResponder(UserProtocol.class,new UserProtocolImpl());
- SaslSocketServer server = new SaslSocketServer(responder,new InetSocketAddress(9999));
- server.start();
- Thread.sleep(5000000);
- }
- }
编写 clientApp
- public class ClientApp {
- public static void main(String[] args) throws IOException {
- SaslSocketTransceiver transceiver = new SaslSocketTransceiver(new InetSocketAddress(9999));
- UserProtocol client = SpecificRequestor.getClient(UserProtocol.class, transceiver);
- Scanner scanner = new Scanner(System.in);
- while (scanner.next() != null) {
- User user = new User();
- user.setName("xiaofen");
- System.out.println(client.sendMes(user));
- }
- }
- }
测试: 先启动 serverApp, 然后启动 clientApp, 这时候在 client 的 console 中输入任意值, 会发现服务端和客户端都会输出消息
- server
- Server --> {
- "name": "xiaofen", "age": null, "date": null
- }
- Server --> {
- "name": "xiaofen", "age": null, "date": null
- }
- Server --> {
- "name": "xiaofen", "age": null, "date": null
- }
- Server --> {
- "name": "xiaofen", "age": null, "date": null
- }
- Server --> {
- "name": "xiaofen", "age": null, "date": null
- }
- Server --> {
- "name": "xiaofen", "age": null, "date": null
- }
- Server --> {
- "name": "xiaofen", "age": null, "date": null
- }
- client
- 1
- Client sendMes {
- "name": "xiaofen", "age": null, "date": null
- }
- 1
- Client sendMes {
- "name": "xiaofen", "age": null, "date": null
- }
- 1
- Client sendMes {
- "name": "xiaofen", "age": null, "date": null
- }
- 1
- Client sendMes {
- "name": "xiaofen", "age": null, "date": null
- }
- 1
- Client sendMes {
- "name": "xiaofen", "age": null, "date": null
- }
- 1
- Client sendMes {
- "name": "xiaofen", "age": null, "date": null
- }
- 1
- Client sendMes {
- "name": "xiaofen", "age": null, "date": null
- }
对于 server 的 client 的实现有如下几种
1. 基于 jetty 的 http 实现: HttpServer 和 HttpTransceiver
2. 基于 netty 的实现: NettyServer 和 NettyTransceiver
3. 基于 TCP 的实现: SocketServer 和 SocketTransceiver
4. 基于 UDP 的实现: DatagramServer 和 DatagramTransceiver
5. 基于加密的 TCP 实现: SaslSocketServer 和 SaslSocketTransceiver
来源: https://yq.aliyun.com/articles/684896