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

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2