仿写SpringMVC

1.创建简单的注解

1.1 Controller

java 复制代码
package com.heaboy.annotation;

import java.lang.annotation.*;

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

1.2 RequestMapping

java 复制代码
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类

java 复制代码
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 "";
    }
}
java 复制代码
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实现类

java 复制代码
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.启动类

java 复制代码
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.结果展示

相关推荐
追风林3 分钟前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
芒果披萨17 分钟前
El表达式和JSTL
java·el
q5673152318 分钟前
在 Bash 中获取 Python 模块变量列
开发语言·python·bash
许野平43 分钟前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
也无晴也无风雨1 小时前
在JS中, 0 == [0] 吗
开发语言·javascript
狂奔solar1 小时前
yelp数据集上识别潜在的热门商家
开发语言·python
duration~1 小时前
Maven随笔
java·maven
zmgst1 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD1 小时前
前后端分离,Jackson,Long精度丢失
java
blammmp2 小时前
Java:数据结构-枚举
java·开发语言·数据结构