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

相关文章

Spring Boot整合Redis注解实现增删改查功能(Redis注解使用)

《SpringBoot整合Redis注解实现增删改查功能(Redis注解使用)》文章介绍了如何使用SpringBoot整合Redis注解实现增删改查功能,包括配置、实体类、Repository、Se... 目录配置Redis连接定义实体类创建Repository接口增删改查操作示例插入数据查询数据删除数据更

Java Lettuce 客户端入门到生产的实现步骤

《JavaLettuce客户端入门到生产的实现步骤》本文主要介绍了JavaLettuce客户端入门到生产的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录1 安装依赖MavenGradle2 最小化连接示例3 核心特性速览4 生产环境配置建议5 常见问题

Java使用Swing生成一个最大公约数计算器

《Java使用Swing生成一个最大公约数计算器》这篇文章主要为大家详细介绍了Java使用Swing生成一个最大公约数计算器的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下... 目录第一步:利用欧几里得算法计算最大公约数欧几里得算法的证明情形 1:b=0情形 2:b>0完成相关代码第二步:加

Java 的ArrayList集合底层实现与最佳实践

《Java的ArrayList集合底层实现与最佳实践》本文主要介绍了Java的ArrayList集合类的核心概念、底层实现、关键成员变量、初始化机制、容量演变、扩容机制、性能分析、核心方法源码解析、... 目录1. 核心概念与底层实现1.1 ArrayList 的本质1.1.1 底层数据结构JDK 1.7

Java Map排序如何按照值按照键排序

《JavaMap排序如何按照值按照键排序》该文章主要介绍Java中三种Map(HashMap、LinkedHashMap、TreeMap)的默认排序行为及实现按键排序和按值排序的方法,每种方法结合实... 目录一、先理清 3 种 Map 的默认排序行为二、按「键」排序的实现方式1. 方式 1:用 TreeM

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node