仿写SpringMVC

1.创建简单的注解

1.1 Controller

package com.heaboy.annotation;

import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @ interface Controller {
}

1.2 RequestMapping

package com.heaboy.annotation;

import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface RequestMapping {
    String value() default "";
}

2.创建controller类

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 "";
    }
}
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");
    }
}

3.SpingMVC实现类

package com.heaboy.mvc;

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

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.channels.ClosedSelectorException;
import java.sql.SQLOutput;
import java.util.*;
import java.util.regex.Matcher;

public class HeaboyMvc {
    private static HashMap<String, Map<String,Method>> map=new HashMap<>();
    private static HashMap<String,Object> objMap=new HashMap<>();
    public static void scanner(String path,String packageName)  {
        //扫描main所在包中的类以及子包中的类的绝对路径
        List<String> paths=traverseFolder2(path);
        for (String p : paths) {
            p=p.substring(path.length()-1);
            //遍历每一个类文件的绝对路径,并且处理只剩下对main的相对路径
            try {
                String className=packageName+"."+p.replaceAll(Matcher.quoteReplacement(File.separator),".");
                //包名加相对路径,把相对路径的/换成.
                String replace=className.replace(".class","");
                //去掉.class后缀
                Class<?> cl=Class.forName(replace);
                //获取改类的class对象
                if (isController(cl)){
                    //是否有controller注解
                    if (isRequestMapping(cl)){
                        //是否有requestMapping注解
                        RequestMapping requestMapping=getRequestMapping(cl);
                        //获取requestmapping注解
                        if (map.containsKey(requestMapping.value())){
                            throw new RuntimeException("类多注解值:"+requestMapping.value());
                            //跟之前扫描的名字冲突报错
                        }else {
                            map.put(requestMapping.value(),new HashMap<>());
                            //类的requestMapping注解值和map字典放入字典中
                            objMap.put(requestMapping.value(),cl.newInstance());
                            //类的注解值和类对象放入字典中
                        }
                        Method[] declaredMethods=cl.getDeclaredMethods();
                        //获取该对象的每一个方法对象
                        for (Method declaredMethod : declaredMethods) {
                            //遍历方法对象
                            if (isRequestMapping(declaredMethod)){
                                //判断该方法是否有requesting注解
                                RequestMapping mapping=getRequestMapping(declaredMethod);
                                //获取该方法的注解
                                if (map.get(requestMapping.value()).containsKey(mapping.value())){
                                    //判断该类是否有相同的注解值,有就报错
                                    throw  new RuntimeException("方法多注解值:"+requestMapping.value());
                                }else {
                                    map.get(requestMapping.value()).put(mapping.value(),declaredMethod);
                                    //没有就添加map对应类的方法字典中
                                }
                            }
                        }
                    }else {
                        throw new RuntimeException("类无requestMapping");
                    }
                }

            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    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){
                //判断该类中是否有该方法
                System.out.println("没有这个方法 404");
            }else {
                try {
                    //获取该类的该方法并且执行
                    map.get(classPath).get(methodPath).invoke(objMap.get(classPath));
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                } catch (InvocationTargetException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    private static List<String> traverseFolder2(String path){
        //创建main所在文件夹对象
        File file=new File(path);
        ArrayList<String> classPaths=new ArrayList<>();
        //创建数组,存放类路径
        if (file.exists()){
            //文件夹存在执行
            LinkedList<File> list=new LinkedList<>();
            //存放子文件夹路径以及子子文件夹数量
            File[] files=file.listFiles();
            //把main所在文件夹下的子文件夹和文件放入数组
            for (File file1 : files) {
                //遍历
                if (file1.isDirectory()){
                    //判断是不是文件夹
                    list.add(file1);
                    //是放入子文件夹集合
                }else {
                    classPaths.add(file1.getAbsolutePath());
                    //文件则放入文件集合
                }
            }
            while (!list.isEmpty()){
                //子文件夹集合不为空,一直遍历,直到空为止
                File directory=list.removeFirst();
                //弹出第一个子文件夹对象
                File[] files1=directory.listFiles();
                for (File file1 : files1) {
                    if (file1.isDirectory()){
                        list.add(file1);
                        //判断是否为文件夹,是则放入集合
                    }else {
                        classPaths.add(file1.getAbsolutePath());
                        //文件则放入类集合
                    }
                }
            }
        }
        return classPaths;
    }
    private static boolean isController(Class cl){
        Annotation annotation=cl.getAnnotation(Controller.class);
        if (annotation!=null){
            return true;
        }
        return false;
    }
    private static boolean isRequestMapping(Class cl){
        Annotation annotation=cl.getAnnotation(RequestMapping.class);
        if (annotation!=null){
            return true;
        }
        return false;
    }
    private static boolean isRequestMapping(Method method){
        Annotation annotation=method.getAnnotation(RequestMapping.class);
        if (annotation!=null){
            return true;
        }
        return false;
    }
    private static RequestMapping getRequestMapping(Class cl){
        Annotation annotation=cl.getAnnotation(RequestMapping.class);
        if (annotation instanceof RequestMapping){
            return (RequestMapping) annotation;
        }
        return null;
    }
    private static RequestMapping getRequestMapping(Method method){
        Annotation annotation = method.getAnnotation(RequestMapping.class);
        if(annotation instanceof  RequestMapping){
            return  (RequestMapping) annotation;
        }
        return null;
    }
}

4.启动类

package com.heaboy;

import com.heaboy.mvc.HeaboyMvc;

import java.util.Stack;

public class Main {
    static {
        String path=Main.class.getResource("").getPath();
        //获取main方法的路径
        String packageName=Main.class.getPackage().getName();
        //获取main方法所在包的路径
        HeaboyMvc.scanner(path,packageName);
        //扫描main所在包中的类以及子包中的类
    }

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

5.结果展示

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

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

相关文章

Qt QWizard新建向导实例

使用QWizard做新建向导&#xff0c;最简单的实例 class MyWizard : public QWizard { public: MyWizard(QWidget* parent nullptr); QWizardPage* createFirstPage(); QWizardPage* createSecondPage(); QWizardPage* createThirdPage(); }; MyWizard::MyWizard(QWidget* par…

Python编程:如何有效等待套接字的读取与关闭

背景介绍 网络编程是现代应用程序开发的重要组成部分&#xff0c;尤其是在大数据和实时通信的背景下。套接字&#xff08;Socket&#xff09;作为网络通信的核心技术&#xff0c;是开发网络应用程序的基础。在Python编程中&#xff0c;如何有效地等待套接字的读取与关闭事件是…

25届最近5年天津工业大学自动化考研院校分析

天津工业大学 目录 一、学校学院专业简介 二、考试科目指定教材 三、近5年考研分数情况 四、近5年招生录取情况 五、最新一年分数段图表 六、初试大纲复试大纲 七、学费&奖学金&就业方向 一、学校学院专业简介 二、考试科目指定教材 1、考试科目介绍 2、指定教…

AIGC:构筑创意新时代的神奇力量

在当今数字化浪潮中&#xff0c;AIGC&#xff08;人工智能生成内容&#xff09;正以其强大的创造力和应用价值&#xff0c;引领着一场前所未有的创意革命。从文本生成到音乐创作&#xff0c;从图像设计到电影制作&#xff0c;AIGC的触角已延伸至文化艺术的各个领域&#xff0c;…

FreeRTOS——任务通知

一、任务通知 1.1 任务通知简介 任务通知&#xff1a;用来通知任务的&#xff0c;任务控制块中的结构体成员变量 ulNotifiedValue就是这个通知值 &#xff08;1&#xff09;使用队列、信号量、事件标志组时都需另外 创建一个结构体 &#xff0c;通过中间的结构体进行间接通信…

古代VS现代,太阳黑子的影响有什么变化?

公元前28年&#xff0c;我国汉朝人在人类历史上第一次记载下了“太阳黑子”。在《汉书五行志》里是这样记载&#xff1a;“汉成帝河平元年三月乙未&#xff0c;日出黄&#xff0c;有黑气&#xff0c;大如钱&#xff0c;居日中央”。在2052年前&#xff0c;人类对于太阳黑子的认…

社区6月月报 | Apache DolphinScheduler重要修复和优化记录

各位热爱Apache DolphinScheduler的小伙伴们&#xff0c;社区6月月报更新啦&#xff01;这里将记录Apache DolphinScheduler社区每月的重要更新&#xff0c;欢迎关注。 月度Merge Stars 感谢以下小伙伴上个月为Apache DolphinScheduler所做的精彩贡献&#xff08;排名不分先后…

跨境传输需要遵守哪些准则,如何做到有效管控?

在全球化的商业环境中&#xff0c;跨国企业面临着数据跨境传输的挑战。随着业务的扩展&#xff0c;企业需要在不同国家和地区之间高效、安全地传输大量数据。选择合适的跨境传输方案对于保障数据安全、提高业务效率、遵守法律法规至关重要。 跨境传输数据需要遵守的准则和规定主…

FPGA之 串口UART通信

FPGA之串口UART通信 1. UART发送模块&#xff08;Transmitter&#xff09;2. UART接收模块&#xff08;Receiver&#xff09;3. testbench4. 边沿检测电路 串口&#xff08;Universal Asynchronous Receiver/Transmitter&#xff0c;UART&#xff09;是一种串行通信协议&#x…

大数据下的用户研究:深度洞察与精准决策的引擎

文章目录 一、大数据时代的用户研究新机遇二、大数据用户研究的流程与关键技术三、大数据用户研究的实践案例四、大数据用户研究的挑战与展望《用户研究方法&#xff1a;卓越产品和服务的用户研究技巧》内容及特色读者对象 在当今这个数据爆炸的时代&#xff0c;大数据已成为推…

仪表板展示|DataEase看中国:2023年中国新能源汽车经济运行情况分析

背景介绍 随着政府机构、企业和个人对环保和可持续发展的高度关注&#xff0c;“新能源汽车”在全球范围内成为了一个热门话题。新能源汽车是指使用非传统燃料&#xff08;如电能、氢能等&#xff09;作为动力源的汽车。 在中国市场&#xff0c;新能源汽车产业蓬勃发展&#…

2.贪心算法.基础

2.贪心算法.基础 基础知识题目1.分发饼干2.摆动序列3.最大子序和4.买股票的最佳时机24.2.买股票的最佳时机5.跳跃游戏5.1.跳跃游戏26.K次取反后最大化的数组和7.加油站8.分发糖果 基础知识 什么是贪心? 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 贪…

Codeforces Round #956 (Div. 2) and ByteRace 2024(A~D题解)

这次比赛也是比较吃亏的&#xff0c;做题顺序出错了&#xff0c;先做的第三个&#xff0c;错在第三个数据点之后&#xff0c;才做的第二个&#xff08;因为当时有个地方没检查出来&#xff09;所以这次比赛还是一如既往地打拉了 那么就来发一下题解吧 A. Array Divisibility …

Nifi 与 Kettle

01 Kettle简介 Kettle是一个开源的ETL&#xff08;Extract-Transform-Load&#xff09;工具&#xff0c;可以用于数据集成、数据转换和数据处理等任务。它提供了一组可视化的设计工具&#xff0c;使得用户可以通过简单的拖拽和连接来构建数据流程&#xff0c;并且还支持多种数据…

apache启动报错:the requested operation has failed

Apache24\bin cmd 回车 httpd -t 因为我重新压缩了&#xff0c;记住&#xff0c;重新压缩要使用原路径&#xff0c; 因为你安装的 时候使用的是原路径 还是不行就改个端口&#xff0c;切记修改配置文件httpd.conf先把Tomcat停了 Define SRVROOT "F:\Apache\Apache24&q…

人工智能和机器学习 (复旦大学计算机科学与技术实践工作站)20240703(上午场)人工智能初步、mind+人脸识别

前言 在这个科技日新月异的时代&#xff0c;人工智能&#xff08;AI&#xff09;已经逐渐渗透到我们生活的方方面面&#xff0c;从智能家居到自动驾驶&#xff0c;无一不彰显着AI的强大潜力。而人脸识别技术作为AI领域的一项重要应用&#xff0c;更是以其高效、便捷的特点受到了…

什么是Kudu

Kudu是一个由Cloudera于2015年9月开源的分布式数据存储引擎&#xff0c;设计旨在结合Hadoop分布式文件系统&#xff08;HDFS&#xff09;和HBase的优势。Kudu提供了一种既支持高效随机访问又支持数据扫描的能力&#xff0c;适用于需要实时插入、更新和读取数据的场景&#xff0…

决策树算法简单介绍:原理和方案实施

决策树算法介绍&#xff1a;原理和方案实施 决策树&#xff08;Decision Tree&#xff09;是一种常用的机器学习算法&#xff0c;它既可以用于分类任务&#xff0c;也可以用于回归任务。由于其直观性和解释性&#xff0c;决策树在数据分析和模型构建中得到了广泛的应用。本文将…

python爬虫和用腾讯云API接口进行翻译并存入excel,通过本机的Windows任务计划程序定时运行Python脚本!

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a;定时爬取外网的某个页面&#xff0c;并将需要的部分翻译为中文存入excel 接下了的&#xff0c;没学过的最好看一下 基本爬虫的学习 【爬虫】requests 结合 BeautifulSoup抓取网页数据_requests beauti…

科普文:Linux服务器常用命令和脚本

Linux服务器常用的命令&#xff1a;find、grep、xargs、sort、uniq、tr、cut、paste、wc、sed、awk&#xff1b;提供的例子和参数都是最常用和最为实用的。 1.find 文件查找 查找txt和pdf文件 find . \( -name "*.txt" -o -name "*.pdf" \) -print 正…