当前位置: 首页 > news >正文

手写简单模拟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 {@RequestMappingpublic 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 {@RequestMappingpublic 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为一个新的HashMapobjMap.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) {// 如果注解对象不为nullreturn true;// 返回true,表示类为控制器}return false;// 返回false,表示类不是控制器}private static boolean isRequestMapping(Class cl) {// 定义一个私有的静态方法,用于检查类是否包含RequestMapping注解Annotation annotation = cl.getAnnotation(RequestMapping.class);// 获取类的RequestMapping注解对象if (annotation != null) {// 如果注解对象不为nullreturn true;// 返回true,表示类包含RequestMapping注解}return false;// 返回false,表示类不包含RequestMapping注解}private static boolean isRequestMapping(Method method) {// 定义一个私有的静态方法,用于检查方法是否包含RequestMapping注解Annotation annotation = method.getAnnotation(RequestMapping.class);// 获取方法的RequestMapping注解对象if (annotation != null) {// 如果注解对象不为nullreturn 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.lryc.cn/news/395304.html

相关文章:

  • 【FreeRTOS】同步互斥与通信 FreeRTOS提供的方法
  • Kafka 面试题指南
  • 2024年7月5日 (周五) 叶子游戏新闻
  • 热门开源项目推荐:探索开源世界的精彩
  • Codeforces Round #956 (Div. 2) and ByteRace 2024(A~D题解)
  • 基于YOLOv9的脑肿瘤区域检测
  • 阿里云 ECS 服务器的安全组设置
  • 昇思25天学习打卡营第15天|应用实践之ShuffleNet图像分类
  • 怀庄之醉适合搭配什么食物?
  • Java | Leetcode Java题解之第223题矩形面积
  • 基于单片机的空调控制器的设计
  • 企业如何利用短视频平台做口碑塑造和品牌营销?
  • SQL INSERT批量插入方式
  • 2.5 C#视觉程序开发实例1----IO_Manager实现切换程序
  • 【入门篇】STM32寻址范围(更新中)
  • DDD架构
  • Open3D KDtree的建立与使用
  • C语言编程3:运算符,运算符的基本用法
  • 如何通过SPI机制去实现读取配置文件并动态加载对应实现类
  • 双链表(数组模拟)
  • ChatGPT 5.0:一年半后的展望与看法
  • 城市地下综合管廊物联网远程监控
  • VS 附加进程调试
  • 核函数的深入理解
  • 使用Ckman部署ClickHouse集群介绍
  • 「前端工具」postman接口测试工具详解
  • 生成requirements.txt
  • ubuntu ceph部署
  • 2024.7.8
  • Spring 外部jar包Bean自动装配