手寫簡單模擬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.pswp.cn/diannao/43190.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43190.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43190.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

掌握Vue 3生命周期:從組合式API到高效代碼實踐

引言 在 Vue 3 中&#xff0c;生命周期的概念得到了進一步的優化和簡化。Vue 3 引入了組合式 API&#xff08;Composition API&#xff09;&#xff0c;這為開發者提供了更靈活的方式來組織和重用代碼邏輯。與傳統的選項式 API&#xff08;Options API&#xff09;相比&#x…

node-sass 老版本4.14.0 安裝失敗解決辦法

舊項目 npm install 發現 node-sass 安裝 失敗 切換淘寶鏡像之后 不能完全解決問題。因為需要編譯&#xff0c;本地沒有Python環境不能實現 安裝node-sass時&#xff0c;在install階段會從Github上下載一個叫binding.node的文件&#xff0c;而「GitHub Releases」里的文件…

C++編譯鏈接原理

從底層剖析程序從編譯到運行的整個過程 三個階段 一、編譯階段二、鏈接階段三、運行階段 為了方便解釋&#xff0c;給出兩端示例代碼&#xff0c;下面圍繞代碼進行實驗&#xff1a; //sum.cpp int gdata 10; int sum(int a,int b) {return ab; }//main.cpp extern int gdata…

Stream流的簡單用法

filter //stream流中的filter //filter 方法用于通過設置的條件過濾出元素。以下代碼片段使用 filter 方法過濾掉空字符串&#xff1a; List<String> filter Arrays.asList("mz", "", "mz55", "m", "MZ"); Stream&l…

初始redis:在Ubuntu上安裝redis

1.先切換到root用戶 使用su命令切換到root 2.使用apt命令來搜索redis相關的軟件包 命令&#xff1a;apt search redis 3.下載redis 命令&#xff1a; apt install redis 在Ubuntu 20.04中 &#xff0c;下載的redis版本是redis5 4.查看redis狀態 命令&#xff1a; netst…

Python自動化測試系列[v1.0.0][高效自動化設計]

Python多線程應用于自動化測試 將多線程在測試巧妙地應用&#xff0c;確實會帶來很多好處&#xff0c;并且這是充分利用機器資源執行高效率測試很好的方式 # -*- coding: utf-8 -*- import threading from time import ctime import time from selenium import webdriverdef …

LLM 入門與實踐(四) Yi 部署與分析

本文截取自20萬字的《PyTorch實用教程》&#xff08;第二版&#xff09;&#xff0c;敬請關注&#xff1a;《Pytorch實用教程》&#xff08;第二版&#xff09;無論是零基礎入門&#xff0c;還是CV、NLP、LLM項目應用&#xff0c;或是進階工程化部署落地&#xff0c;在這里都有…

python對象

類 我們目前所學習的對象都是Python內置的對象但是內置對象并不能滿足所有的需求&#xff0c;所以我們在開發中經常需要自定義一些對象類&#xff0c;簡單理解它就相當于一個圖紙。在程序中我們需要根據類來創建對象類就是對象的圖紙&#xff01;我們也稱對象是類的實例&#…

JAVA--IO流

一、IO流什么&#xff1f; I/O是Input/output的縮寫&#xff0c;用于處理設備之間的數據傳輸。如讀/寫文件、網絡通訊。 java程序中&#xff0c;對于數據的輸入、輸出是以流&#xff08;Stream)的方式進行。 Java.io包下提供了各種流類和接口&#xff0c;用以獲取不同種類的數…

web自動化(六)unittest 測試報告跳過用例

三種類型測試報告&#xff1a;unittest.TextTestRunner、BeautifulReport、HTMLTestRunner Python3.0 無法直接安裝 HTMLTestRunner 安裝 XTestRunner pip install XTestRunner安裝 BeautifulReport pip install BeautifulReportimport unittestclass TestSkipCase(unittest…

ELfK logstash filter模塊常用的插件 和ELFK部署

ELK之filter模塊常用插件 logstash filter模塊常用的插件&#xff1a; filter&#xff1a;表示數據處理層&#xff0c;包括對數據進行格式化處理、數據類型轉換、數據過濾等&#xff0c;支持正則表達式 grok 對若干個大文本字段進行再分割成一些小字段 (?<字段名…

【算法篇】KMP算法,一種高效的字符串匹配算法

我們今天了解一個字符串匹配算法-KMP算法&#xff0c;內容難度相對來說較高&#xff0c;建議先收藏再細品&#xff01;&#xff01;&#xff01; KMP算法的基本概念 KMP算法是一種高效的字符串匹配算法&#xff0c;由D.E.Knuth&#xff0c;J.H.Morris和V.R.Pratt提出的&#…

LLMs之gptpdf:gptpdf的簡介、安裝和使用方法、案例應用之詳細攻略

LLMs之gptpdf&#xff1a;gptpdf的簡介、安裝和使用方法、案例應用之詳細攻略 目錄 gptpdf的簡介 1、處理流程 第一步&#xff0c;使用 PyMuPDF 庫&#xff0c;對 PDF 進行解析出所有非文本區域&#xff0c;并做好標記&#xff0c;比如: 第二步&#xff0c;使用視覺大模型&…

離婚后,孩子就讀私立高中的高昂學費誰承擔?

江蘇省南京市六合區人民法院審結一起撫養費糾紛案件&#xff0c;認定夫妻雙方在決定孩子教育事務上均存在責任&#xff0c;為保障臨近高考的未成年子女的切身利益&#xff0c;認定由夫妻雙方按比例承擔教育費。   2015年6月&#xff0c;李某與王某離婚&#xff0c;雙方之子小…

PCL 有序點云的法線估計(使用積分圖進行法線估計)

使用積分圖進行法線估計 一、概述1.1 概念1.2 有序點云與無序點云1.2.1 有序點云1.2.2 無序點云1.3 代碼講解二、代碼實現三、結果示例一、概述 1.1 概念 使用積分圖進行法線估計:計算一個有序點云的法線,注意該方法只適用于有序點云。 1.2 有序點云與無序點云 有序點云與無…

MySQL安裝時initializing database失敗

問題頁面&#xff1a; 解決方法&#xff1a; 1.勾選紅框中的選項&#xff1a; 2.將下圖紅框中全部改為英文&#xff1a; 然后一路next就可以了。

cs231n作業1——KNN

參考文章&#xff1a;assignment1——KNN KNN 測試時分別計算測試樣本和訓練集中的每個樣本的距離&#xff0c;然后選取距離最近的k個樣本的標簽信息來進行分類。 方法1&#xff1a;Two Loops for i in range(num_test):for j in range(num_train):dist X[i, :] - self.X…

vue3使用方式匯總

1、引入iconfont阿里圖庫圖標&#xff1a; 1.1 進入阿里圖標網站&#xff1a; iconfont阿里&#xff1a;https://www.iconfont.cn/ 1.2 添加圖標&#xff1a; 1.3 下載代碼&#xff1a; 1.4 在vue3中配置代碼&#xff1a; 將其代碼復制到src/assets/fonts/目錄下&#xff1…

Mysql之Using index for skip scan

一、Using index for skip scan 在 MySQL 中&#xff0c;EXPLAIN 語句用于顯示查詢執行計劃&#xff0c;幫助我們理解查詢是如何被執行的&#xff0c;以及如何優化查詢。其中&#xff0c;Extra 列提供了關于查詢執行的一些額外信息。當 Extra 列顯示 Using index for skip sca…

CF F. Alex‘s whims

原題鏈接&#xff1a;Problem - 1899F - Codeforces 題目大意&#xff1a;要求構建出一顆樹&#xff0c;多次詢問樹的葉節點之間的距離有沒有達到要求的距離&#xff0c;如果有直接輸出-1 -1 -1&#xff0c;如果沒有可以斷開一條邊和連上一條邊&#xff0c;輸出x y z&#xff…