简单仿写MVC

代码地址(需要自取):mvc_Imitation: 简单仿写实现MVC (gitee.com)

项目目录

先把架子搭好

Controller注解

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

RequestMapping

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

HydController

@Controller
@RequestMapping("hyd")
public class HydController {
    @RequestMapping
    public  String index(){
        System.out.println("RequestMapping为“hyd, ”的方法已执行");
        return "";
    }
    @RequestMapping("hyd2")
    public  String index1(){
        System.out.println("RequestMapping为“hyd,hyd2”的方法已执行");
        return "";
    }
}

indexController

@Controller
@RequestMapping
public class IndexController {
    @RequestMapping
    public void index() {
        System.out.println("RequestMapping为“ , ”的方法已执行");
    }
}

Main

public class Main {
    static {
//        获取Main的路径
        String path = Main.class.getResource("").getPath();
//        获取Main的包名
        String packageName = Main.class.getPackage().getName();
        
        HydMVC.scanner(path, packageName);
    }

    public static void main(String[] args) {
        HydMVC.mehtod_go("","");
        HydMVC.mehtod_go("hyd","");
        HydMVC.mehtod_go("hyd","hyd2");
        HydMVC.mehtod_go("232323","23131");
        HydMVC.mehtod_go("hyd","23131");
    }

}

HydMVC

public class HydMVC {
//    存放 一级注解-二级注解-方法 的map
    private static HashMap<String,HashMap<String, Method>> map_method = new HashMap<>();
//    存放 一级注解-类的实例化对象 的map
    private static HashMap<String, Object> map_object = new HashMap<>();

    /**
     * 方法执行函数
     * @param first_path 第一路径
     * @param second_path 第二路径
     */
    public static void mehtod_go(String first_path,String second_path){
//        如果map_object中没有fisrt_path,则不存在该注解的类
        if (map_object.get(first_path)==null){
            System.out.println("没有一个类有"+first_path+"注解");
        }else {
            if (map_method.get(first_path).get(second_path)==null){
                System.out.println(first_path+"下没有"+second_path+"注解"+"的方法");
            }else{
                try {
                    map_method.get(first_path).get(second_path).invoke(map_object.get(first_path));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 扫描获取类实例化对象以及方法
     * @param path
     * @param packageName 包名
     */

    public static void scanner(String path,String packageName){
//        扫描当前所有的文件
        List<String> paths = traverseFolder2(path);
//        遍历拿到的文件路径
        for (String path1 : paths) {
//              path1为:C:\ttt\imitating_spring_mvc\out\production\imitating_spring_mvc\com\heaboy\IndexController.class
//              先拿到文件名 例:IndexController.class
            path1=path1.substring(path.length()-1);
            try{
                //            构建类名
//            因为可能存在多级路径,例如:www/IndexController.class,所以还需要进行一些小处理,不能直接拼接
//            File.separator代表文件分隔符
//            Matcher.quoteReplacement确保了文件分隔符在替换过程中被正确地转义,以防包含任何正则表达式的特殊字符。它返回一个适合用于正则表达式替换的字符串。
                String ClassName = packageName + "." + path1.replaceAll(Matcher.quoteReplacement(File.separator),".");
//            去掉文件名中的.class后缀
                String load_className = ClassName.replace(".class","");
//            通过类加载器加载类
                Class<?> cl = ClassLoader.getSystemClassLoader().loadClass(load_className);
//            用写好的检查注解方法(isController)判断cl是否有Controller注解
                if(isController(cl)){
//              用写好的检查注解方法(isRequestMapping)判断cl是否有RequestMapping注解
                    if (isRequestMapping(cl)){
//                    如果有就获取类上RequestMapping注解的实例
                        RequestMapping requestMapping_first = getRequestMapping(cl);
//                    判断map_method中是否已经存在了该一级注解
                        if (map_method.containsKey(requestMapping_first.value())){
//                        已经存在该一级注解,则抛出异常
                            throw new RuntimeException("包含多个注解:"+requestMapping_first.value());
                        }else {
//                        不存在,添加至map_method中
                            map_method.put(requestMapping_first.value(),new HashMap<>());
//                        添加类的实例化对象到
                            map_object.put(requestMapping_first.value(),cl.newInstance());
                        }
//                    获取类中所有的方法
                        Method[] declareMethods = cl.getDeclaredMethods();
//                    遍历所有方法
                        for (Method method : declareMethods) {
                            if (isRequestMapping(method)){
                                RequestMapping requestMapping_second = getRequestMapping(method);
//                            判断该二级注解是否已经存在
                                if (map_method.get(requestMapping_first.value()).containsKey(requestMapping_second.value())){
//                                存在抛出错误
                                    throw new RuntimeException("方法注解已经存在:"+requestMapping_second.value());
                                }else {
//                                不存在就将方法放入map_method
                                    map_method.get(requestMapping_first.value()).put(requestMapping_second.value(),method);
                                }
                            }
                        }
                    }else{
                        throw new RuntimeException("该类有没RequestMapping注解");
                    }
                }
            }catch (Exception e){
                System.out.println(e);
            }
        }

    }



    /**
     * 扫描文件
     * @param path 绝对路径
     * @return List<String> 文件绝对路径集合
     * C:\ttt\imitating_spring_mvc\out\production\imitating_spring_mvc\com\heaboy\IndexController.class
     */
    private static List<String> traverseFolder2(String path) {
//        当前路径下的文件和文件夹
        File file = new File(path);
//        返回的文件集合
        List<String> file_list = new ArrayList<>();

        if (file.exists()){
//            放文件夹
            LinkedList<File> list = new LinkedList<>();

//            存储过程中要处理的文件
            File[] files = file.listFiles();

            for (File file1 : files) {
//                如果当前文件是文件夹就把它放到list里面
                if (file1.isDirectory()){
                    list.add(file1);
                }else { //不是就将该文件的绝对路径放到返回列表中file_list
                    file_list.add(file1.getAbsolutePath());
                }
            }
//            申请一个临时变量
            File file_temp;
//            当存放文件夹的队列不为空时,执行以下操作
            while (!list.isEmpty()){
//                取出第一个文件夹来处理
                file_temp=list.removeFirst();
//                使用上面申请的FIle[]来存放file_temp中的文件
                files=file_temp.listFiles();
//                处理files中的文件,同上,文件夹放到list中,文件放到file_list中
                for (File file1 : files) {
                    if (file1.isDirectory()){
                        list.add(file1);
                    }else {
                        file_list.add(file1.getAbsolutePath());
                    }
                }
            }
        }else{
//            如果没有任何文件,则不做处理
        }
        return file_list;
    }

//    判断类是否有Controller注解
    private static boolean isController(Class cl){
        Annotation annotation = cl.getAnnotation(Controller.class);
        if(annotation!=null){
            return  true;
        }
        return false;
    }

//    判断类是否有RequestMapping注解
    private static boolean isRequestMapping(Class cl){
        Annotation annotation = cl.getAnnotation(RequestMapping.class);
        if(annotation!=null){
            return  true;
        }
        return false;
    }
//    获取类的RequestMapping注解的实例
    private static RequestMapping getRequestMapping(Class<?> cl) {
        Annotation annotation = cl.getAnnotation(RequestMapping.class);
        if (annotation instanceof  RequestMapping){
            return (RequestMapping) annotation;
        }
        return null;
    }

    //    判断方法是否有RequestMapping注解
    private static boolean isRequestMapping(Method method) {
        Annotation annotation = method.getAnnotation(RequestMapping.class);
        if (annotation!=null){
            return true;
        }
        return false;
    }
//    获取方法上的RequestMapping注解的实例
    private static RequestMapping getRequestMapping(Method method) {
        Annotation annotation  = method.getAnnotation(RequestMapping.class);
        if (annotation instanceof RequestMapping){
            return (RequestMapping) annotation;
        }
        return null;
    }

}

整体思路流程,先对路径下的文件进行扫描,拿到.class后缀的文件,然后根据不同的注解进行不同的操作,将实例化对象和方法都存到map中,再从map中获取调用。具体详细的解释可以查看代码及其注释。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值