在C/S中,客户端会向服务器发出各种请求,而服务器就要根据请求做出对应的响应。

实际上就是客户机上执行某一个方法,将方法返回值,通过字节流的方式传输给服务器,服务器找到该请求对应的响应方法,并执行,将结果再次通过字节流的方式传输给客户机!

下面搭建一个简单的Request和Response分发器:

类标识的注解,只有带有该标识,才进行之后方法的扫描,否则不进行:

1 importjava.lang.annotation.ElementType;2 importjava.lang.annotation.Retention;3 importjava.lang.annotation.RetentionPolicy;4 importjava.lang.annotation.Target;5

6 @Retention(RetentionPolicy.RUNTIME)7 @Target(ElementType.TYPE)8 public @interfaceService {9 }

方法的注解, 必须对注解中的action赋值,往后我们是要将action的值作为map中的键:

1 importjava.lang.annotation.ElementType;2 importjava.lang.annotation.Retention;3 importjava.lang.annotation.RetentionPolicy;4 importjava.lang.annotation.Target;5

6 @Retention(RetentionPolicy.RUNTIME)7 @Target(ElementType.METHOD)8 public @interfaceActioner {9 String action();10 }

方法参数的注解,同样要对其name赋值,为了以后能够找到对应的参数,完成赋值:

1 importjava.lang.annotation.ElementType;2 importjava.lang.annotation.Retention;3 importjava.lang.annotation.RetentionPolicy;4 importjava.lang.annotation.Target;5

6 @Retention(RetentionPolicy.RUNTIME)7 @Target(ElementType.PARAMETER)8 public @interfaceAParameter {9 String name();10 }

我们需要将方法抽象成一个类,封装起来:

1 importjava.lang.reflect.Method;2 importjava.lang.reflect.Parameter;3 importjava.util.List;4

5 public classActionDefination {6 private Class> klass;      //该方法所对应的类

7 private Object object; //执行该方法的对象

8 private Method method;       //该方法

9 private List paramerterList; //该方法的所有参数

10

11 protected ActionDefination(Class> klass, Object object, Method method, ListparamerterList) {12 this.klass =klass;13 this.object =object;14 this.method =method;15 this.paramerterList =paramerterList;16 }17

18 protected Class>getKlass() {19 returnklass;20 }21

22 protectedObject getObject() {23 returnobject;24 }25

26 protectedMethod getMethod() {27 returnmethod;28 }29

30 protected ListgetParamerterList() {31 returnparamerterList;32 }33

34 }

所有准备工作都做好了,我们就需要通过包扫描的方式,找到带有Service 注解的类,然后找到其中带有Actioner 注解的方法,并且得到带有注解的所有参数,若其某一参数没有带注解,则应该异常处理!

扫描包下符合要求的所有内容,最后形成一张map

1 importjava.lang.reflect.Method;2 importjava.lang.reflect.Parameter;3 importjava.util.ArrayList;4 importjava.util.HashMap;5 importjava.util.List;6 importjava.util.Map;7

8 public classActionFactory {9 private static final Map actionDefinationMap = new HashMap();10

11 //单例模式

12 privateActionFactory() {13 }14 public staticActionFactory newInstance() {15 returncreatNewInstance.actionFactory;16 }17

18 private static classcreatNewInstance {19 private static final ActionFactory actionFactory = newActionFactory();20 }21

22 //通过类,扫描其所在包下的所有文件

23 public void scanAction(Class>klass) {24 scanAction(klass.getPackage().getName());25 }26

27 //通过包名称,扫描其下所有文件

28 public voidscanAction(String packageName) {29 //包扫描,在我的上一篇博客有该方法的实现

30 newPackageScanner() {31

32 @Override33 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 voidscanAction(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) throwsException {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 parameterList = new ArrayList();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, ListparameterList) {93 ActionDefination actionDefination = newActionDefination(klass, object, method, parameterList);94 actionDefinationMap.put(action, actionDefination);95 }96

97 protectedActionDefination getActionDefination(String action) {98 returnactionDefinationMap.get(action);99 }100

101 }

上述的ActionFactory可以帮助我们扫描到包下所有符合要求的方法,接下来就是通过传递参数执行这些方法。

要注意,这套工具的出发点是搭载在网络上,所以传递的参数就只能是字符串或者字节流的形式,所以,我们应该对传递的参数进行处理,将其生成能供我们识别的形式。

这里我们将参数转换为字符串的形式,我会用到gson,方便我们将对象转换为gson字符串:

1 importjava.util.HashMap;2 importjava.util.Map;3

4 importcom.google.gson.Gson;5 importcom.google.gson.GsonBuilder;6

7 public classArgumentMaker {8 //注解AParameter中name的值 + 参数对象转换成的gson字符串所形成的map

9 private MapargumentMap;10 privateGson gson;11

12 publicArgumentMaker() {13 gson = newGsonBuilder().create();14 argumentMap = new HashMap();15 }16

17 //其name就是注解AParameter中name的值,value就是参数的具体值

18 publicArgumentMaker 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 publicString toOgnl() {26 if(argumentMap.isEmpty()) {27 return null;28 }29

30 returngson.toJson(argumentMap);31 }32

33 }

接下来就是处理具体的action

1 importjava.lang.reflect.Method;2 importjava.lang.reflect.Parameter;3 importjava.lang.reflect.Type;4 importjava.util.List;5 importjava.util.Map;6

7 importcom.google.gson.Gson;8 importcom.google.gson.GsonBuilder;9 importcom.google.gson.reflect.TypeToken;10

11 public classAddition {12 private static finalGson gson;13 private static finalType type;14

15 static{16 gson = newGsonBuilder().create();17 //可以得到带有泛型的map类型

18 type = new TypeToken>(){}.getType();19 }20

21 public String doRequest(String action, String parameter) throwsException {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 returngson.toJson(result);35 }36

37 private Object[] getParameterArr(String parameterString, ListparameterList) {38 Object[] results = newObject[parameterList.size()];39 //将字符串形式的参数,转换成map

40 Map 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 returnresults;56 }

演示如何使用

1 @Service2 public classDemo {3

4 @Actioner(action="one")5 public voidfun() {6 System.out.println("执行无参的fun方法");7 }8

9 @Actioner(action="two")10 public void fun(@AParameter(name="1")intparameter) {11 System.out.println("执行单参的fun方法: parameter = " +parameter);12 }13

14 @Actioner(action="three")15 public void fun(@AParameter(name="1")intone,16 @AParameter(name="2")String two,17 @AParameter(name="3")booleanthree) {18 System.out.println("执行三参的fun方法: one = " + one + " two = " + two + " three = " +three);19 }20

21 private static classStudent {22 privateString name;23 private intage;24 private booleansex;25

26 private Student(String name, int age, booleansex) {27 this.name =name;28 this.age =age;29 this.sex =sex;30 }31

32 @Override33 publicString 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) throwsException {44 //扫描包,这里直接扫描Demo所在的包

45 ActionFactory.newInstance().scanAction(Demo.class);46

47 Addition addition = newAddition();48

49 addition.doRequest("one", null);50

51 addition.doRequest("two", newArgumentMaker()52 .add("1", 3)53 .toOgnl());54

55 addition.doRequest("three",newArgumentMaker()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", newArgumentMaker()63 .add("1", student)64 .toOgnl());65 }66

67 }

运行结果

java分发_【Java】用注解实现分发器相关推荐

  1. autowired java配置_使用autowired注解怎么配置配置文件

    展开全部 1. 使用Spring注解来注入属性e69da5e6ba9062616964757a686964616f31333363363434 1.1. 使用注解以前我们是怎样注入属性的 类的实现: ...

  2. java沙漏_(java)五大常用算法

    算法一:分治法 基本概念1.把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题--直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并.2.分治策略是对于一个规模 ...

  3. webservice java教程_[Java教程]JAVA开发Webservice——JAXB

    [Java教程]JAVA开发Webservice--JAXB 0 2016-01-19 17:00:04 JAXB(Java API for JAXB 可以实现Java对象与 下面来了解一下如何通过标 ...

  4. android java教程_[Java教程]Android开发快速入门

    [Java教程]Android开发快速入门 0 2020-12-22 18:01:40 Xamarin.Android 应用程序剖析 以下屏幕截图列出了解决方案的内容. 下面是一个解决方案资源管理器, ...

  5. java 矩阵_(JAVA)计算机图形学与矩阵

    (JAVA)计算机图形学与矩阵 平移 旋转 变比 一)矩阵 1)矩阵的乘法运算 矩阵是计算机图形学的重要工具. 计算机图形学要常常用到 矩阵乘法(矩阵与矩阵相乘). 矩阵(Aij)m*n 与矩阵(Bi ...

  6. java后门_@Java Web 程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码...

    从数据库.redis取了些数据,做了一些运算后,没抛异常,但是就是结果不对 抛了个空指针异常,但是看代码,感觉没问题,是取出来就是空,还是中间什么函数把它改坏了 发现导致一个bug的原因是用了JVM缓 ...

  7. ie8不兼容java项目_[Java教程]ie8以下不兼容document.getElementsByName解决方法

    [Java教程]ie8以下不兼容document.getElementsByName解决方法 0 2016-09-13 19:00:06 在IE8以认为只有文本标签才有name属性的,一些元素标签用d ...

  8. java切片_ java中一个极其强悍的新特性Stream详解(非常实用)

    java8中有两个非常有名的改进,一个是Lambda表达式,一个是Stream.如果我们了解过函数式编程的话,都知道Stream真正把函数式编程的风格引入到了java中.这篇文章由简入繁逐步介绍Str ...

  9. java获取焦点_[Java教程]dialog获取焦点

    [Java教程]dialog获取焦点 0 2014-09-25 18:00:41 弹出层是一个iframe openWindow: function (options) { var url = opt ...

  10. java 浅克隆_(Java)浅克隆与深克隆的区别

    克隆,就是复制一个对象的副本,而克隆又分浅克隆和深克隆.浅克隆是指克隆得到的对象基本类型的值改变了,而源对象的值不会变.但如果被克隆对象引用类型的值改变了,那么源对象的值同样会改变,因为引用类型在栈内 ...

最新文章

  1. linux查看CPU利用率与负载,Linux CPU负载利用率统计
  2. hdu4784 不错的搜索( 买卖盐,要求整钱最多)
  3. 欧拉工程第57题:Square root convergents
  4. App设计灵感之十二组精美的机票预订App设计案例
  5. linux系统服务器可能被攻击的几种攻击方式
  6. C++primer第九章 顺序容器 9.3 顺序容器操作
  7. python标准库怎么用_Python常用标准库使用(一)
  8. 寻路机器人单片机程序示例_C51独立按键的识别示例程序
  9. mysql数据库表名批量改为小写,MySQL 批量修改表名
  10. jQuery如何退出each循环的?
  11. TableView Within Alert
  12. LINUX CENTOS 7 X86_64中开始菜单的编辑安装软件alacarte即可
  13. 现在大火的Web3是什么 web1 web2
  14. 基于中医药知识图谱智能问答(一)
  15. masm编译.asm文件报错fatal errorA1000: cannot open file
  16. 计算机网络华为路由器配置实验,华为路由器的配置实验
  17. html一键删除空白格,如何一次性删除空白行 word里的空白行怎么批量删除
  18. win0如何添加计算机用户,Win10系统如何添加来宾账户 win10添加来宾账户的方法
  19. 动态规划(练习题目)
  20. 华为又要给员工分红了!预计每股 1.61 元,网友:点赞任正非

热门文章

  1. html访问共享文件夹,教大家如何通过IP地址访问共享文件夹
  2. 无人车之美——技术要点速览
  3. IT学习网站,各大主流网站
  4. 世界前五大IT咨询公司
  5. MySQL 清除表空间碎片
  6. PAT --- 1055.集体照 (25 分)
  7. 二元函数偏导数公式_偏导数计算公式大全
  8. shiro原理简介说明
  9. 安卓第三方登录之微信登录(图文详解)
  10. http 高级配置 虚拟主机,https 编译安装