java分发_【Java】用注解实现分发器
在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】用注解实现分发器相关推荐
- autowired java配置_使用autowired注解怎么配置配置文件
展开全部 1. 使用Spring注解来注入属性e69da5e6ba9062616964757a686964616f31333363363434 1.1. 使用注解以前我们是怎样注入属性的 类的实现: ...
- java沙漏_(java)五大常用算法
算法一:分治法 基本概念1.把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题--直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并.2.分治策略是对于一个规模 ...
- webservice java教程_[Java教程]JAVA开发Webservice——JAXB
[Java教程]JAVA开发Webservice--JAXB 0 2016-01-19 17:00:04 JAXB(Java API for JAXB 可以实现Java对象与 下面来了解一下如何通过标 ...
- android java教程_[Java教程]Android开发快速入门
[Java教程]Android开发快速入门 0 2020-12-22 18:01:40 Xamarin.Android 应用程序剖析 以下屏幕截图列出了解决方案的内容. 下面是一个解决方案资源管理器, ...
- java 矩阵_(JAVA)计算机图形学与矩阵
(JAVA)计算机图形学与矩阵 平移 旋转 变比 一)矩阵 1)矩阵的乘法运算 矩阵是计算机图形学的重要工具. 计算机图形学要常常用到 矩阵乘法(矩阵与矩阵相乘). 矩阵(Aij)m*n 与矩阵(Bi ...
- java后门_@Java Web 程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码...
从数据库.redis取了些数据,做了一些运算后,没抛异常,但是就是结果不对 抛了个空指针异常,但是看代码,感觉没问题,是取出来就是空,还是中间什么函数把它改坏了 发现导致一个bug的原因是用了JVM缓 ...
- ie8不兼容java项目_[Java教程]ie8以下不兼容document.getElementsByName解决方法
[Java教程]ie8以下不兼容document.getElementsByName解决方法 0 2016-09-13 19:00:06 在IE8以认为只有文本标签才有name属性的,一些元素标签用d ...
- java切片_ java中一个极其强悍的新特性Stream详解(非常实用)
java8中有两个非常有名的改进,一个是Lambda表达式,一个是Stream.如果我们了解过函数式编程的话,都知道Stream真正把函数式编程的风格引入到了java中.这篇文章由简入繁逐步介绍Str ...
- java获取焦点_[Java教程]dialog获取焦点
[Java教程]dialog获取焦点 0 2014-09-25 18:00:41 弹出层是一个iframe openWindow: function (options) { var url = opt ...
- java 浅克隆_(Java)浅克隆与深克隆的区别
克隆,就是复制一个对象的副本,而克隆又分浅克隆和深克隆.浅克隆是指克隆得到的对象基本类型的值改变了,而源对象的值不会变.但如果被克隆对象引用类型的值改变了,那么源对象的值同样会改变,因为引用类型在栈内 ...
最新文章
- linux查看CPU利用率与负载,Linux CPU负载利用率统计
- hdu4784 不错的搜索( 买卖盐,要求整钱最多)
- 欧拉工程第57题:Square root convergents
- App设计灵感之十二组精美的机票预订App设计案例
- linux系统服务器可能被攻击的几种攻击方式
- C++primer第九章 顺序容器 9.3 顺序容器操作
- python标准库怎么用_Python常用标准库使用(一)
- 寻路机器人单片机程序示例_C51独立按键的识别示例程序
- mysql数据库表名批量改为小写,MySQL 批量修改表名
- jQuery如何退出each循环的?
- TableView Within Alert
- LINUX CENTOS 7 X86_64中开始菜单的编辑安装软件alacarte即可
- 现在大火的Web3是什么 web1 web2
- 基于中医药知识图谱智能问答(一)
- masm编译.asm文件报错fatal errorA1000: cannot open file
- 计算机网络华为路由器配置实验,华为路由器的配置实验
- html一键删除空白格,如何一次性删除空白行 word里的空白行怎么批量删除
- win0如何添加计算机用户,Win10系统如何添加来宾账户 win10添加来宾账户的方法
- 动态规划(练习题目)
- 华为又要给员工分红了!预计每股 1.61 元,网友:点赞任正非