目錄結構:

?兩個注解類:
@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");}
}