kotlin和vertx和mongo寫的一個服務器驗證登錄功能(很簡陋)

包結構長這個樣子:java

 


 

server包:(服務器相關配置)mongodb

  HttpServer:用ver.x建立了一個http服務器,把接收到的req請求傳入RPCRequest中;數據庫

  RPCRequest:解析請求body內容,把信息保存爲M(類名) A(方法名) P(參數),同時還擁有invoke()方法,根據m、a、p的數據用反射調用方法。服務器

  RPCResponse:沒寫,用來保存響應信息的。異步

Manager包:(將全部須要被遠程調用的方法保存到內容中,加快調用時遍歷查詢方法的響應速度)函數

  MethodManager:裏面聲明一個HashMap,value是KFunction<*>保存全部被@RPC1註解的方法,同時有addAllMethod()方法,用來保存當前類全部帶@RPC1註解的方法。spa

  ControllerManager:用HashMap保存全部Controller類,value是KClass<*>,init中須要手動put添加controller類。日誌

Service包:(提供業務方法,供調用)code

  LoginService:提供業務解決邏輯的方法server

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)
相關文章
相關標籤/搜索