在C/S中,客户端会向服务器发出各种请求,而服务器就要根据请求做出对应的响应。
实际上就是客户机上执行某一个方法,将方法返回值,通过字节流的方式传输给服务器,服务器找到该请求对应的响应方法,并执行,将结果再次通过字节流的方式传输给客户机!
下面搭建一个简单的Request和Response分发器:
类标识的注解,只有带有该标识,才进行之后方法的扫描,否则不进行:
1 import java.lang.annotation.ElementType; 2 import java.lang.annotation.Retention; 3 import java.lang.annotation.RetentionPolicy; 4 import java.lang.annotation.Target; 5 6 @Retention(RetentionPolicy.RUNTIME) 7 @Target(ElementType.TYPE) 8 public @interface Service { 9 }
方法的注解, 必须对注解中的action赋值,往后我们是要将action的值作为map中的键:
1 import java.lang.annotation.ElementType; 2 import java.lang.annotation.Retention; 3 import java.lang.annotation.RetentionPolicy; 4 import java.lang.annotation.Target; 5 6 @Retention(RetentionPolicy.RUNTIME) 7 @Target(ElementType.METHOD) 8 public @interface Actioner { 9 String action(); 10 }
方法参数的注解,同样要对其name赋值,为了以后能够找到对应的参数,完成赋值:
1 import java.lang.annotation.ElementType; 2 import java.lang.annotation.Retention; 3 import java.lang.annotation.RetentionPolicy; 4 import java.lang.annotation.Target; 5 6 @Retention(RetentionPolicy.RUNTIME) 7 @Target(ElementType.PARAMETER) 8 public @interface AParameter { 9 String name(); 10 }
我们需要将方法抽象成一个类,封装起来:
1 import java.lang.reflect.Method; 2 import java.lang.reflect.Parameter; 3 import java.util.List; 4 5 public class ActionDefination { 6 private Class<?> klass; // 该方法所对应的类 7 private Object object; // 执行该方法的对象 8 private Method method; // 该方法 9 private List<Parameter> paramerterList; // 该方法的所有参数 10 11 protected ActionDefination(Class<?> klass, Object object, Method method, List<Parameter> paramerterList) { 12 this.klass = klass; 13 this.object = object; 14 this.method = method; 15 this.paramerterList = paramerterList; 16 } 17 18 protected Class<?> getKlass() { 19 return klass; 20 } 21 22 protected Object getObject() { 23 return object; 24 } 25 26 protected Method getMethod() { 27 return method; 28 } 29 30 protected List<Parameter> getParamerterList() { 31 return paramerterList; 32 } 33 34 }
所有准备工作都做好了,我们就需要通过包扫描的方式,找到带有Service 注解的类,然后找到其中带有Actioner 注解的方法,并且得到带有注解的所有参数,若其某一参数没有带注解,则应该异常处理!
扫描包下符合要求的所有内容,最后形成一张map
1 import java.lang.reflect.Method; 2 import java.lang.reflect.Parameter; 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 8 public class ActionFactory { 9 private static final Map<String, ActionDefination> actionDefinationMap = new HashMap<String, ActionDefination>(); 10 11 // 单例模式 12 private ActionFactory() { 13 } 14 public static ActionFactory newInstance() { 15 return creatNewInstance.actionFactory; 16 } 17 18 private static class creatNewInstance { 19 private static final ActionFactory actionFactory = new ActionFactory(); 20 } 21 22 // 通过类,扫描其所在包下的所有文件 23 public void scanAction(Class<?> klass) { 24 scanAction(klass.getPackage().getName()); 25 } 26 27 // 通过包名称,扫描其下所有文件 28 public void scanAction(String packageName) { 29 // 包扫描,在我的上一篇博客有该方法的实现 30 new PackageScanner() { 31 32 @Override 33 public void dealClass(Class<?> klass) { 34 // 只处理带有Service注解的类 35 if (!klass.isAnnotationPresent(Service.class)) { 36 return; 37 } 38 try { 39 // 直接由反射机制产生一个对象,将其注入 40 Object object = klass.newInstance(); 41 // 扫描改类下的所有方法 42 scanMethod(klass, object); 43 } catch (Exception e) { 44 e.printStackTrace(); 45 } 46 } 47 }.scanPackage(packageName); 48 } 49 50 // 通过对象,扫描其所有方法 51 public void scanAction(Object object) { 52 try { 53 scanMethod(object.getClass(), object); 54 } catch (Exception e) { 55 e.printStackTrace(); 56 } 57 } 58 59 private void scanMethod(Class<?> klass, Object object) throws Exception { 60 // 得到所有方法 61 Method[] methods = klass.getDeclaredMethods(); 62 63 // 遍历所有方法,找到带有Actioner注解的方法,并得到action的值 64 for (Method method : methods) { 65 if (!method.isAnnotationPresent(Actioner.class)) { 66 continue; 67 } 68 Actioner actioner = method.getAnnotation(Actioner.class); 69 String action = actioner.action(); 70 71 // 判断action是否已经定义 72 if (actionDefinationMap.get(action) != null) { 73 throw new ActionHasDefineException("方法" + action + "已定义!"); 74 } 75 76 // 得到所有参数,并判断参数是否满足要求 77 Parameter[] parameters = method.getParameters(); 78 List<Parameter> parameterList = new ArrayList<Parameter>(); 79 for (int i = 0; i < parameters.length; i++) { 80 Parameter parameter = parameters[i]; 81 if (!parameters[i].isAnnotationPresent(AParameter.class)) { 82 throw new MethodParameterNotDefineException("第" + (i+1) + "个参数未定义!"); 83 } 84 85 parameterList.add(parameter); 86 } 87 // 将得到的结果添加到map中 88 addActionDefination(action, klass, object, method, parameterList); 89 } 90 } 91 92 private void addActionDefination(String action, Class<?> klass, Object object, Method method, List<Parameter> parameterList) { 93 ActionDefination actionDefination = new ActionDefination(klass, object, method, parameterList); 94 actionDefinationMap.put(action, actionDefination); 95 } 96 97 protected ActionDefination getActionDefination(String action) { 98 return actionDefinationMap.get(action); 99 } 100 101 }
上述的ActionFactory可以帮助我们扫描到包下所有符合要求的方法,接下来就是通过传递参数执行这些方法。
要注意,这套工具的出发点是搭载在网络上,所以传递的参数就只能是字符串或者字节流的形式,所以,我们应该对传递的参数进行处理,将其生成能供我们识别的形式。
这里我们将参数转换为字符串的形式,我会用到gson,方便我们将对象转换为gson字符串:
1 import java.util.HashMap; 2 import java.util.Map; 3 4 import com.google.gson.Gson; 5 import com.google.gson.GsonBuilder; 6 7 public class ArgumentMaker { 8 // 注解AParameter中name的值 + 参数对象转换成的gson字符串所形成的map 9 private Map<String, String> argumentMap; 10 private Gson gson; 11 12 public ArgumentMaker() { 13 gson = new GsonBuilder().create(); 14 argumentMap = new HashMap<String, String>(); 15 } 16 17 // 其name就是注解AParameter中name的值,value就是参数的具体值 18 public ArgumentMaker add(String name, Object value) { 19 // 通过gson将参数对象转换为gson字符串 20 argumentMap.put(name, gson.toJson(value)); 21 return this; 22 } 23 24 // 将得到的name + 参数对象转换成的gson字符串map再次转换成gson字符串,以便于进行传输 25 public String toOgnl() { 26 if (argumentMap.isEmpty()) { 27 return null; 28 } 29 30 return gson.toJson(argumentMap); 31 } 32 33 }
接下来就是处理具体的action
1 import java.lang.reflect.Method; 2 import java.lang.reflect.Parameter; 3 import java.lang.reflect.Type; 4 import java.util.List; 5 import java.util.Map; 6 7 import com.google.gson.Gson; 8 import com.google.gson.GsonBuilder; 9 import com.google.gson.reflect.TypeToken; 10 11 public class Addition { 12 private static final Gson gson; 13 private static final Type type; 14 15 static { 16 gson = new GsonBuilder().create(); 17 // 可以得到带有泛型的map类型 18 type = new TypeToken<Map<String, String>>(){}.getType(); 19 } 20 21 public String doRequest(String action, String parameter) throws Exception { 22 ActionDefination ad = ActionFactory.newInstance().getActionDefination(action); 23 24 if (ad == null) { 25 throw new ActionNotDefineException("方法" + action + "未定义!"); 26 } 27 28 Object object = ad.getObject(); 29 Method method = ad.getMethod(); 30 31 Object[] parameters = getParameterArr(parameter, ad.getParamerterList()); 32 Object result = method.invoke(object, parameters); 33 34 return gson.toJson(result); 35 } 36 37 private Object[] getParameterArr(String parameterString, List<Parameter> parameterList) { 38 Object[] results = new Object[parameterList.size()]; 39 // 将字符串形式的参数,转换成map 40 Map<String, String> parameterStringMap = gson.fromJson(parameterString, type); 41 42 int index = 0; 43 for (Parameter parameter : parameterList) { 44 // 得到参数的注解AParameter中name的值 45 String key = parameter.getAnnotation(AParameter.class).name(); 46 47 // 以name的值为键,找到参数map中value,再通过gson将其从字符串转换成具体的对象 48 Object value = gson.fromJson(parameterStringMap.get(key), 49 // 得到参数的具体类型 50 parameter.getParameterizedType()); 51 52 results[index++] = value; 53 } 54 55 return results; 56 }
演示如何使用
1 @Service 2 public class Demo { 3 4 @Actioner(action="one") 5 public void fun() { 6 System.out.println("执行无参的fun方法"); 7 } 8 9 @Actioner(action="two") 10 public void fun(@AParameter(name="1")int parameter) { 11 System.out.println("执行单参的fun方法: parameter = " + parameter); 12 } 13 14 @Actioner(action="three") 15 public void fun(@AParameter(name="1")int one, 16 @AParameter(name="2")String two, 17 @AParameter(name="3")boolean three) { 18 System.out.println("执行三参的fun方法: one = " + one + " two = " + two + " three = " + three); 19 } 20 21 private static class Student { 22 private String name; 23 private int age; 24 private boolean sex; 25 26 private Student(String name, int age, boolean sex) { 27 this.name = name; 28 this.age = age; 29 this.sex =sex; 30 } 31 32 @Override 33 public String toString() { 34 return "name = " + name + ", age = " + age + ", sex = " + (sex ? "男" : "女"); 35 } 36 } 37 38 @Actioner(action="four") 39 public void fun(@AParameter(name="1")Student student) { 40 System.out.println("执行复杂类型参数的fun方法 :" + student); 41 } 42 43 public static void main(String[] args) throws Exception { 44 // 扫描包,这里直接扫描Demo所在的包 45 ActionFactory.newInstance().scanAction(Demo.class); 46 47 Addition addition = new Addition(); 48 49 addition.doRequest("one", null); 50 51 addition.doRequest("two", new ArgumentMaker() 52 .add("1", 3) 53 .toOgnl()); 54 55 addition.doRequest("three",new ArgumentMaker() 56 .add("3", true) 57 .add("1", 3) 58 .add("2", "这是第二个参数") 59 .toOgnl()); 60 61 Student student = new Student("小明", 15, true); 62 addition.doRequest("four", new ArgumentMaker() 63 .add("1", student) 64 .toOgnl()); 65 } 66 67 }
运行结果