在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

利用java的代理建立缓存

2016-12-20 13:13| 发布者: zhangjf| 查看: 400| 评论: 0

摘要: 背景: 为了实现组件的复用,几乎所有的项目都会调用一个通用的用户组件(org)。各系统和org之间是使用webservice技术进行通,主要是org提供了webservice业务接口。经过了一段时间的使用发现组件相当稳定 ...
背景:

为了实现组件的复用,几乎所有的项目都会调用一个通用的用户组件(org)。各系统和org之间是使用webservice技术进行通,主要是org提供了webservice业务接口。经过了一段时间的使用发现组件相当稳定,正常情况下几乎可以满足所有系统的要求。只是有一个问题比较突出就是当一个方法包含过多的webservice请求时还是会有性能问题,这个问题应该说是webservice的通病。所以这里提供一种解决方法,建立缓存机制。

分析: 首先建立缓存位置其实有两个选择,一是建立在org服务器端,二是建立在客户端。建立在org服务的话可以优化数据库查询的时间,建立在客户端的话可节省调用的时间+数据库查询的时间,所以效率上肯定更高,但是需要付出的代价是需要在每个调用系统中修改相应的代码。 其次建立缓存方式也有所不同,最简单的方式是直接添加一个支持缓存方法,譬如 findCacheUserByDeptId,但是这种方法的缺点也是需要修改过多的代码,所以这里我使用的是通过代理方式实现缓存。优点是只需要修改client的声明方式,无需修改具体调用的代码。
实现步骤:
1 建立一个代理类 新建 IOrgServiceCachePxy 继承InvocationHandler接口
2 实现接口的invoke(Object proxy, Method method, Object[] args) 方法 当被代理class对象的任何业务方法被调用时,这个方法就会被触发。而且这个方法获取这个业务方法的方法信息、参数信息,所以可以轻松实现对这个方法前置、后置操作。相关的缓存操作可以是在改方法中实现的,如果缓存方法比较多的话建议添加多个缓存实现方法,然后根据方法名称分别调用。
3 建立代理对象和实体对象的关联 使用java.lang.reflect.Proxy.newProxyInstance 方法 代理对象的完整代码
  1. package com.megait.orgv2.webservice.cache;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.InvocationTargetException;
  4. import java.lang.reflect.Method;
  5. import java.lang.reflect.Proxy;
  6. import com.megait.orgv2.webservice.client.model.ArrayOfDepartment;
  7. import com.megait.orgv2.webservice.client.model.ArrayOfUser;
  8. import com.megait.orgv2.webservice.client.model.Department;
  9. import com.megait.orgv2.webservice.client.model.User;
  10. public class IOrgServiceCachePxy implements InvocationHandler {
  11. private Object target;
  12. /**
  13. * 获取代理对象,必须是个实例(在这个对象的基础进行添加其它行为)
  14. * @param target
  15. * @return
  16. */
  17. public Object getProxyInstance(Object target){
  18. this.target = target;
  19. return Proxy.newProxyInstance(target.getClass().getClassLoader(),
  20. target.getClass().getInterfaces(), this);
  21. }
  22. /**
  23. * target 实例,被调用时会触发此方法
  24. * InvocationHandler接口的方法
  25. */
  26. public Object invoke(Object proxy, Method method, Object[] args)
  27. throws Throwable {
  28. Object result = null;
  29. //System.out.println(Thread.currentThread().getName() +": 进入IOrgServiceCachePxy。。。");
  30. if(method.getName().equals("findAllDepartment")){
  31. //System.out.println("args[0]:"+args[0]+",args:[1]"+args[1]+",args[2]:"+args[2]);
  32. result = findAllDepartment(method, args);
  33. }else if(method.getName().equals("findDeptByActDeptId")){
  34. // System.out.println("args[0]:"+args[0]+",args[1]:"+args[1]);
  35. result = findDeptByActDeptId(method, args);
  36. }else if(method.getName().equals("findUserByUserId")){
  37. result = findUserByUserId(method, args);
  38. }else if(method.getName().equals("findUserByDeptId")){
  39. result = findUserByDeptId(method, args);
  40. }else{ //非过滤条件
  41. result = method.invoke(target, args);
  42. }
  43. // System.out.println(Thread.currentThread().getName() +": 22222222222222222");
  44. // System.out.println("after target method...");
  45. return result;
  46. }
  47. // 获得所有的部门
  48. private Object findAllDepartment(Method method, Object[] args)
  49. throws IllegalAccessException, InvocationTargetException {
  50. Object result;
  51. // 只有符合参数要求的方法才会进行缓存处理(只对获取当前有效部门列表)
  52. if(args[0].equals("0") && args[1].equals("y") && args[2].equals(0)){
  53. // System.out.println(Thread.currentThread().getName() +": 进入IOrgServiceCachePxy。。。2");
  54. //System.out.println("方法可进行缓存");
  55. String key = "findAllDepartment_0_y_0";
  56. if(OrgCachePools.allDeptPools.containsKey(key)){
  57. //System.out.println("从缓存中获取"+key);
  58. return OrgCachePools.allDeptPools.get(key);
  59. }
  60. result = method.invoke(target, args);
  61. final ArrayOfDepartment arrayDept = (ArrayOfDepartment)result;
  62. OrgCachePools.allDeptPools.put(key, arrayDept);
  63. }else{
  64. //System.out.println(Thread.currentThread().getName() +": 进入IOrgServiceCachePxy。。。3");
  65. //System.out.println("不符合缓存条件");
  66. result = method.invoke(target, args);
  67. }
  68. return result;
  69. }
  70. // 获得部门对象 根据实体id
  71. private Object findDeptByActDeptId(Method method, Object[] args)
  72. throws IllegalAccessException, InvocationTargetException {
  73. Object result;
  74. // 只有符合参数要求的方法才会进行缓存处理(只对获取当前有效部门列表)
  75. if(args[1].equals(0) ){
  76. // System.out.println(Thread.currentThread().getName() +": 进入IOrgServiceCachePxy。。。2");
  77. //System.out.println("方法可进行缓存");
  78. String key = args[0]+"_0";
  79. if(OrgCachePools.deptPools.containsKey(key)){
  80. // System.out.println("从缓存中获取"+key);
  81. return OrgCachePools.deptPools.get(key);
  82. }
  83. result = method.invoke(target, args);
  84. if(result!=null){
  85. Department dept = (Department)result;
  86. OrgCachePools.deptPools.put(key, dept);
  87. }
  88. }else{
  89. //System.out.println(Thread.currentThread().getName() +": 进入IOrgServiceCachePxy。。。3");
  90. // System.out.println("方法参数不符");
  91. result = method.invoke(target, args);
  92. }
  93. return result;
  94. }
  95. // 获得用户对象
  96. private Object findUserByUserId(Method method, Object[] args)
  97. throws IllegalAccessException, InvocationTargetException {
  98. Object result;
  99. // 只有符合参数要求的方法才会进行缓存处理(只对获取当前有效部门列表)
  100. if(args[1].equals(0) ){
  101. // System.out.println(Thread.currentThread().getName() +": 进入IOrgServiceCachePxy。。。2");
  102. //System.out.println("方法可进行缓存");
  103. String key = args[0]+"_0";
  104. if(OrgCachePools.userPools.containsKey(key)){
  105. // System.out.println("从缓存中获取"+key);
  106. return OrgCachePools.userPools.get(key);
  107. }
  108. result = method.invoke(target, args);
  109. User dept = (User)result;
  110. OrgCachePools.userPools.put(key, dept);
  111. }else{
  112. //System.out.println(Thread.currentThread().getName() +": 进入IOrgServiceCachePxy。。。3");
  113. // System.out.println("方法参数不符");
  114. result = method.invoke(target, args);
  115. }
  116. return result;
  117. }
  118. // 获得用户对象
  119. private Object findUserByDeptId(Method method, Object[] args)
  120. throws IllegalAccessException, InvocationTargetException {
  121. Object result;
  122. // 只有符合参数要求的方法才会进行缓存处理(只对获取当前有效部门列表)
  123. if(args[1].equals("y") ){
  124. // System.out.println(Thread.currentThread().getName() +": 进入IOrgServiceCachePxy。。。2");
  125. //System.out.println("方法可进行缓存");
  126. String key = args[0]+"_y";
  127. if(OrgCachePools.deptUserPools.containsKey(key)){
  128. // System.out.println("从缓存中获取"+key);
  129. return OrgCachePools.deptUserPools.get(key);
  130. }
  131. result = method.invoke(target, args);
  132. ArrayOfUser userList = (ArrayOfUser)result;
  133. OrgCachePools.deptUserPools.put(key, userList);
  134. }else{
  135. //System.out.println(Thread.currentThread().getName() +": 进入IOrgServiceCachePxy。。。3");
  136. // System.out.println("方法参数不符");
  137. result = method.invoke(target, args);
  138. }
  139. return result;
  140. }
  141. }
复制代码

调用代码的差别
  1. // 原来的代码
  2. IOrgServiceClient client = new IOrgServiceClient();
  3. IOrgServicePortType service = client.getIOrgServiceHttpPort();
  4. ArrayOfUser userArr = service.findUserByDeptId(bgsVerid, "y");
  5. // 缓存代码
  6. IOrgServiceClient client = new IOrgServiceClient();
  7. IOrgServiceCachePxy proxy = new IOrgServiceCachePxy();
  8. cacheService = (IOrgServicePortType)proxy.getProxyInstance(client.getIOrgServiceHttpPort());
  9. ArrayOfUser userArr = service.findUserByDeptId(bgsVerid, "y");
复制代码

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-7-8 07:06

Copyright 2015-2025 djqfx

返回顶部