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中的异步写法。
异步就是当前程序正在执行,使用回调执行了另外一段代码,如果当前程序执行完了,就会结束,不会得到另一端代码的结果,如:
/*
* 查找指定用户名和密码的用户
* */
fun findUser(userName:String,pwd:String):String?{
val query=JsonObject().put("name",userName).put("pwd",pwd)
var user?=null
mongoClient.find("jtest",query,{res->
if (res.succeeded()){
val result=res.result()[]
if (!result.isEmpty){
user=User(result.getString("name"),result.getString("pwd"))
}
}
})
return user
}
上面的写法是错误的,因为vertx的mongo的find()方法使用了异步写法,在异步的方法块里面对外面的变量赋值,外面是接收不到的。
正确的写法应该是回调来接收结果。java中想要使用回调onDone需要写一个接口如Active,然后把这个接口作为参数传入方法,重写onDone来对结果进行处理。
而kotlin中的回调不需要重新写一个接口。它可以直接把过程作为对象传入参数,如下:onDone是一个类型为(参数为User,返回值为Void的过程)。可以看到findUser方法的结尾调用了onDone,并把保存后的user作为参数传递进去了。调用findUser方法的时候,我们就可以使用lambda表达式写出对传入onDone的参数user对象的处理。
/*
* 查找指定用户名和密码的用户
* */
fun findUser(userName:String,pwd:String, onDone:(User?) -> Unit){
val query=JsonObject().put("name",userName).put("pwd",pwd)
mongoClient.find("jtest",query,{res->
var user:User?=null
if (res.succeeded()){
val result=res.result()[]
if (!result.isEmpty){
user=User(result.getString("name"),result.getString("pwd"))
}
}
onDone.invoke(user)
})
}
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的异步有了更深的了解,回调函数可以传递,如下:
fun login(Param:JsonObject,onDone:(JsonObject)->Unit){
LoginService().login(Param, {req->
val request=req
onDone(req)
})
} //可以写成如下: fun login(Param:JsonObject,onDone:(JsonObject)->Unit){
LoginService().login(Param, onDone)
}
此外,如果反射要调用的函数里有回调,那么只需要先声明一个变量保存这个回调函数,再传入参数即可:
//回调函数
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)
最新文章
- select初始化添加option,通过标签给出回显值,由于回显值和初始化值option中有一个值重复,去重等问题!
- poj3461 字符串匹配 熟悉kmp算法第一题
- 再也不必当心我的密码了,多个SAP 客户端自动输入密码
- face mask in opencv
- 使用 Team Foundation 版本控制命令
- asp.net 实现对xml文件的 读取,添加,删除,修改
- SRM 599 DIV1
- Ecstore 2.0 报表显示空白
- Arcengine 开发,FeatureClass新增feature时“The Geometry has no z-value”或";The Geometry has null z-value";的解决方案
- hdu 4712 Hamming Distance bfs
- 教你pomeloclient包libpomelo增加cocos2d-x 3.0工程(Windows、Android、IOS平台)
- 5次Shift会触发粘滞键的妙用(转)
- Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询
- 移动端Bug管理工具——Bugtags
- ASP.NET MVC 实现AJAX跨域请求的两种方法
- 最近学习java时的记录
- 2个域名重定向到https域名
- Chart.js 與 ASP.NET MVC 整合應用
- docker学习------docker私有仓库的搭建
- hive高级数据类型