当前位置:   article > 正文

简单仿写MVC

简单仿写MVC

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

项目目录

先把架子搭好

Controller注解

  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target(ElementType.TYPE)
  4. public @ interface Controller {
  5. }

RequestMapping

  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target({ElementType.TYPE,ElementType.METHOD})
  4. public @interface RequestMapping {
  5. /**
  6. *
  7. * @return
  8. */
  9. String value() default "";
  10. }

HydController

  1. @Controller
  2. @RequestMapping("hyd")
  3. public class HydController {
  4. @RequestMapping
  5. public String index(){
  6. System.out.println("RequestMapping为“hyd, ”的方法已执行");
  7. return "";
  8. }
  9. @RequestMapping("hyd2")
  10. public String index1(){
  11. System.out.println("RequestMapping为“hyd,hyd2”的方法已执行");
  12. return "";
  13. }
  14. }

indexController

  1. @Controller
  2. @RequestMapping
  3. public class IndexController {
  4. @RequestMapping
  5. public void index() {
  6. System.out.println("RequestMapping为“ , ”的方法已执行");
  7. }
  8. }

Main

  1. public class Main {
  2. static {
  3. // 获取Main的路径
  4. String path = Main.class.getResource("").getPath();
  5. // 获取Main的包名
  6. String packageName = Main.class.getPackage().getName();
  7. HydMVC.scanner(path, packageName);
  8. }
  9. public static void main(String[] args) {
  10. HydMVC.mehtod_go("","");
  11. HydMVC.mehtod_go("hyd","");
  12. HydMVC.mehtod_go("hyd","hyd2");
  13. HydMVC.mehtod_go("232323","23131");
  14. HydMVC.mehtod_go("hyd","23131");
  15. }
  16. }

HydMVC

  1. public class HydMVC {
  2. // 存放 一级注解-二级注解-方法 的map
  3. private static HashMap<String,HashMap<String, Method>> map_method = new HashMap<>();
  4. // 存放 一级注解-类的实例化对象 的map
  5. private static HashMap<String, Object> map_object = new HashMap<>();
  6. /**
  7. * 方法执行函数
  8. * @param first_path 第一路径
  9. * @param second_path 第二路径
  10. */
  11. public static void mehtod_go(String first_path,String second_path){
  12. // 如果map_object中没有fisrt_path,则不存在该注解的类
  13. if (map_object.get(first_path)==null){
  14. System.out.println("没有一个类有"+first_path+"注解");
  15. }else {
  16. if (map_method.get(first_path).get(second_path)==null){
  17. System.out.println(first_path+"下没有"+second_path+"注解"+"的方法");
  18. }else{
  19. try {
  20. map_method.get(first_path).get(second_path).invoke(map_object.get(first_path));
  21. } catch (IllegalAccessException e) {
  22. e.printStackTrace();
  23. } catch (InvocationTargetException e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. }
  28. }
  29. /**
  30. * 扫描获取类实例化对象以及方法
  31. * @param path
  32. * @param packageName 包名
  33. */
  34. public static void scanner(String path,String packageName){
  35. // 扫描当前所有的文件
  36. List<String> paths = traverseFolder2(path);
  37. // 遍历拿到的文件路径
  38. for (String path1 : paths) {
  39. // path1为:C:\ttt\imitating_spring_mvc\out\production\imitating_spring_mvc\com\heaboy\IndexController.class
  40. // 先拿到文件名 例:IndexController.class
  41. path1=path1.substring(path.length()-1);
  42. try{
  43. // 构建类名
  44. // 因为可能存在多级路径,例如:www/IndexController.class,所以还需要进行一些小处理,不能直接拼接
  45. // File.separator代表文件分隔符
  46. // Matcher.quoteReplacement确保了文件分隔符在替换过程中被正确地转义,以防包含任何正则表达式的特殊字符。它返回一个适合用于正则表达式替换的字符串。
  47. String ClassName = packageName + "." + path1.replaceAll(Matcher.quoteReplacement(File.separator),".");
  48. // 去掉文件名中的.class后缀
  49. String load_className = ClassName.replace(".class","");
  50. // 通过类加载器加载类
  51. Class<?> cl = ClassLoader.getSystemClassLoader().loadClass(load_className);
  52. // 用写好的检查注解方法(isController)判断cl是否有Controller注解
  53. if(isController(cl)){
  54. // 用写好的检查注解方法(isRequestMapping)判断cl是否有RequestMapping注解
  55. if (isRequestMapping(cl)){
  56. // 如果有就获取类上RequestMapping注解的实例
  57. RequestMapping requestMapping_first = getRequestMapping(cl);
  58. // 判断map_method中是否已经存在了该一级注解
  59. if (map_method.containsKey(requestMapping_first.value())){
  60. // 已经存在该一级注解,则抛出异常
  61. throw new RuntimeException("包含多个注解:"+requestMapping_first.value());
  62. }else {
  63. // 不存在,添加至map_method
  64. map_method.put(requestMapping_first.value(),new HashMap<>());
  65. // 添加类的实例化对象到
  66. map_object.put(requestMapping_first.value(),cl.newInstance());
  67. }
  68. // 获取类中所有的方法
  69. Method[] declareMethods = cl.getDeclaredMethods();
  70. // 遍历所有方法
  71. for (Method method : declareMethods) {
  72. if (isRequestMapping(method)){
  73. RequestMapping requestMapping_second = getRequestMapping(method);
  74. // 判断该二级注解是否已经存在
  75. if (map_method.get(requestMapping_first.value()).containsKey(requestMapping_second.value())){
  76. // 存在抛出错误
  77. throw new RuntimeException("方法注解已经存在:"+requestMapping_second.value());
  78. }else {
  79. // 不存在就将方法放入map_method
  80. map_method.get(requestMapping_first.value()).put(requestMapping_second.value(),method);
  81. }
  82. }
  83. }
  84. }else{
  85. throw new RuntimeException("该类有没RequestMapping注解");
  86. }
  87. }
  88. }catch (Exception e){
  89. System.out.println(e);
  90. }
  91. }
  92. }
  93. /**
  94. * 扫描文件
  95. * @param path 绝对路径
  96. * @return List<String> 文件绝对路径集合
  97. * C:\ttt\imitating_spring_mvc\out\production\imitating_spring_mvc\com\heaboy\IndexController.class
  98. */
  99. private static List<String> traverseFolder2(String path) {
  100. // 当前路径下的文件和文件夹
  101. File file = new File(path);
  102. // 返回的文件集合
  103. List<String> file_list = new ArrayList<>();
  104. if (file.exists()){
  105. // 放文件夹
  106. LinkedList<File> list = new LinkedList<>();
  107. // 存储过程中要处理的文件
  108. File[] files = file.listFiles();
  109. for (File file1 : files) {
  110. // 如果当前文件是文件夹就把它放到list里面
  111. if (file1.isDirectory()){
  112. list.add(file1);
  113. }else { //不是就将该文件的绝对路径放到返回列表中file_list
  114. file_list.add(file1.getAbsolutePath());
  115. }
  116. }
  117. // 申请一个临时变量
  118. File file_temp;
  119. // 当存放文件夹的队列不为空时,执行以下操作
  120. while (!list.isEmpty()){
  121. // 取出第一个文件夹来处理
  122. file_temp=list.removeFirst();
  123. // 使用上面申请的FIle[]来存放file_temp中的文件
  124. files=file_temp.listFiles();
  125. // 处理files中的文件,同上,文件夹放到list中,文件放到file_list中
  126. for (File file1 : files) {
  127. if (file1.isDirectory()){
  128. list.add(file1);
  129. }else {
  130. file_list.add(file1.getAbsolutePath());
  131. }
  132. }
  133. }
  134. }else{
  135. // 如果没有任何文件,则不做处理
  136. }
  137. return file_list;
  138. }
  139. // 判断类是否有Controller注解
  140. private static boolean isController(Class cl){
  141. Annotation annotation = cl.getAnnotation(Controller.class);
  142. if(annotation!=null){
  143. return true;
  144. }
  145. return false;
  146. }
  147. // 判断类是否有RequestMapping注解
  148. private static boolean isRequestMapping(Class cl){
  149. Annotation annotation = cl.getAnnotation(RequestMapping.class);
  150. if(annotation!=null){
  151. return true;
  152. }
  153. return false;
  154. }
  155. // 获取类的RequestMapping注解的实例
  156. private static RequestMapping getRequestMapping(Class<?> cl) {
  157. Annotation annotation = cl.getAnnotation(RequestMapping.class);
  158. if (annotation instanceof RequestMapping){
  159. return (RequestMapping) annotation;
  160. }
  161. return null;
  162. }
  163. // 判断方法是否有RequestMapping注解
  164. private static boolean isRequestMapping(Method method) {
  165. Annotation annotation = method.getAnnotation(RequestMapping.class);
  166. if (annotation!=null){
  167. return true;
  168. }
  169. return false;
  170. }
  171. // 获取方法上的RequestMapping注解的实例
  172. private static RequestMapping getRequestMapping(Method method) {
  173. Annotation annotation = method.getAnnotation(RequestMapping.class);
  174. if (annotation instanceof RequestMapping){
  175. return (RequestMapping) annotation;
  176. }
  177. return null;
  178. }
  179. }

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

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

闽ICP备14008679号