包結構長這個樣子: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)