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使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.

Spring MVC如何设置响应

《SpringMVC如何设置响应》本文介绍了如何在Spring框架中设置响应,并通过不同的注解返回静态页面、HTML片段和JSON数据,此外,还讲解了如何设置响应的状态码和Header... 目录1. 返回静态页面1.1 Spring 默认扫描路径1.2 @RestController2. 返回 html2

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

Spring核心思想之浅谈IoC容器与依赖倒置(DI)

《Spring核心思想之浅谈IoC容器与依赖倒置(DI)》文章介绍了Spring的IoC和DI机制,以及MyBatis的动态代理,通过注解和反射,Spring能够自动管理对象的创建和依赖注入,而MyB... 目录一、控制反转 IoC二、依赖倒置 DI1. 详细概念2. Spring 中 DI 的实现原理三、

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.