java分发器 及(注解 + 反射机制)—————— 开开开山怪

2024-02-07 07:48

本文主要是介绍java分发器 及(注解 + 反射机制)—————— 开开开山怪,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

java分发器 及 (注解 + 反射机制)

引 入:

在C/S框架应用中,当应用层通过点击界面的按钮进行资源的请求的时候,请求的背后代码的实现实际上会自动构成一系列的requst信息请求,由C/S框架内部的communcation层进行消息的发送,服务器通过解析requst请求获取到action(希望服务器端做出的响应)来调用已经配置好的对应的action的方法来进行请求的响应工作,当然这些方法的调用是通过反射机制类调用的。

对于服务器来说只用做一件事请就是,解析requst获取到action,然后自动调用action对应的方法,这就是我所理解的分发。

那上边我可以总结出两个关键字:1.配置2.反射调用(分发过程)

配 置:

先说配置问题,这应该是针对引用C/S框架的编程者来说的,因为采用C/S框架来进行开发,提供给应用者的一些请求功能和对应响应这些请求的方法是相辅相成的。现在我举个栗子,如果编程者提供给用户登录的功能,那对应就会有login方法作为配置文件的方法,当然文件的配置也很有讲究。

下面我给出配置方法。
在这里插入图片描述
这是我所配置的类,在这个类中包含了三个注解,我来一一说明。

1.classAction注解:
这个注解是在类上进行的,主要是为了方便我们识别这个类是我们需要扫描的类,因为这个类所包含的方法就是专门处理请求响应的。我们扫描到这个类,才对里边的方法进行收集,到最终供服务器完成响应的时候调用这些方法来实现。

2.actionMethod注解
这个注解上有对应的值,事实上拥有这些注解的方法才值得我们被扫描,并且注解上的值对应着我们的方法名称,每扫描一个这个注解的方法,我们便用一个classDefination来封装(classDefination这个类下面马上说到),并且利用classFactory类形成一个map<String,classDefination>, map中的键为String,事实上就是方法注解上对应的值(也可以说这个值就是这个方法的标志),map中的值就是一个个封装方法的classDefination。

那为什么要这样封装并形成一个map呢???

原因是这样,我们进行这样的配置并采用map来进行收集,为了服务器在响应请求的时候可以直接从requst请求中解析出action(action事实上和方法上注解的值是相对应的,因为我说过了,编程者写一个action,那它自然知道对应哪个方法,方法的注解的值当然和action是一一对应),根据action在map中找到对应的键,并且得到对应action方法的classDefination对象。因为classDefination类中的成员包括method,当然可以采用method.invoke()反射机制的方法来调用该方法实现响应操作。

3.actionPara注解
这个注解有意思了,因为method.invoke()事实上是需要参数的,一个参数就是该方法所在的类的对象,还有一个就是该方法的真实参数的一个数组。
这个注解是在参数上的,那必然是辅助method.invoke()这个方法的,下面我会详细说。

先给出上面我说的classDefination类和classFactory吧,不然你们还不知道咋回事儿呢。

classDefination类

public class classDefination {private Class<?> className;private Method method;private Object object;public Class<?> getClassName() {return className;}public void setClassName(Class<?> className) {this.className = className;}public Method getMethod() {return method;}public void setMethod(Method method) {this.method = method;}public Object getObject() {return object;}public void setObject(Object object) {this.object = object;}
}
classFactory类
public class classFactory {private static final Map<String, classDefination> map = new HashMap<String, classDefination>();public classFactory() {}public static void parserAnno(String packetName) { new PackageScanner() {   @Overridepublic void dealClass(Class<?> klass) {//通过包扫描到这种的类,循环分析每一个类if (klass.isAnnotationPresent(classAction.class)) {//如果类有该注解try {Object object =  klass.newInstance();Method[] method = klass.getDeclaredMethods();      for (Method one : method) {if (one.isAnnotationPresent(actionMethod.class)) {//总结当前的房的的一套classDefinationclassDefination cdf = new classDefination();actionMethod am = one.getAnnotation(actionMethod.class);cdf.setObject(object);cdf.setMethod(one);cdf.setClassName(klass);map.put(am.methodName(), cdf);         }}     } catch (Exception e) {   e.printStackTrace();}     }   }}.scanPackage(packetName); }public static Map<String, classDefination> getMap() {return map;}public static classDefination getByKey(String methodName) {System.out.println(map);return map.get(methodName);}}

分发开始了:

前面我说过了,既然编程者提供了功能,那就会有自己针对功能请求相应的响应功能的方法。我采用一个 登陆功能(相当于用户端的某一个请求)举个栗子,并且以下的内容采用登陆进行说明。

用户请求登陆,在登陆请求背后的代码事实上就是由C/S框架的cilent层requst()方法进行请求的发送,然后通过communcation层将请求传送给服务器。

图一

在这里插入图片描述

图二在这里插入图片描述

requst()实际上发送的内容有三个部分:
1.REQUST 这是C/S内部用来识别并且处理requst请求的标志,
2.action 这是用户真正的请求,例如此时的action = login
3.content 这是用来请求响应所需要的条件,此时的content 是由 userName:XXXX passWord:XXXX 组成的一个字符串,此时的 userName:XXXX passWord:XXXX是由makePar类来进行包装的,这里的 userName 和 passWord 其实对应到上面我们配置方法的参数名称。

这三部分用Message类来进行包装,然后转化为字符串交给服务器,服务器根据字符串反解析成Message类型,并从中获取到对应的command = REQUST,在这个REQUST的switch case下就真正的开始进行分发了。

图三

在这里插入图片描述

此时dealAction类出现了,这个类就是我们专门处理响应配置方法的类,因为在Message中我们还能得到 actioncontent ,这是这两个值就作为dealAction 方法的参数。

dealAction这个类中干的事情就很明确了,就是通过action在我们之前准备好的map中得到对应的classDefinition,从classDefinition中得到method成员和object成员,此时就只需要通过method.invoke(object, object[ ]), 来进行反射调用我们配置好的方法,invoke的第二个参数就是方法所需要的真正参数的数组,这就是为什么之前的 actionPara注解 存在的原因了。因为我们dealAction传进来的参数content是一个字符串,我们只有将这个字符串转化成真正的方法参数(具体转化过程及为什么要存在actionPara注解请阅读 Google中Gson的巧妙使用)就可以可以反射机制调用方法进行响应的操作。

public interface IdealAction {String deal(String action, String text) throws Exception ;}
public class dealAction implements IdealAction{private static final Gson gson = new GsonBuilder().create();public dealAction() {}private Object[] getParaValues(Method method, String para) throws Exception {Parameter[] paras = method.getParameters();//根据参数个数构造真实参数的数组if(paras.length <= 0) {return new Object[] {};}Object[] realParas = new Object[paras.length];makePar mp = new makePar(para);//会产生一个map,将para分解成键值对的形式for (int i = 0; i < paras.length; i++) {Parameter p = paras[i];if (!p.isAnnotationPresent(actionPara.class)) {throw new Exception("第" + (i + 1 ) + "个参数没有注解");}actionPara at = p.getAnnotation(actionPara.class);String name = at.paraName();Type tp = p.getParameterizedType();realParas[i] = mp.getParaValue(name, tp);}return realParas;}@Overridepublic String deal(String action, String text) throws Exception {//在这之前应该得到相应的classFactory的信息classDefination cdf = classFactory.getByKey(action);if (cdf == null) {throw new Exception("action" + (action) + "未定义");}//通过cdf可以知道参数的名称和参数的类型,可以对应传递过来的字符串,通过名称找到对应的键值//并且通过类型将相应的键值转化成真正的值进行方法的调用Method method = cdf.getMethod(); Object result = method.invoke(cdf.getObject(), getParaValues(method, text));return gson.toJson(result);}}

这篇关于java分发器 及(注解 + 反射机制)—————— 开开开山怪的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/687018

相关文章

SpringBoot中四种AOP实战应用场景及代码实现

《SpringBoot中四种AOP实战应用场景及代码实现》面向切面编程(AOP)是Spring框架的核心功能之一,它通过预编译和运行期动态代理实现程序功能的统一维护,在SpringBoot应用中,AO... 目录引言场景一:日志记录与性能监控业务需求实现方案使用示例扩展:MDC实现请求跟踪场景二:权限控制与

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

Java注解之超越Javadoc的元数据利器详解

《Java注解之超越Javadoc的元数据利器详解》本文将深入探讨Java注解的定义、类型、内置注解、自定义注解、保留策略、实际应用场景及最佳实践,无论是初学者还是资深开发者,都能通过本文了解如何利用... 目录什么是注解?注解的类型内置注编程解自定义注解注解的保留策略实际用例最佳实践总结在 Java 编程

Java 实用工具类Spring 的 AnnotationUtils详解

《Java实用工具类Spring的AnnotationUtils详解》Spring框架提供了一个强大的注解工具类org.springframework.core.annotation.Annot... 目录前言一、AnnotationUtils 的常用方法二、常见应用场景三、与 JDK 原生注解 API 的

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Java中的StringBuilder之如何高效构建字符串

《Java中的StringBuilder之如何高效构建字符串》本文将深入浅出地介绍StringBuilder的使用方法、性能优势以及相关字符串处理技术,结合代码示例帮助读者更好地理解和应用,希望对大家... 目录关键点什么是 StringBuilder?为什么需要 StringBuilder?如何使用 St

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows