手写简单模拟mvc

目录结构:

 两个注解类:

@Controller:

package com.heaboy.annotation;

import java.lang.annotation.*;

/**
 * 注解没有功能只是简单标记
 *  .RUNTIME    运行时还能看到
 *  .CLASS  类里面还有,构建对象久没来了,这个说明是给类加载器的
 *  .SOURCE  表示这个注解能存活到哪一阶段(源码阶段)仅在   .java阶段有用 也就是仅在编译阶段有 
 *   用 
 *   是让编译器去看的
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Controller {
}

@RequestMapping:

package com.heaboy.annotation;

import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})//既在类上有用 在方法上也能用
public @interface RequestMapping {
    /**
     * 表明使用这个注解需要传入一个值,可以通过value()的形式传入, dafault是设置默认值 表明既可以传值
     * 也可以不传,使用设置的默认值null
     * @return
     */
    String value() default "";

}

两个Controller类:

TestController:

package com.heaboy.Controller;

import com.heaboy.annotation.Controller;
import com.heaboy.annotation.RequestMapping;

@Controller
@RequestMapping("test")
public class TestController {
    @RequestMapping
    public String index(){
        System.out.println("test->index");
        return "";
    }
    @RequestMapping("index1")
    public String index1(){
        System.out.println("test->index1");
        return "";
    }
    @RequestMapping("index2")
    public String index2(){
        System.out.println("test->index2");
        return "";
    }
//    @RequestMapping("index1")
//    public String index3(){
//        System.out.println("test->index3");
//        return "";
//    }

}

IndexController类:

package com.heaboy;

import com.heaboy.annotation.Controller;
import com.heaboy.annotation.RequestMapping;

@Controller
@RequestMapping
public class IndexController {
    @RequestMapping
    public void index(){
        System.out.println("index->index");
    }
    @RequestMapping("index1")
    public String index1(){
        System.out.println("test->index111111");
        return "";
    }
}

最重要的模拟mvc功能类:HeaboyMvc

package com.heaboy.mvc;

import com.heaboy.annotation.Controller;
import com.heaboy.annotation.RequestMapping;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;

/**
 * @author heaboy
 * mvc类
 */
public class HeaboyMvc {
    private static HashMap<String, Map<String, Method>> map = new HashMap<>();
    // 创建一个静态的哈希映射,用于存储类路径和方法路径对应的Method对象
    private static HashMap<String, Object> objMap = new HashMap<>();
    // 创建一个静态的哈希映射,用于存储类路径和对应的实例对象

    public static void exec(String classPath, String methodPath) {
        // 定义一个公开的静态方法,用于执行指定类路径和方法路径的方法
        if (objMap.get(classPath) == null) {
            // 如果objMap中没有对应的类实例,则输出错误信息
            System.out.println("没有这个类 404");
        } else {
            // 如果有对应的类实例
            if (map.get(classPath).get(methodPath) == null) {
                // 如果map中没有对应的方法,则输出错误信息
                System.out.println("没有这个方法 404");
            } else {
                // 如果有对应的方法
                try {
                    // 尝试调用该方法
                    map.get(classPath).get(methodPath).invoke(objMap.get(classPath));
                } catch (IllegalAccessException e) {
                    // 捕获调用方法时可能出现的异常,并打印堆栈跟踪信息
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    // 捕获调用方法时可能出现的异常,并打印堆栈跟踪信息
                    e.printStackTrace();
                }
            }
        }
    }

    public static void scanner(String path, String packageName) {
        // 定义一个公开的静态方法,用于扫描指定路径下的类文件,并处理注解
        List<String> paths = traverseFolder2(path);
        // 获取指定路径下所有的类文件路径
        for (String p : paths) {
            p = p.substring(path.length() - 1);
            // 从路径中截取类文件的相对部分
            try {
                String className = packageName + "." + p.replaceAll(Matcher.quoteReplacement(File.separator), ".");
                // 构造类的完整名称,包括包名和类名
                String replace = className.replace(".class", "");
                // 移除类名称后面的“.class”后缀
                Class<?> cl = ClassLoader.getSystemClassLoader().loadClass(replace);
                // 加载类文件到内存
                if (isController(cl)) {
                    // 检查当前类是否为控制器
                    if (isRequestMapping(cl)) {
                        // 检查当前类是否包含RequestMapping注解
                        RequestMapping requestMapping = getRequestMapping(cl);
                        // 获取类的RequestMapping注解对象
                        if (map.containsKey(requestMapping.value())) {
                            // 如果map中已经包含了该注解值
                            throw new RuntimeException("类多注解值:" + requestMapping.value());
                            // 抛出运行时异常,表示类有多个注解值
                        } else {
                            // 如果没有包含该注解值
                            map.put(requestMapping.value(), new HashMap<>());
                            // 在map中添加一个新的映射项,key为注解值,value为一个新的HashMap
                            objMap.put(requestMapping.value(), cl.newInstance());
                            // 创建该类的实例,并存储在objMap中
                        }
                        Method[] declaredMethods = cl.getDeclaredMethods();
                        // 获取类中声明的所有方法
                        for (Method declaredMethod : declaredMethods) {
                            // 遍历每个方法
                            if (isRequestMapping(declaredMethod)) {
                                // 如果方法包含RequestMapping注解
                                RequestMapping mapping = getRequestMapping(declaredMethod);
                                // 获取方法的RequestMapping注解对象
                                if (map.get(requestMapping.value()).containsKey(mapping.value())) {
                                    // 如果map中已经包含了该方法注解值
                                    throw new RuntimeException("方法多注解值:" + requestMapping.value());
                                    // 抛出运行时异常,表示方法有多个注解值
                                } else {
                                    // 如果没有包含该方法注解值
                                    map.get(requestMapping.value()).put(mapping.value(), declaredMethod);
                                    // 将方法存储在map中
                                }
                            }
                        }
                    } else {
                        // 如果类不包含RequestMapping注解
                        throw new RuntimeException("类无requestMapping");
                        // 抛出运行时异常,表示类无RequestMapping注解
                    }
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                // 捕获类未找到异常,并打印堆栈跟踪信息
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                // 捕获非法访问异常,并打印堆栈跟踪信息
            } catch (InstantiationException e) {
                e.printStackTrace();
                // 捕获实例化异常,并打印堆栈跟踪信息
            }
        }
    }

    private static boolean isController(Class cl) {
        // 定义一个私有的静态方法,用于检查类是否为控制器
        Annotation annotation = cl.getAnnotation(Controller.class);
        // 获取类的Controller注解对象
        if (annotation != null) {
            // 如果注解对象不为null
            return true;
            // 返回true,表示类为控制器
        }
        return false;
        // 返回false,表示类不是控制器
    }

    private static boolean isRequestMapping(Class cl) {
        // 定义一个私有的静态方法,用于检查类是否包含RequestMapping注解
        Annotation annotation = cl.getAnnotation(RequestMapping.class);
        // 获取类的RequestMapping注解对象
        if (annotation != null) {
            // 如果注解对象不为null
            return true;
            // 返回true,表示类包含RequestMapping注解
        }
        return false;
        // 返回false,表示类不包含RequestMapping注解
    }

    private static boolean isRequestMapping(Method method) {
        // 定义一个私有的静态方法,用于检查方法是否包含RequestMapping注解
        Annotation annotation = method.getAnnotation(RequestMapping.class);
        // 获取方法的RequestMapping注解对象
        if (annotation != null) {
            // 如果注解对象不为null
            return true;
            // 返回true,表示方法包含RequestMapping注解
        }
        return false;
        // 返回false,表示方法不包含RequestMapping注解
    }

    private static RequestMapping getRequestMapping(Class cl) {
        // 定义一个私有的静态方法,用于获取类的RequestMapping注解对象
        Annotation annotation = cl.getAnnotation(RequestMapping.class);
        // 获取类的RequestMapping注解对象
        if (annotation instanceof RequestMapping) {
            // 如果注解对象是RequestMapping类型
            return (RequestMapping) annotation;
            // 将注解对象强制转换为RequestMapping类型并返回
        }
        return null;
        // 返回null,表示类不包含RequestMapping注解
    }

    private static RequestMapping getRequestMapping(Method method) {
        // 定义一个私有的静态方法,用于获取方法的RequestMapping注解对象
        Annotation annotation = method.getAnnotation(RequestMapping.class);
        // 获取方法的RequestMapping注解对象
        if (annotation instanceof RequestMapping) {
            // 如果注解对象是RequestMapping类型
            return (RequestMapping) annotation;
            // 将注解对象强制转换为RequestMapping类型并返回
        }
        return null;
        // 返回null,表示方法不包含RequestMapping注解
    }

    private static List<String> traverseFolder2(String path) {
        // 定义一个私有的静态方法,用于遍历文件夹,获取所有类文件的路径
        File file = new File(path);
        // 创建文件对象
        List<String> classFiles = new ArrayList<>();
        // 创建一个列表,用于存储类文件路径
        if (file.exists()) {
            // 如果文件夹存在
            LinkedList<File> list = new LinkedList<File>();
            // 创建一个链表,用于存储子文件夹
            File[] files = file.listFiles();
            // 获取文件夹中的所有文件和子文件夹
            for (File file2 : files) {
                // 遍历每个文件和子文件夹
                if (file2.isDirectory()) {
                    // 如果是子文件夹
                    list.add(file2);
                    // 将子文件夹添加到链表中
                } else {
                    // 如果是文件
                    classFiles.add(file2.getAbsolutePath());
                    // 将文件的绝对路径添加到类文件路径列表中
                }
            }
            File temp_file;
            while (!list.isEmpty()) {
                // 当链表不为空时
                temp_file = list.removeFirst();
                // 移除链表中的第一个文件夹
                files = temp_file.listFiles();
                // 获取文件夹中的所有文件和子文件夹
                for (File file2 : files) {
                    // 遍历每个文件和子文件夹
                    if (file2.isDirectory()) {
                        // 如果是子文件夹
                        list.add(file2);
                        // 将子文件夹添加到链表中
                    } else {
                        // 如果是文件
                        classFiles.add(file2.getAbsolutePath());
                        // 将文件的绝对路径添加到类文件路径列表中
                    }
                }
            }
        } else {
            // 如果文件夹不存在
            System.out.println("路径不存在");
        }
        return classFiles;
        // 返回类文件路径列表
    }
    // 结束 traverseFolder2 方法
}

测试类:Main

package com.heaboy;

import com.heaboy.mvc.HeaboyMvc;

public class Main {
    static {
        String path = Main.class.getResource("").getPath();
        String packageName = Main.class.getPackage().getName();
        HeaboyMvc.scanner(path,packageName);
    }

    public static void main(String[] args) {
        HeaboyMvc.exec("","");
        HeaboyMvc.exec("test","index1");
        HeaboyMvc.exec("test","index2");
        HeaboyMvc.exec("test","");
        HeaboyMvc.exec("test","dadasdadad");
        HeaboyMvc.exec("","index1");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/784533.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java信号量semaphore的原理与使用方法

Semaphore的基本概念 在Java中&#xff0c;Semaphore是位于java.util.concurrent包下的一个类。它的核心就是维护了一个许可集。简单来说&#xff0c;就是有一定数量的许可&#xff0c;线程需要先获取到许可&#xff0c;才能执行&#xff0c;执行完毕后再释放许可。 那么&…

Django 新增数据 create()方法

1&#xff0c;添加模型 Test/app11/models.py from django.db import modelsclass Book(models.Model):title models.CharField(max_length100)author models.CharField(max_length100)publication_date models.DateField()price models.DecimalField(max_digits5, decim…

意得辑ABSJU202优惠15%啦,新用户注册直减哦

不得不说&#xff0c;还得是意得辑&#xff0c;钱不白花&#xff0c;润色的挺好~ 第一篇SCI终于成功见刊&#xff01;&#xff01;&#xff01; 都来接accept&#xff01;&#xff01;&#xff01;谢谢accept小狗&#xff0c;接accept 求求accept小狗&#xff0c;真的想要双证毕…

消防认证-防火窗

一、消防认证 消防认证是指消防产品符合国家相关技术要求和标准&#xff0c;且通过了国家认证认可监督管理委员会审批&#xff0c;获得消防认证资质的认证机构颁发的证书&#xff0c;消防产品具有完好的防火功能&#xff0c;是住房和城乡建设领域验收的重要指标。 二、认证依据…

绝地求生PUBG没有开始游戏按钮的解决办法

绝地求生是一款特别热门的战术竞技型射击类游戏&#xff0c;游戏中玩家需要在游戏地图上收集各种资源&#xff0c;并在不断缩小的安全区域内持武器对抗其他玩家&#xff0c;让自己生存到最后。当游戏最后场上只剩下一支队伍的时候即可获得游戏胜利。然而一些玩家在游玩绝地求生…

深入探索 Python 中的数据维数:高维数据处理方法与应用

Python 数据维数 在数据科学和机器学习领域&#xff0c;理解数据的维度是至关重要的。Python作为一种强大而灵活的编程语言&#xff0c;提供了丰富的工具和库来处理各种维度的数据。本文将介绍Python中数据维数的概念&#xff0c;以及如何使用Python库来处理不同维度的数据。 什…

YARN运行流程源码分析

一、yarn任务执行流程图 在分析任务之前先走一下yarn内部的流程细节。 二、RM 内部处理提交阶段运行流程 如上图流程所示&#xff1a; 1.client 提交任务给yarn&#xff0c;yarn 这边会获取任务的AM相关资源&#xff0c;client在提交阶段会上传job.split &#xff08;数据切分…

SpringCloud第一篇Docker基础

文章目录 一、常见命令二、数据卷三、数据挂载四、自定义镜像五、网络 一、常见命令 Docker最常见的命令就是操作镜像、容器的命令&#xff0c;详见官方文档&#xff1a; https://docs.docker.com/ 需求&#xff1a; 在DockerHub中搜索Nginx镜像&#xff0c;查看镜像的名称 …

企业如何从无序管理走向精益生产管理?

先来看看企业生产管理无序的弊端有哪些&#xff1f; 数据统计不及时&#xff1a;纸质生产工单&#xff0c;数据难统计&#xff0c;各业务环节问题难定位&#xff0c;影响车间生产效率。生产过程不透明&#xff1a;生产过程数据难监控&#xff0c;生产派工管理混乱&#xff0c;…

百度网盘非会员,享受视频倍速

百度网盘会员过期了&#xff0c;看视频不能倍速很难受&#xff0c;下面就是跨过会员机制&#xff0c;享受倍速的方法。 Edge浏览器 在浏览器设置中找到扩展选项 在扩展中搜索视频速度控制 global speed&#xff0c;安装后即可使用

在Linux操作系统中去修复/etc/fstab文件引起的系统故障。

如果/etcfstab文件中发生错误&#xff0c;有可能导致系统无法正常启动。 比如&#xff1a;系统里的一块磁盘被删除&#xff0c;但是/etc/fstab中关于这块磁盘的信息依然被保存在文件/etc/fstab中。 主要看倒数后两行&#xff0c;系统提示&#xff0c;敲ctrlD或者是直接输入密码…

2通道音频ADC解码芯片ES7243L、ES7243E、ES7243,用于低成本实现模拟麦克风转换为IIS数字话筒

前言&#xff1a; 音频解码芯片某创参考价格&#xff1a; ES7243L 500&#xff1a;&#xffe5;1.36 / 个 ES7243E 500&#xff1a;&#xffe5;1.66 / 个 ES7243 500&#xff1a; &#xffe5;1.91 / 个 其中ES7243L工作电压为1.8V&#xff0c;与其他两款的3.3V工作电压不同&…

推荐3款免费电脑工具

Tools-Web Tools-Web是一个在线工具箱&#xff0c;提供丰富的工具和功能&#xff0c;适用于日常工作和学习。根据用户评价&#xff0c;Tools-Web的工具种类丰富且操作简单&#xff0c;是日常工作和学习的好帮手。该工具箱涵盖了开发运维、文本处理、图片处理、图表处理、随机工…

大模型知识问答: 文本分块要点总结

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型技术趋势、算法项目落地经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了深入的讨论。 总结链接如…

昇思MindSpore学习笔记6-01LLM原理和实践--FCN图像语义分割

摘要&#xff1a; 记录MindSpore AI框架使用FCN全卷积网络理解图像进行图像语议分割的过程、步骤和方法。包括环境准备、下载数据集、数据集加载和预处理、构建网络、训练准备、模型训练、模型评估、模型推理等。 一、概念 1.语义分割 图像语义分割 semantic segmentation …

【易捷海购-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

【2024华为HCIP831 | 高级网络工程师之路】刷题日记(BGP)

个人名片:🪪 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻‍❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️ 零基础学Java——小白入门必备🔥重识C语言——复习回顾🔥计算机网络体系———深度详讲HCIP数通工程师-刷题与实战🔥🔥

windows obdc配置

进入控制面板&#xff1a; 进入管理工具&#xff1a;

java —— JSP 技术

一、JSP &#xff08;一&#xff09;前言 1、.jsp 与 .html 一样属于前端内容&#xff0c;创建在 WebContent 之下&#xff1b; 2、嵌套的 java 语句放置在<% %>里面&#xff1b; 3、嵌套 java 语句的三种语法&#xff1a; ① 脚本&#xff1a;<% java 代码 %>…

顶会FAST24最佳论文|阿里云块存储架构演进的得与失-4.EBS不同架构性能提升思路

3.1 平均延迟与长尾延迟 虚拟磁盘&#xff08;VD&#xff09;的延迟是由其底层架构决定的&#xff0c;具体而言&#xff0c;取决于请求所经历的路径。以EBS2为例&#xff0c;VD的延迟受制于两跳网络&#xff08;从BlockClient到BlockServer&#xff0c;再至ChunkServer&#x…