项目用的是 netty,需要再handler里面去处理请求.请过过来之后,原先的做法是直接做if else判断,但是每次加一个api,我就需要改一次常量定义和 handler,感觉太麻烦了.
我想的就是能不能用我们在php里的常用方法(用数组做api和controller的映射).尝试了下如下做法:
1.有一个hashMap里面存的就是一个 api => className.methodName.
2.然后在handler里接受到api的请求之后,获取该api对应的值.例如现在的请求api为user.get,然后以user.get为 key,找到其值为UserService.getInfo,然后再通过.分隔,再通过反射把请求的参数也带上.
这样就达到了控制器分发的效果.实际压测发现效率不降反升,我猜可能是因为用if else判断的时候要每个都判断一次,如果100个控制器,而现在需要找的又正好是最后一个控制器,那么就需要做100次判断.如果用hashMap就一次定位找到,所以速度反而快了?
先上之前的老代码:// handler code
Map objectMap = new HashMap();
//user.get
if(method.equals(Constants.MethodUserInfo)){
objectMap = UserService.getInfo(httpParams);
}
//misc.getVersion
if(method.equals(Constants.MethodMiscGetVersion)){
objectMap = MiscService.getVersion(httpParams);
}
//feed.getType
if(method.equals(Constants.MethodFeedGetType)){
objectMap = FeedService.getType(httpParams);
}
//msg.get
if(method.equals(Constants.MethodMsgGet)){
objectMap = MessageService.list(httpParams);
}
//feed.get
if(method.equals(Constants.MethodGetFeed)){
objectMap = FeedService.list(httpParams);
}
//uploadToken.get
if(method.equals(Constants.MethodUploadToken)){
objectMap = UploadService.uploadToken(httpParams);
}
//feed.add
if(method.equals(Constants.MethodFeedAdd)){
objectMap = FeedService.post(httpParams);
}
//sendWeChat
if(method.equals(Constants.MethodSendWeChat)){
objectMap = MessageService.sendWeChatToSomebody(httpParams);
}
//comment.add
if(method.equals(Constants.MethodComment)){
objectMap = CommentService.add(httpParams);
}
//fav.add
if(method.equals(Constants.MethodFavAdd)){
objectMap = FavService.add(httpParams);
}
//fav.del
if(method.equals(Constants.MethodFavDel)){
objectMap = FavService.del(httpParams);
}
//editInfo
if(method.equals(Constants.MethodEditUserInfo)){
objectMap = UserService.edit(httpParams);
}
//interest.add
if(method.equals(Constants.MethodInterestAdd)){
objectMap = TagService.add(httpParams);
}
//interest.del
if(method.equals(Constants.MethodInterestDel)){
objectMap = TagService.del(httpParams);
}
//register
if(method.equals(Constants.MethodRegister)){
objectMap = LoginService.register(httpParams);
}
//login
if(method.equals(Constants.MethodLogin)){
objectMap = LoginService.login(httpParams);
}
//logout
if(method.equals(Constants.MethodLogout)){
objectMap = LoginService.logout(httpParams);
}
JSONObject jsonObject = new JSONObject(objectMap);
json = jsonObject.toString();public class Constants {
public final static String MethodBase = "http://localhost:5000/?method=";
public final static String MethodUserInfo = "user.get";
public final static String MethodEditUserInfo = "editInfo";
public final static String MethodMiscGetVersion = "misc.getVersion";
public final static String MethodFeedGetType = "feed.getType";
public final static String MethodGetFeed = "feed.get";
public final static String MethodFeedAdd = "feed.add";
public final static String MethodMsgGet = "msgs.get";
public final static String MethodSendWeChat = "sendWechat";
public final static String MethodUploadToken = "uploadToken.get";
public final static String MethodComment = "comment.add";
public final static String MethodFavAdd = "fav.add";
public final static String MethodFavDel = "fav.del";
public final static String MethodInterestAdd = "interest.add";
public final static String MethodInterestDel = "interest.del";
public final static String MethodRegister = "register";
public final static String MethodLogin = "login";
public final static String MethodLogout = "logout";
}
因为习惯了在php的入口里做控制器分发,所以想java里面肯定能实现.吃饭的时候问下领导,领导说可以用反射,但是一般都是远程调用才去那么做,就像上面那样写if else就行了,没多少.
不管怎么说最后我还是改了.性能还不知道,先用着,反射的内容也没深入学习,等项目完了,再来复习.if(Constants.methodMap.containsKey(method)){
String classAndMethod = Constants.methodMap.get(method);
String[] classAndMethodArray = classAndMethod.split("\\.");
Class> className = null;
try {
className = Class.forName("me.topit.site.service."+classAndMethodArray[0]);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method methodName = null;
try {
methodName = className.getMethod(classAndMethodArray[1],HttpParams.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
Map objectMap = (Map) methodName.invoke(null,httpParams);
JSONObject jsonObject = new JSONObject(objectMap);
json = jsonObject.toString();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}else{
Map errorMsg = BaseService.error("该API不存在.");
JSONObject jsonObject = new JSONObject(errorMsg);
json = jsonObject.toString();
}
常量的定义我也换了:public class Constants {
public final static String MethodBase = "http://localhost:5000/?method=";
public final static HashMap methodMap = new HashMap(){{
// 系统类
put("misc.getVersion", "MiscService.getVersion");
// 用户类
put("user.get", "UserService.getInfo");
put("editInfo", "UserService.edit");
// feed类
put("feed.getType", "FeedService.getType");
put("feed.get", "FeedService.list");
put("feed.add", "FeedService.post");
// 消息类
put("msgs.get", "MessageService.list");
put("sendWechat", "MessageService.sendWeChatToSomebody");
// 上传类
put("uploadToken.get", "UploadService.uploadToken");
// 评论类
put("comment.add", "CommentService.add");
// 点赞类
put("fav.add", "FavService.add");
put("fav.del", "FavService.del");
// 兴趣标签类
put("interest.add", "TagService.add");
put("interest.del", "TagService.del");
// 注册类
put("register", "LoginService.register");
put("login", "LoginService.login");
put("logout", "LoginService.logout");
}};
}
我测试判断,发现除了第一次之外,之后的请求中都是修改为反射后的效率更高,没有看出效率受到影响.ab -c10 -n1000 http://localhost:5000/?method=user.get&id=1
Concurrency Level: 10
Time taken for tests: 1.278 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 81000 bytes
HTML transferred: 42000 bytes
// 没有用反射的情况,每秒可以处理1645.70个请求
Requests per second: 782.23 [#/sec] (mean)
Time per request: 12.784 [ms] (mean)
Requests per second: 1287.48 [#/sec] (mean)
Time per request: 7.767 [ms] (mean)
Requests per second: 1667.01 [#/sec] (mean)
Time per request: 5.999 [ms] (mean)
Requests per second: 1797.64 [#/sec] (mean)
Time per request: 5.563 [ms] (mean)
Requests per second: 2136.11 [#/sec] (mean)
Time per request: 4.681 [ms] (mean)
Requests per second: 1769.91 [#/sec] (mean)
Time per request: 5.650 [ms] (mean)
Requests per second: 2079.54 [#/sec] (mean)
Time per request: 4.809 [ms] (mean)
// 使用用反射的情况,每秒可以处理 1771.13 个请求
Requests per second: 728.11 [#/sec] (mean)
Time per request: 13.734 [ms] (mean)
Requests per second: 1318.63 [#/sec] (mean)
Time per request: 7.584 [ms] (mean)
Requests per second: 1833.21 [#/sec] (mean)
Time per request: 5.455 [ms] (mean)
Requests per second: 1818.62 [#/sec] (mean)
Time per request: 5.499 [ms] (mean)
Requests per second: 2075.64 [#/sec] (mean)
Time per request: 4.818 [ms] (mean)
Requests per second: 2238.91 [#/sec] (mean)
Time per request: 4.466 [ms] (mean)
Requests per second: 2384.78 [#/sec] (mean)
Time per request: 4.193 [ms] (mean)