[SpringMVC]仿写SpringMVC(注解开发)

前提:

当前版本无接受网络请求功能,不喜勿喷🙏🙏
本文将对代码核心进行讲解,源码已上传到gitee仓库

1、代码结构

在这里插入图片描述
如果对反射有些忘记了,可以先移步到这里,对反射进行了详解

如果对注解有些忘记了,可以先移步到这里,对注解进行了详解

2、核心:YhzMVC

package Test.mvc;

import Test.Test;
import Test.annotation.Controller;
import Test.annotation.RequestMapping;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @BelongsProject: 3.9.demo
 * @Author: yhz
 * @CreateTime: 2023-07-22  14:36
 * @Description: TODO
 * @Version: 1.0
 */
public class YhzMVC {
    //存的是该项目文件夹中所有.java结尾文件的全限定名
    public static List<String>arr= new ArrayList<>();

    //存的是每个controller上requestmapping的value以及该controller下所有的requestmapping的value以及所属方法
    public static HashMap<String, Map<String, Method>> map=new HashMap<>();

    //controller的requestmapping的value值以及controller对象
    public static Map<String,Object>controllerMap = new HashMap<>();




    public static void exec(String classPath,String methodPath){
        if(controllerMap.get(classPath)==null){
            System.out.println("没有这个类 404");
        }else {
            if(map.get(classPath).get(methodPath)==null){
                System.out.println("没有这个方法 404");
            }else {
                try {
                    map.get(classPath).get(methodPath).invoke(controllerMap.get(classPath));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public static void getFilePath(File file) {
        File[] fs = file.listFiles();
        for (File f : fs) {
            if (f.isDirectory()){
                getFilePath(f);
            }
            if (f.isFile()) {
                String filepath = f.toString();
                filepath = filepath.split("src")[1];
                filepath = filepath.substring(1,filepath.length());
                if( filepath.endsWith(".java")) {
                    //把是.java文件的全类名放到arr中
                    arr.add(filepath.replace("\\", ".").replace(".java", ""));
                }
            }
        }
    }

    //查找所有controller,并创建对象装入Map里(“url”:Object)
    public static void chooseController() {
        for(String file: arr){
            try {
                Class<?> aClass = Class.forName(file);
                //如果有Controller注解
                if(aClass.isAnnotationPresent(Controller.class)){
                    //如果有RequestMapping注解
                    if(aClass.isAnnotationPresent(RequestMapping.class)){
                        RequestMapping requestMapping = getRequestMapping(aClass);
                        //如果之前已经有了一样的  不同controller的requestmapping的值,说明有冲突。
                        if(map.containsKey(requestMapping.value())){
                            throw  new RuntimeException("类多注解值:"+requestMapping.value());
                        }else {
                            map.put(requestMapping.value(),new HashMap<>());
                            controllerMap.put(requestMapping.value(),aClass.newInstance());
                        }
                        Method[] declaredMethods = aClass.getDeclaredMethods();
                        for (Method declaredMethod : declaredMethods) {
                            if(declaredMethod.isAnnotationPresent(RequestMapping.class)){
                                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);
                                }
                            }
                        }

                    }else {
                        throw  new RuntimeException("类无requestMapping注解");
                    }
                }
            }catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    }
    //Java基础 : 方法的重载。
    public static RequestMapping getRequestMapping(Class cl){
        Annotation annotation = cl.getAnnotation(RequestMapping.class);
        if(annotation instanceof  RequestMapping){
            return  (RequestMapping) annotation;
        }
        return null;
    }
    public static RequestMapping getRequestMapping(Method method){
        Annotation annotation = method.getAnnotation(RequestMapping.class);
        if(annotation instanceof  RequestMapping){
            return  (RequestMapping) annotation;
        }
        return null;
    }
}

3、初始化步骤是:

  1. 定义3个静态集合,arr装遍历到的所有java文件的全类名、controllerMap装controller的url与controller的映射结构、map装每个controller的url与每个controller里每个方法的url与方法的map的映射结构
  2. 通过给getFilePath(File file)方法传入源代码根目录,对项目中所有以.java结尾的java文件进行搜索,对每个java文件的路径进行字符串处理,得到文件的全限定名(包名+类名),然后将全限定名装入list中,用于反射(Class.forName(String className))。
    例如:
    在这里插入图片描述
  3. 对每个java文件进行遍历,通过反射识别类上是否有我们所需的注解,找到带有@Controller注解和@RequestMapping注解的类,如果只有@Controller,没有@RequestMapping,那么抛出一个运行时异常(类无requestMapping注解)。通过反射获取类上的@RequestMapping注解内的值,先对值进行判断,是否map里已经存在了这个值,如果存在,抛出一个运行时异常(类多注解值:"+requestMapping.value());如果不存在,向map中添加(controller的url,new HashMap)(这个new 的HashMap,用来装controller里的方法上的url与方法的映射结构)、向controllerMap中添加(controller的url,controller的实例)。对类操作完,接下来对类里的方法进行遍历,先判断方法上是否带有@RequestMapping注解,如果有,再判断,这个方法上@RequestMapping注解的值是否已经存在了,如果存在,抛出一个运行时异常(“方法多注解值:”+mapping.value());如果当前值是唯一的,则获取到map中当前controller类的url对应的HashMap,将方法的url与方法的映射结构装入得到的HashMap。

4、执行

  1. 传入的两个字符串参数,一个controller的url:classPath,一个方法的url:methodPath
  2. 先判断controllerMap中是否包含classPath这个key,如果不包含则认为没有这个类;如果包含,再判断map的classPath对用的value里是否包含methodPath,如果不包含,则认为这个类里没有这个方法;如果包含,则通过反射执行该方法(method.invoke(Object obj, Object… args))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值