avro

一、介绍,直接看官网来得快

官方网站:http://avro.apache.org/

1.1、Maven项目构建pom示例

所需要的jar包

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  <!-- 测试类 -->
              < dependency >
                    < groupId > junit</ groupId  >
                    < artifactId > junit</ artifactId  >
                    < version > 4.12</ version  >
              </ dependency >
              <!-- 序列化需要的jar -->
              < dependency >
                    < groupId > org.apache.avro</ groupId  >
                    < artifactId > avro</ artifactId  >
                    < version > 1.7.7</ version  >
              </ dependency >
              <!-- rpc 通讯需要的jar -->
              < dependency >
                    < groupId > org.apache.avro</ groupId  >
                    < artifactId > avro-ipc</ artifactId >
                    < version > 1.7.7</ version  >
              </ dependency >

所需要的插件,如果是在外部生成,可以不要

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  < plugin  >
     < groupId  > org.apache.avro</ groupId >
     < artifactId  > avro-maven-plugin</ artifactId >
     < version  > 1.7.7</ version >
     < executions  >
           < execution >
                 < phase > generate-sources</ phase  >
                 < goals >
                       <!-- Schema序列化 -->
                       <!-- <goal>schema</goal> -->
                       <!-- RPC协议通讯 -->
                       < goal > protocol</ goal  >
                 </ goals >
                 < configuration >
                       <!-- 源目录,用于存放 avro的schema文件及protocol文件 -->
                       < sourceDirectory > ${project.basedir}/src/main/resources/</ sourceDirectory >
                       < outputDirectory > ${project.basedir}/src/main/java/</ outputDirectory >
                 </ configuration >
           </ execution >
     </ executions  >
  </ plugin  >

二、消息结构

Avro的模式主要由JSON对象来表示,Avro支持8种基本类型(Primitive Type)和6种复杂类型(Complex Type:records、enums、arrays、maps、unions 和fixed),基本类型可以由JSON字符串来表示。

Avro支持两种序列化编码方式:二进制编码和JSON编码,使用二进制编码会高效序列化,并且序列化后得到的结果会比较小。

2.1、基本数据类型

null: 表示没有值 0字节

boolean: 表示一个二进制布尔值 一个字节 0-false,1-true

int: 表示32位有符号整数
long: 表示64位有符号整数
float: 表示32位的单精度浮点数(IEEE 754)4字节
double: 表示64位双精度浮点数(IEEE 754) 8字节
bytes: 表示8位的无符号字节序列
string: Unicode 编码的字符序列

总共就这8种原生数据类型,这些原生数据类型均没有明确的属性。

原生数据类型也可以使用JSON定义类型名称,比如schema "string"和{"type": "string"}是同义且相等的。

2.2、复合数据类型

2.2.1、records使用类型名称“record”,并且支持三个必选属性。
type: 必有属性。

name: 必有属性,是一个JSON string,提供了记录的名字。

namespace,也是一个JSON string,用来限定和修饰name属性,动态方式生成后,为Java的包名

doc: 可选属性,是一个JSON string,为使用这个Schema的用户提供文档。

aliases: 可选属性,是JSON的一个string数组,为这条记录提供别名。

fields: 必选属性,是一个JSON数组,数组中列举了所有的field。每一个field都是一个JSON对象,并且具有如下属性:

     name: 必选属性,field的名字,是一个JSON string,类似一个Java属性。

     doc: 可选属性,为使用此Schema的用户提供了描述此field的文档。

     type: 必选属性,定义Schema的一个JSON对象,或者是命名一条记录定义的JSON string。

     default: 可选属性,即field的默认值,当读到缺少这个field的实例时用到。

例如:

?
1
2
3
4
5
6
7
8
9
{"namespace": "example.avro",
"type": "record",
"name": "User",
"fields": [
      {"name": "name", "type": "string"},
      {"name": "favorite_number",  "type": ["int", "null"]},
      {"name": "favorite_color", "type": ["string", "null"]}
]
}

说明:以上表示建立了一个复合类型User,具有三个字段属性,分别是字符串类型的name,整型的favorite_number,字符串类型的favorite_color,报名:example.avro,类名为:user

2.2.2、“enum”的type并且支持如下的属性:

name: 必有属性,是一个JSON string,提供了enum的名字。
namespace,也是一个JSON string,用来限定和修饰name属性。
aliases: 可选属性,是JSON的一个string数组,为这个enum提供别名。
doc: 可选属性,是一个JSON string,为使用这个Schema的用户提供文档。
symbols: 必有属性,是一个JSON string数组,列举了所有的symbol,在enum中的所有symbol都必须是唯一的,不允许重复。比如下面的例子:
例如

?
1
2
3
4
{ "type": "enum",
"name": "Suit",
"symbols" : ["SPADES", "HEARTS", "DIAMONDS", "CLUBS"]
}

说明:以上表示建立了一个Suit的枚举类,含有symbols里面的属性

2.2.3、Array使用名为"array"的type,并且支持一个属性 items: array中元素的Schema

例如

?
1
2
3
4
5
6
7
{
   "type": "record",
   "name": "ArrAvro",
   "fields" : [
     {"name": "arr", "type": ["null",{"type":"array", "items":"string"}]}
   ]
}

2.2.4、Map使用名为"map"的type,并且支持一个属性 values: 用来定义map的值的Schema。Maps的key都是string。

比如一个key为string,value为long的maps定义为:

例如
{
  "type": "record",
  "name": "MapAvro",
  "fields" : [
    {"name": "map", "type": ["null",{"type":"map", "values":"string"}]}
  ]

}

2.2.5、序列化文件样式及RPC通讯协议样式编写

序列化schema文件

Members.avsc

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
        "namespace":"com.ifree.serrpc.builder",
        "type":"record",
        "name":"Members",
        "fields":[
             {
                    "name":"userName",
                    "type":"string"
             },
             {
                    "name":"userPwd",
                    "type":"string"
             },
             {
                    "name":"realName",
                    "type":"string"
             }
             
       ]
       
}

说明:该文件中的namespace命名空间在生成代码的时候会自动生成包路径;type类型是record复合类型;name为Members,在生成的时候,会生成一个Members类,建议首字母大写;fields是一个字段集合,里面的每一个字段类似与Java的实体字段,如userName字段,类型为String


RPC通讯协议protocol文件

Members.avpr

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
{
        "namespace":"com.ifree.serrpc.builder",
        "protocol":"MemberIFace",
        "types":[
             {
                    "type":"record",
                    "name":"Members",
                    "fields":[
                         {
                                "name":"userName",
                                "type":"string"
                         },
                         {
                                "name":"userPwd",
                                "type":"string"
                         },
                         {
                                "name":"realName",
                                "type":[
                                      "string",
                                      "null"
                               ]
                               
                         }
                         
                   ]
                   
             },
             {
                    "type":"record",
                    "name":"Retmsg",
                    "fields":[
                         {
                                "name":"msg",
                                "type":"string"
                         }
                   ]
             }
             
       ],
        "messages":{
              "login":{
                    "doc":"member login.",
                    "request":[
                         {
                                "name":"m",
                                "type":"Members"
                         }
                         
                   ],
                    "response":"Retmsg"
             }
             
       }
}

说明:该文件中,namespace表示包路径;protocol表示协议,名字是MemberIFace,这里在工具生成的时候会生成一个类,故首字母大写;types是一个类型集合,返回类型和请求类型都可以在这里定义,里面的定义方式可参考序列化化定义文件;messages是表示一个请求返回消息体,login表示一个Java方法,里面有两部分组成,请求和响应,request表示请求,里面是一个members类型的对象,response表示相应,返回值,这里是Retmsg对象。

三、序列化编码

     Avro有两种序列化编码:binary和JSON。

四、序列化

      在使用序列化时,我们可以有两种方式来实现,一种是静态方式,采用schema文件来生成所需要的类,然后直接调用类里面的实现;另一种是动态方式,直接采用代码解析schema文件内容,动态设置内容。

五、RPC

      在使用Avro进行RPC通讯时,我们可以有两种方式来实现,一种是静态方式,采用protocol文件来生成所需要的类,然后直接调用类里面的实现;另一种是动态方式,直接采用代码解析protocol文件内容,动态设置内容。

六、综合示例

序列化Schema和RPC的Protocol都是上面的文件,这里不做列出

Java代码:

服务端代码:含(动态|工具)序列化、RPC通讯代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
package  com.ifree.serrpc.avro;
 
import  java.io.File;
import  java.io.IOException;
import  java.net.InetSocketAddress;
import  java.util.Random;
 
import  org.apache.avro.Protocol;
import  org.apache.avro.Protocol.Message;
import  org.apache.avro.Schema;
import  org.apache.avro.Schema.Parser;
import  org.apache.avro.file.DataFileWriter;
import  org.apache.avro.generic.GenericData;
import  org.apache.avro.generic.GenericRecord;
import  org.apache.avro.io.DatumWriter;
import  org.apache.avro.ipc.HttpServer;
import  org.apache.avro.ipc.NettyServer;
import  org.apache.avro.ipc.Server;
import  org.apache.avro.ipc.generic.GenericResponder;
import  org.apache.avro.ipc.specific.SpecificResponder;
import  org.apache.avro.specific.SpecificDatumWriter;
import  org.junit.Test;
 
import  com.ifree.serrpc.builder.MemberIFace;
import  com.ifree.serrpc.builder.Members;
import  com.ifree.serrpc.impl.MemberIFaceImpl;
 
/**
  * 会员信息处理服务端
 
  * @author ifree
  *
  */
public  class  MemberServerProvider {
 
     /**
      * 动态序列化:通过动态解析Schema文件进行内容设置,并序列化内容
     
      * @throws IOException
      */
     @Test
     public  void  MemberInfoDynSer()  throws  IOException {
         // 1.解析schema文件内容
         Parser parser =  new  Parser();
         Schema mSchema = parser.parse( this .getClass().getResourceAsStream( "/Members.avsc" ));
         // 2.构建数据写对象
         DatumWriter<GenericRecord> mGr =  new  SpecificDatumWriter<GenericRecord>(mSchema);
         DataFileWriter<GenericRecord> mDfw =  new  DataFileWriter<GenericRecord>(mGr);
         // 3.创建序列化文件
         mDfw.create(mSchema,  new  File( "E:/avro/members.avro" ));
         // 4.添加序列化数据
         for  ( int  i =  0 ; i <  20 ; i++) {
             GenericRecord gr =  new  GenericData.Record(mSchema);
             int  r = i *  new  Random().nextInt( 50 );
             gr.put( "userName" "xiaoming-"  + r);
             gr.put( "userPwd" "9999"  + r);
             gr.put( "realName" "小明"  + r +  "号" );
             mDfw.append(gr);
         }
         // 5.关闭数据文件写对象
         mDfw.close();
         System.out.println( "Dyn Builder Ser Start Complete." );
     }
 
     /**
      * 通过Java工具生成文件方式进行序列化操作 命令:C:\Users\Administrator>java -jar
      * E:\avro\avro-tools-1.7.7.jar compile schema E:\avro\Members.avsc E:\avro
     
      * @throws IOException
      */
     @Test
     public  void  MemberInfoToolsSer()  throws  IOException {
         // 1.为Member生成对象进行设置必要的内容,这里实现三种设置方式的演示
         // 1.1、构造方式
         Members m1 =  new  Members( "xiaoming" "123456" "校名" );
         // 1.2、属性设置
         Members m2 =  new  Members();
         m2.setUserName( "xiaoyi" );
         m2.setUserPwd( "888888" );
         m2.setRealName( "小艺" );
         // 1.3、Builder方式设置
         Members m3 = Members.newBuilder().setUserName( "xiaohong" ).setUserPwd( "999999" ).setRealName( "小红" ).build();
         // 2.构建反序列化写对象
         DatumWriter<Members> mDw =  new  SpecificDatumWriter<Members>(Members. class );
         DataFileWriter<Members> mDfw =  new  DataFileWriter<Members>(mDw);
         // 2.1.通过对Members.avsc的解析创建Schema
         Schema schema =  new  Parser().parse(AvroSerProvider. class .getClass().getResourceAsStream( "/Members.avsc" ));
         // 2.2.打开一个通道,把schema和输出的序列化文件关联起来
         mDfw.create(schema,  new  File( "E:/avro/members.avro" ));
         // 4.把刚刚创建的Users类数据追加到数据文件写入对象中
         mDfw.append(m1);
         mDfw.append(m2);
         mDfw.append(m3);
         // 5.关闭数据文件写入对象
         mDfw.close();
         System.out.println( "Tools Builder Ser Start Complete." );
     }
 
     // ******************************************************ser
     // end*********************************************************
     /**
      * 服务端支持的网络通讯协议有:NettyServer、SocketServer、HttpServer
      * 采用HTTPSERVER方式调用
     
      * @throws IOException
      * @throws InterruptedException
      */
     @Test
     public  void  MemberHttpRPCDynBuilderServer()  throws  IOException, InterruptedException {
         // 1.进行业务处理
         GenericResponder gr = bussinessDeal();
         // 2.开启一个HTTP服务端,进行等待客户端的连接
         Server server =  new  HttpServer(gr,  60090 );
         server.start();
         System.out.println( "Dyn Builder PRC Start Complete." );
         server.join();
     }
 
     /**
      * 服务端支持的网络通讯协议有:NettyServer、SocketServer、HttpServer
      * 采用Netty方式调用
     
      * @throws IOException
      * @throws InterruptedException
      */
     @Test
     public  void  MemberNettyRPCDynBuilderServer()  throws  IOException, InterruptedException {
         // 1.进行业务处理
         GenericResponder gr = bussinessDeal();
         // 2.开启一个Netty服务端,进行等待客户端的连接
         Server server =  new  NettyServer(gr,  new  InetSocketAddress( 60090 ));
         server.start();
         System.out.println( "Dyn Builder PRC Start Complete." );
         server.join();
     }
 
     /**
      * 主要进行业务处理 服务端逻辑处理 采用动态生成代码处理方式,客户端和服务端只需要有protocol文件即可,不需要手工生成代码
     
      * @return
      * @throws IOException
      */
     private  GenericResponder bussinessDeal()  throws  IOException {
         // 1.构建协议
         final  Protocol protocol = Protocol.parse( this .getClass().getResourceAsStream( "/Members.avpr" ));
         // 2.构建业务逻辑及响应客户端
         GenericResponder gr =  new  GenericResponder(protocol) {
             @Override
             public  Object respond(Message message, Object request)  throws  Exception {
                 System.err.println( "request:"  + request);
                 // 3.获取请求信息
                 GenericRecord record = (GenericRecord) request;
                 GenericRecord retGr =  null ;
                 // 4.判断请求的方法
                 if  (message.getName().equals( "login" )) {
                     // 5.获取到传输的参数
                     Object obj = record.get( "m" );
 
                     GenericRecord mGr = (GenericRecord) obj;
                     String userName = mGr.get( "userName" ).toString();
                     String userPwd = mGr.get( "userPwd" ).toString();
                     // 6.进行相应的业务逻辑处理
                     System.out.println( "Members:"  ",userName:"  + userName + mGr +  ",userPwd:"  + userPwd);
                     String retMsg;
                     if  (userName.equalsIgnoreCase( "rita" ) && userPwd.equals( "123456" )) {
                         retMsg =  "哈哈,恭喜你,成功登录。" ;
                         System.out.println(retMsg);
                     else  {
                         retMsg =  "登录失败。" ;
                         System.out.println(retMsg);
                     }
                     // 7.获取返回值类型
                     retGr =  new  GenericData.Record(protocol.getMessages().get( "login" ).getResponse());
                     // 8.构造回复消息
                     retGr.put( "msg" , retMsg);
                 }
                 System.err.println( "DEAL SUCCESS!" );
                 return  retGr;
             }
         };
         return  gr;
     }
     
     
     /**
      * Java工具生成协议代码方式:java -jar  E:\avro\avro-tools-1.7.7.jar compile protocol E:\avro\Members.avpr E:\avro
      * 功能和动态调用方式一致
      * @throws InterruptedException 
      */
     @Test
     public  void  MemberNettyRPCToolsBuilderServer()  throws  InterruptedException{
         //1.构造接口和实现类的映射相应对象,MemberIFaceImpl该类为具体的业务实现类
         SpecificResponder responder= new  SpecificResponder(MemberIFace. class new  MemberIFaceImpl());
         //2.Netty启动RPC服务
         Server server= new  NettyServer(responder,  new  InetSocketAddress( 60090 ));
         server.start();
         System.out.println( "Tools Builder PRC Start Complete." );
         server.join();
     }
 
}

客户端代码:含(动态|工具)反序列化、RPC通讯代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package  com.ifree.serrpc.avro;
 
import  java.io.File;
import  java.io.IOException;
import  java.net.InetSocketAddress;
import  java.net.URL;
 
import  org.apache.avro.Protocol;
import  org.apache.avro.Schema;
import  org.apache.avro.Schema.Parser;
import  org.apache.avro.file.DataFileReader;
import  org.apache.avro.generic.GenericData;
import  org.apache.avro.generic.GenericRecord;
import  org.apache.avro.io.DatumReader;
import  org.apache.avro.ipc.HttpTransceiver;
import  org.apache.avro.ipc.NettyTransceiver;
import  org.apache.avro.ipc.Transceiver;
import  org.apache.avro.ipc.generic.GenericRequestor;
import  org.apache.avro.ipc.specific.SpecificRequestor;
import  org.apache.avro.specific.SpecificDatumReader;
import  org.junit.Test;
 
import  com.ifree.serrpc.builder.MemberIFace;
import  com.ifree.serrpc.builder.Members;
import  com.ifree.serrpc.builder.Retmsg;
 
/**
  * 服务消费者 该类测试了通过工具和动态序列化及反序列化两种方式,同时测试了通过工具生成代码及动态调用RPC服务两种方式
 
  * @author ifree
  *
  */
public  class  MemberServerConsumer {
 
     /**
      * 动态反序列:通过Schema文件进行动态反序列化操作
     
      * @throws IOException
      */
     @Test
     public  void  MemberInfoDynDeser()  throws  IOException {
         // 1.schema文件解析
         Parser parser =  new  Parser();
         Schema mSchema = parser.parse( this .getClass().getResourceAsStream( "/Members.avsc" ));
 
         // 2.构建数据读对象
         DatumReader<GenericRecord> mGr =  new  SpecificDatumReader<GenericRecord>(mSchema);
         DataFileReader<GenericRecord> mDfr =  new  DataFileReader<GenericRecord>( new  File( "E:/avro/members.avro" ), mGr);
         // 3.从序列化文件中进行数据反序列化取出数据
         GenericRecord gr =  null ;
         while  (mDfr.hasNext()) {
             gr = mDfr.next();
             System.err.println( "deser data:"  + gr.toString());
         }
         mDfr.close();
         System.out.println( "Dyn Builder Ser Start Complete." );
     }
 
     /**
      * 通过Java工具来生成必要的类,进行反序列化操作
     
      * @throws IOException
      */
     @Test
     public  void  MemberInfoToolsDeser()  throws  IOException {
         // 1.构建反序列化读取对象
         DatumReader<Members> mDr =  new  SpecificDatumReader<Members>(Members. class );
         DataFileReader<Members> mDfr =  new  DataFileReader<Members>( new  File( "E:/avro/members.avro" ), mDr);
         Members m =  null ;
         // 2.循环读取文件数据
         while  (mDfr.hasNext()) {
             m = mDfr.next();
             System.err.println( "tools deser data :"  + m);
         }
         // 3.关闭读取对象
         mDfr.close();
         System.out.println( "Tools Builder Ser Start Complete." );
     }
 
     /**
      * 采用HTTP方式建立和服务端的连接
     
      * @throws IOException
      */
     @Test
     public  void  MemberHttpRPCDynBuilderClient()  throws  IOException {
         // 1.建立和服务端的http通讯
         Transceiver transceiver =  new  HttpTransceiver( new  URL( "http://192.168.1.116:60090" ));
         bussinessDeal(transceiver);
     }
 
     /**
      * 采用Netty方式建立和服务端的连接
     
      * @throws IOException
      */
     @Test
     public  void  MemberNettyRPCDynBuilderClient()  throws  IOException {
         // 1.建立和服务端的Netty通讯
         Transceiver transceiver =  new  NettyTransceiver( new  InetSocketAddress( "192.168.1.116" 60090 ));
         // 2.进行必要的业务处理
         bussinessDeal(transceiver);
     }
 
     /**
      * 进行必要的业务处理
     
      * @param transceiver
      * @throws IOException
      */
     private  void  bussinessDeal(Transceiver transceiver)  throws  IOException {
         // 2.获取协议
         Protocol protocol = Protocol.parse( this .getClass().getResourceAsStream( "/Members.avpr" ));
         // 3.根据协议和通讯构造请求对象
         GenericRequestor requestor =  new  GenericRequestor(protocol, transceiver);
         // 4.根据schema获取messages主节点内容
         GenericRecord loginGr =  new  GenericData.Record(protocol.getMessages().get( "login" ).getRequest());
         // 5.在根据协议里面获取request中的schema
         GenericRecord mGr =  new  GenericData.Record(protocol.getType( "Members" ));
         // 6.设置request中的请求数据
         mGr.put( "userName" "rita" );
         mGr.put( "userPwd" "123456" );
         // 7、把二级内容加入到一级message的主节点中
         loginGr.put( "m" , mGr);
         // 8.设置完毕后,请求方法,正式发送访问请求信息,并得到响应内容
         Object retObj = requestor.request( "login" , loginGr);
         // 9.进行解析操作
         GenericRecord upGr = (GenericRecord) retObj;
         System.out.println(upGr.get( "msg" ));
     }
 
     /**
      * Java工具生成协议代码方式:java -jar E:\avro\avro-tools-1.7.7.jar compile protocol
      * E:\avro\Members.avpr E:\avro 功能和动态调用方式一致
     
      * @throws InterruptedException
      * @throws IOException
      */
     @Test
     public  void  MemberNettyRPCToolsBuilderClient()  throws  InterruptedException, IOException {
         // 1.和服务端建立通讯
         Transceiver transceiver =  new  NettyTransceiver( new  InetSocketAddress( "192.168.1.116" 60090 ));
         // 2.获取客户端对象
         MemberIFace memberIFace = SpecificRequestor.getClient(MemberIFace. class , transceiver);
         // 3.进行数据设置
         Members members =  new  Members();
         members.setUserName( "rita" );
         members.setUserPwd( "123456" );
         // 开始调用登录方法
         Retmsg retmsg = memberIFace.login(members);
         System.out.println( "Recive Msg:"  + retmsg.getMsg());
     }
}

具体业务实现类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package  com.ifree.serrpc.impl;
 
import  org.apache.avro.AvroRemoteException;
 
import  com.ifree.serrpc.builder.MemberIFace;
import  com.ifree.serrpc.builder.Members;
import  com.ifree.serrpc.builder.Retmsg;
 
/**
* 具体的业务处理类
* @author Administrator
*
*/
public  class  MemberIFaceImpl  implements  MemberIFace {
 
      final  String userName= "rita" ;
      final  String userPwd= "888888" ;
      /**
      * 登录业务处理
      */
      @Override
      public  Retmsg login(Members m)  throws  AvroRemoteException {
           //验证登录权限
           if (m.getUserName().equals(userName)&&m.getUserPwd().equals(userPwd)){
                return  new  Retmsg( "恭喜你,登录成功,欢迎进入AVRO测试环境。" );
           }
           return  new  Retmsg( "对不起,权限不足,不能登录。" );
      }
 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值