当前位置:   article > 正文

手写简单模拟mvc

手写简单模拟mvc

目录结构:

 两个注解类:

@Controller:

  1. package com.heaboy.annotation;
  2. import java.lang.annotation.*;
  3. /**
  4. * 注解没有功能只是简单标记
  5. * .RUNTIME 运行时还能看到
  6. * .CLASS 类里面还有,构建对象久没来了,这个说明是给类加载器的
  7. * .SOURCE 表示这个注解能存活到哪一阶段(源码阶段)仅在 .java阶段有用 也就是仅在编译阶段有
  8. * 用
  9. * 是让编译器去看的
  10. */
  11. @Documented
  12. @Retention(RetentionPolicy.RUNTIME)
  13. @Target(ElementType.TYPE)
  14. public @interface Controller {
  15. }

@RequestMapping:

  1. package com.heaboy.annotation;
  2. import java.lang.annotation.*;
  3. @Documented
  4. @Retention(RetentionPolicy.RUNTIME)
  5. @Target({ElementType.TYPE,ElementType.METHOD})//既在类上有用 在方法上也能用
  6. public @interface RequestMapping {
  7. /**
  8. * 表明使用这个注解需要传入一个值,可以通过value()的形式传入, dafault是设置默认值 表明既可以传值
  9. * 也可以不传,使用设置的默认值null
  10. * @return
  11. */
  12. String value() default "";
  13. }

两个Controller类:

TestController:

  1. package com.heaboy.Controller;
  2. import com.heaboy.annotation.Controller;
  3. import com.heaboy.annotation.RequestMapping;
  4. @Controller
  5. @RequestMapping("test")
  6. public class TestController {
  7. @RequestMapping
  8. public String index(){
  9. System.out.println("test->index");
  10. return "";
  11. }
  12. @RequestMapping("index1")
  13. public String index1(){
  14. System.out.println("test->index1");
  15. return "";
  16. }
  17. @RequestMapping("index2")
  18. public String index2(){
  19. System.out.println("test->index2");
  20. return "";
  21. }
  22. // @RequestMapping("index1")
  23. // public String index3(){
  24. // System.out.println("test->index3");
  25. // return "";
  26. // }
  27. }

IndexController类:

  1. package com.heaboy;
  2. import com.heaboy.annotation.Controller;
  3. import com.heaboy.annotation.RequestMapping;
  4. @Controller
  5. @RequestMapping
  6. public class IndexController {
  7. @RequestMapping
  8. public void index(){
  9. System.out.println("index->index");
  10. }
  11. @RequestMapping("index1")
  12. public String index1(){
  13. System.out.println("test->index111111");
  14. return "";
  15. }
  16. }

最重要的模拟mvc功能类:HeaboyMvc

  1. package com.heaboy.mvc;
  2. import com.heaboy.annotation.Controller;
  3. import com.heaboy.annotation.RequestMapping;
  4. import java.io.File;
  5. import java.lang.annotation.Annotation;
  6. import java.lang.ref.ReferenceQueue;
  7. import java.lang.reflect.InvocationTargetException;
  8. import java.lang.reflect.Method;
  9. import java.util.*;
  10. import java.util.regex.Matcher;
  11. /**
  12. * @author heaboy
  13. * mvc类
  14. */
  15. public class HeaboyMvc {
  16. private static HashMap<String, Map<String, Method>> map = new HashMap<>();
  17. // 创建一个静态的哈希映射,用于存储类路径和方法路径对应的Method对象
  18. private static HashMap<String, Object> objMap = new HashMap<>();
  19. // 创建一个静态的哈希映射,用于存储类路径和对应的实例对象
  20. public static void exec(String classPath, String methodPath) {
  21. // 定义一个公开的静态方法,用于执行指定类路径和方法路径的方法
  22. if (objMap.get(classPath) == null) {
  23. // 如果objMap中没有对应的类实例,则输出错误信息
  24. System.out.println("没有这个类 404");
  25. } else {
  26. // 如果有对应的类实例
  27. if (map.get(classPath).get(methodPath) == null) {
  28. // 如果map中没有对应的方法,则输出错误信息
  29. System.out.println("没有这个方法 404");
  30. } else {
  31. // 如果有对应的方法
  32. try {
  33. // 尝试调用该方法
  34. map.get(classPath).get(methodPath).invoke(objMap.get(classPath));
  35. } catch (IllegalAccessException e) {
  36. // 捕获调用方法时可能出现的异常,并打印堆栈跟踪信息
  37. e.printStackTrace();
  38. } catch (InvocationTargetException e) {
  39. // 捕获调用方法时可能出现的异常,并打印堆栈跟踪信息
  40. e.printStackTrace();
  41. }
  42. }
  43. }
  44. }
  45. public static void scanner(String path, String packageName) {
  46. // 定义一个公开的静态方法,用于扫描指定路径下的类文件,并处理注解
  47. List<String> paths = traverseFolder2(path);
  48. // 获取指定路径下所有的类文件路径
  49. for (String p : paths) {
  50. p = p.substring(path.length() - 1);
  51. // 从路径中截取类文件的相对部分
  52. try {
  53. String className = packageName + "." + p.replaceAll(Matcher.quoteReplacement(File.separator), ".");
  54. // 构造类的完整名称,包括包名和类名
  55. String replace = className.replace(".class", "");
  56. // 移除类名称后面的“.class”后缀
  57. Class<?> cl = ClassLoader.getSystemClassLoader().loadClass(replace);
  58. // 加载类文件到内存
  59. if (isController(cl)) {
  60. // 检查当前类是否为控制器
  61. if (isRequestMapping(cl)) {
  62. // 检查当前类是否包含RequestMapping注解
  63. RequestMapping requestMapping = getRequestMapping(cl);
  64. // 获取类的RequestMapping注解对象
  65. if (map.containsKey(requestMapping.value())) {
  66. // 如果map中已经包含了该注解值
  67. throw new RuntimeException("类多注解值:" + requestMapping.value());
  68. // 抛出运行时异常,表示类有多个注解值
  69. } else {
  70. // 如果没有包含该注解值
  71. map.put(requestMapping.value(), new HashMap<>());
  72. // 在map中添加一个新的映射项,key为注解值,value为一个新的HashMap
  73. objMap.put(requestMapping.value(), cl.newInstance());
  74. // 创建该类的实例,并存储在objMap中
  75. }
  76. Method[] declaredMethods = cl.getDeclaredMethods();
  77. // 获取类中声明的所有方法
  78. for (Method declaredMethod : declaredMethods) {
  79. // 遍历每个方法
  80. if (isRequestMapping(declaredMethod)) {
  81. // 如果方法包含RequestMapping注解
  82. RequestMapping mapping = getRequestMapping(declaredMethod);
  83. // 获取方法的RequestMapping注解对象
  84. if (map.get(requestMapping.value()).containsKey(mapping.value())) {
  85. // 如果map中已经包含了该方法注解值
  86. throw new RuntimeException("方法多注解值:" + requestMapping.value());
  87. // 抛出运行时异常,表示方法有多个注解值
  88. } else {
  89. // 如果没有包含该方法注解值
  90. map.get(requestMapping.value()).put(mapping.value(), declaredMethod);
  91. // 将方法存储在map中
  92. }
  93. }
  94. }
  95. } else {
  96. // 如果类不包含RequestMapping注解
  97. throw new RuntimeException("类无requestMapping");
  98. // 抛出运行时异常,表示类无RequestMapping注解
  99. }
  100. }
  101. } catch (ClassNotFoundException e) {
  102. e.printStackTrace();
  103. // 捕获类未找到异常,并打印堆栈跟踪信息
  104. } catch (IllegalAccessException e) {
  105. e.printStackTrace();
  106. // 捕获非法访问异常,并打印堆栈跟踪信息
  107. } catch (InstantiationException e) {
  108. e.printStackTrace();
  109. // 捕获实例化异常,并打印堆栈跟踪信息
  110. }
  111. }
  112. }
  113. private static boolean isController(Class cl) {
  114. // 定义一个私有的静态方法,用于检查类是否为控制器
  115. Annotation annotation = cl.getAnnotation(Controller.class);
  116. // 获取类的Controller注解对象
  117. if (annotation != null) {
  118. // 如果注解对象不为null
  119. return true;
  120. // 返回true,表示类为控制器
  121. }
  122. return false;
  123. // 返回false,表示类不是控制器
  124. }
  125. private static boolean isRequestMapping(Class cl) {
  126. // 定义一个私有的静态方法,用于检查类是否包含RequestMapping注解
  127. Annotation annotation = cl.getAnnotation(RequestMapping.class);
  128. // 获取类的RequestMapping注解对象
  129. if (annotation != null) {
  130. // 如果注解对象不为null
  131. return true;
  132. // 返回true,表示类包含RequestMapping注解
  133. }
  134. return false;
  135. // 返回false,表示类不包含RequestMapping注解
  136. }
  137. private static boolean isRequestMapping(Method method) {
  138. // 定义一个私有的静态方法,用于检查方法是否包含RequestMapping注解
  139. Annotation annotation = method.getAnnotation(RequestMapping.class);
  140. // 获取方法的RequestMapping注解对象
  141. if (annotation != null) {
  142. // 如果注解对象不为null
  143. return true;
  144. // 返回true,表示方法包含RequestMapping注解
  145. }
  146. return false;
  147. // 返回false,表示方法不包含RequestMapping注解
  148. }
  149. private static RequestMapping getRequestMapping(Class cl) {
  150. // 定义一个私有的静态方法,用于获取类的RequestMapping注解对象
  151. Annotation annotation = cl.getAnnotation(RequestMapping.class);
  152. // 获取类的RequestMapping注解对象
  153. if (annotation instanceof RequestMapping) {
  154. // 如果注解对象是RequestMapping类型
  155. return (RequestMapping) annotation;
  156. // 将注解对象强制转换为RequestMapping类型并返回
  157. }
  158. return null;
  159. // 返回null,表示类不包含RequestMapping注解
  160. }
  161. private static RequestMapping getRequestMapping(Method method) {
  162. // 定义一个私有的静态方法,用于获取方法的RequestMapping注解对象
  163. Annotation annotation = method.getAnnotation(RequestMapping.class);
  164. // 获取方法的RequestMapping注解对象
  165. if (annotation instanceof RequestMapping) {
  166. // 如果注解对象是RequestMapping类型
  167. return (RequestMapping) annotation;
  168. // 将注解对象强制转换为RequestMapping类型并返回
  169. }
  170. return null;
  171. // 返回null,表示方法不包含RequestMapping注解
  172. }
  173. private static List<String> traverseFolder2(String path) {
  174. // 定义一个私有的静态方法,用于遍历文件夹,获取所有类文件的路径
  175. File file = new File(path);
  176. // 创建文件对象
  177. List<String> classFiles = new ArrayList<>();
  178. // 创建一个列表,用于存储类文件路径
  179. if (file.exists()) {
  180. // 如果文件夹存在
  181. LinkedList<File> list = new LinkedList<File>();
  182. // 创建一个链表,用于存储子文件夹
  183. File[] files = file.listFiles();
  184. // 获取文件夹中的所有文件和子文件夹
  185. for (File file2 : files) {
  186. // 遍历每个文件和子文件夹
  187. if (file2.isDirectory()) {
  188. // 如果是子文件夹
  189. list.add(file2);
  190. // 将子文件夹添加到链表中
  191. } else {
  192. // 如果是文件
  193. classFiles.add(file2.getAbsolutePath());
  194. // 将文件的绝对路径添加到类文件路径列表中
  195. }
  196. }
  197. File temp_file;
  198. while (!list.isEmpty()) {
  199. // 当链表不为空时
  200. temp_file = list.removeFirst();
  201. // 移除链表中的第一个文件夹
  202. files = temp_file.listFiles();
  203. // 获取文件夹中的所有文件和子文件夹
  204. for (File file2 : files) {
  205. // 遍历每个文件和子文件夹
  206. if (file2.isDirectory()) {
  207. // 如果是子文件夹
  208. list.add(file2);
  209. // 将子文件夹添加到链表中
  210. } else {
  211. // 如果是文件
  212. classFiles.add(file2.getAbsolutePath());
  213. // 将文件的绝对路径添加到类文件路径列表中
  214. }
  215. }
  216. }
  217. } else {
  218. // 如果文件夹不存在
  219. System.out.println("路径不存在");
  220. }
  221. return classFiles;
  222. // 返回类文件路径列表
  223. }
  224. // 结束 traverseFolder2 方法
  225. }

测试类:Main

  1. package com.heaboy;
  2. import com.heaboy.mvc.HeaboyMvc;
  3. public class Main {
  4. static {
  5. String path = Main.class.getResource("").getPath();
  6. String packageName = Main.class.getPackage().getName();
  7. HeaboyMvc.scanner(path,packageName);
  8. }
  9. public static void main(String[] args) {
  10. HeaboyMvc.exec("","");
  11. HeaboyMvc.exec("test","index1");
  12. HeaboyMvc.exec("test","index2");
  13. HeaboyMvc.exec("test","");
  14. HeaboyMvc.exec("test","dadasdadad");
  15. HeaboyMvc.exec("","index1");
  16. }
  17. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/820955
推荐阅读
相关标签
  

闽ICP备14008679号