目录结构:
两个注解类:
@Controller:
java
复制代码
package com.heaboy.annotation;
import java.lang.annotation.*;
/**
* 注解没有功能只是简单标记
* .RUNTIME 运行时还能看到
* .CLASS 类里面还有,构建对象久没来了,这个说明是给类加载器的
* .SOURCE 表示这个注解能存活到哪一阶段(源码阶段)仅在 .java阶段有用 也就是仅在编译阶段有
* 用
* 是让编译器去看的
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Controller {
}
@RequestMapping:
java
复制代码
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:
java
复制代码
package com.heaboy.Controller;
import com.heaboy.annotation.Controller;
import com.heaboy.annotation.RequestMapping;
@Controller
@RequestMapping("test")
public class TestController {
@RequestMapping
public 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类:
java
复制代码
package com.heaboy;
import com.heaboy.annotation.Controller;
import com.heaboy.annotation.RequestMapping;
@Controller
@RequestMapping
public class IndexController {
@RequestMapping
public void index(){
System.out.println("index->index");
}
@RequestMapping("index1")
public String index1(){
System.out.println("test->index111111");
return "";
}
}
最重要的模拟mvc功能类:HeaboyMvc
java
复制代码
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为一个新的HashMap
objMap.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) {
// 如果注解对象不为null
return true;
// 返回true,表示类为控制器
}
return false;
// 返回false,表示类不是控制器
}
private static boolean isRequestMapping(Class cl) {
// 定义一个私有的静态方法,用于检查类是否包含RequestMapping注解
Annotation annotation = cl.getAnnotation(RequestMapping.class);
// 获取类的RequestMapping注解对象
if (annotation != null) {
// 如果注解对象不为null
return true;
// 返回true,表示类包含RequestMapping注解
}
return false;
// 返回false,表示类不包含RequestMapping注解
}
private static boolean isRequestMapping(Method method) {
// 定义一个私有的静态方法,用于检查方法是否包含RequestMapping注解
Annotation annotation = method.getAnnotation(RequestMapping.class);
// 获取方法的RequestMapping注解对象
if (annotation != null) {
// 如果注解对象不为null
return 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
java
复制代码
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");
}
}