• 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)
  • 相关阅读:
    如何计算二进制数的取值范围
    理解网络请求中的连接超时和读取超时
    两行代码玩转Spring Data排序和分页
    面试必问Elasticsearch倒排索引原理
    你知道Java的四种引用类型吗
    抛弃配置后的Spring终极教程
    Python学习第二篇
    Python
    关于always块内for循环的执行方式
    三态门实现“一读多写”总线结构
  • 原文地址:https://www.cnblogs.com/liumaowu/p/9372050.html
Copyright © 2020-2023  润新知