kotlin和vertx和mongo写的一个服务器验证登陆功能(很简陋)

包结构长这个样子:


server包:(服务器相关配置)

  HttpServer:用ver.x创建了一个http服务器,把接收到的req请求传入RPCRequest中;

  RPCRequest:解析请求body内容,把信息保存为M(类名) A(方法名) P(参数),同时还拥有invoke()方法,根据m、a、p的数据用反射调用方法。

  RPCResponse:没写,用来保存响应信息的。

Manager包:(将所有需要被远程调用的方法保存到内容中,加快调用时遍历查询方法的响应速度)

  MethodManager:里面声明一个HashMap,value是KFunction<*>保存所有被@RPC1注解的方法,同时有addAllMethod()方法,用来保存当前类所有带@RPC1注解的方法。

  ControllerManager:用HashMap保存所有Controller类,value是KClass<*>,init中需要手动put添加controller类。

Service包:(提供业务方法,供调用)

  LoginService:提供业务解决逻辑的方法

Mongo包:(数据持久层,与数据库打交道,应该写成Dao层的)

  UserDao:用户集合的数据库操作。

(2017.7.27更新)

Log包:

  Loggin:封装了日志的信息

controller包:

  LoginController:请求响应被调用的方法


 2018.7.27更新:

  原来的版本有几个缺陷:

    ①没有使用vert.x的mongo,而使用了原生mongo的jdbc;

    ②对数据库的查询没有实现异步。

  ①刚开始使用了原生mongodb的jar包和mongoclient对象,但是这种方式没有用到vertx的异步,所以改为 io.vertx.ext.mongo.MongoClient 这个jar包。但是没有删除原来原生的mongodb包,就造成了一个bug。会在执行 val mongoClient = MongoClient.createNonShared(Main.vertx, config) 这条语句的时候报错:clusterListener can not be null。 删除原生mongodb的jar包就可以了。

  ②改成了vertx的mongo方式就是为了查询数据库的时候使用异步来提高查询效率。刚开始还是不理解kotlin中的异步写法。

  异步就是当前程序正在执行,使用回调执行了另外一段代码,如果当前程序执行完了,就会结束,不会得到另一端代码的结果,如:

 1 /*
 2     * 查找指定用户名和密码的用户
 3     * */
 4     fun findUser(userName:String,pwd:String):String?{
 5         val query=JsonObject().put("name",userName).put("pwd",pwd)
 6         var user?=null        
 7         mongoClient.find("jtest",query,{res->
 8             if (res.succeeded()){
 9                 val result=res.result()[0]
10                 if (!result.isEmpty){
11                     user=User(result.getString("name"),result.getString("pwd"))
12                 }
13             }
14         })
15         return user
16     }

上面的写法是错误的,因为vertx的mongo的find()方法使用了异步写法,在异步的方法块里面对外面的变量赋值,外面是接收不到的。

正确的写法应该是回调来接收结果。java中想要使用回调onDone需要写一个接口如Active,然后把这个接口作为参数传入方法,重写onDone来对结果进行处理。

而kotlin中的回调不需要重新写一个接口。它可以直接把过程作为对象传入参数,如下:onDone是一个类型为(参数为User,返回值为Void的过程)。可以看到findUser方法的结尾调用了onDone,并把保存后的user作为参数传递进去了。调用findUser方法的时候,我们就可以使用lambda表达式写出对传入onDone的参数user对象的处理。

 1 /*
 2     * 查找指定用户名和密码的用户
 3     * */
 4     fun findUser(userName:String,pwd:String, onDone:(User?) -> Unit){
 5         val query=JsonObject().put("name",userName).put("pwd",pwd)
 6         mongoClient.find("jtest",query,{res->
 7             var user:User?=null
 8             if (res.succeeded()){
 9                 val result=res.result()[0]
10                 if (!result.isEmpty){
11                     user=User(result.getString("name"),result.getString("pwd"))
12                 }
13             }
14             onDone.invoke(user)
15         })
16     }
val userDao = UserDao()
val user = userDao.findUser(userName, pwd) { user ->
       if (user == null) {
           var resp = "用户名或密码输入错误!!"
           println(resp)
       } else {
           var resp = "登陆成功!"
           println(resp)
      }
}

2018.7.27的再次更新:

加了注册功能,封装了一些方法,看起来更简洁了一些。对kotlin的异步有了更深的了解,回调函数可以传递,如下:

 1 fun login(Param:JsonObject,onDone:(JsonObject)->Unit){
 2         LoginService().login(Param, {req->
 3               val request=req
 4               onDone(req) 
 5         })
 6 }
 7 
 8 //可以写成如下:
 9 
10 fun login(Param:JsonObject,onDone:(JsonObject)->Unit){
11     LoginService().login(Param, onDone)
12 }        

此外,如果反射要调用的函数里有回调,那么只需要先声明一个变量保存这个回调函数,再传入参数即可:

//回调函数
val call: (JsonObject) -> Unit = {response->
    resp=response
    onDone(resp!!)
}

//得到类的引用M  KClass<*> 类型
var M = Main.ins.controllerManager.controllers.get(actions[0])
//得到方法的引用A KFunction<*> 类型
var A = M?.methods?.get(actions[1])
//反射,这里把回调函数作为参数传入,不能直接把大括号写在里面
A?.javaMethod?.invoke(conIns, JsonObject(),call)
原文地址:https://www.cnblogs.com/liumaowu/p/9372050.html