项目结构
Main类
public class Main { //类一加载就执行这个静态块 static { //当前类所在目录 String path = Main.class.getResource("").getPath(); //当前类所在包名 String packageName = Main.class.getPackage().getName(); Mvc.scanner(path,packageName); } public static void main(String[] args) { Mvc.exec("",""); Mvc.exec("test","index1"); Mvc.exec("test",""); System.out.println("Hello World!"); } }
我们执行程序从这个类开始,类加载的时候,先执行静态块(扫描所有的文件,把类文件的实例和类文件的方法 用HashMap存起来)
main方法中的exec是模拟调用接口,第一个参数是类的@RequestMapping的value值,第二个参数是方法的@ReqeustMapping的value值
MVC
package com.test.mvc; import com.test.annotation.Controller; import com.test.annotation.RequestMapping; import java.io.File; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; import java.util.regex.Matcher; /** * @author sangyinghao * mvc类 */ public class Mvc { //存类的方法 private static HashMap<String, Map<String,Method>> map=new HashMap<>(); //存类的实例 private static HashMap<String, Object> objMap=new HashMap<>(); public static void exec(String classPath,String methodPath){ if(objMap.get(classPath)==null){ System.out.println("没有这个类 404"); }else { if(map.get(classPath).get(methodPath)==null){ 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<?> cl = ClassLoader.getSystemClassLoader().loadClass(replace); //判断是Controller吗 if(isController(cl)){ //判断是否加RequestMapping if(isRequestMapping(cl)){ //拿到注解 RequestMapping requestMapping = getRequestMapping(cl); //判断注解中的值是否有重复 if(map.containsKey(requestMapping.value())){ throw new RuntimeException("类多注解值:"+requestMapping.value()); }else { //没有重复就把类放两个map进去 map.put(requestMapping.value(),new HashMap<>()); objMap.put(requestMapping.value(),cl.newInstance()); } //拿到类中的方法 Method[] declaredMethods = cl.getDeclaredMethods(); //遍历类中的方法 for (Method declaredMethod : declaredMethods) { if(isRequestMapping(declaredMethod)){ RequestMapping mapping = getRequestMapping(declaredMethod); if(map.get(requestMapping.value()).containsKey(mapping.value())){ throw new RuntimeException("方法多注解值:"+requestMapping.value()); }else { //把当前类的方法存起来 map.get(requestMapping.value()).put(mapping.value(),declaredMethod); } } } }else { throw new RuntimeException("类无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); if(annotation!=null){ return true; } return false; } private static boolean isRequestMapping(Class cl){ Annotation annotation = cl.getAnnotation(RequestMapping.class); if(annotation!=null){ return true; } return false; } private static boolean isRequestMapping(Method method){ Annotation annotation = method.getAnnotation(RequestMapping.class); if(annotation!=null){ return true; } return false; } private static RequestMapping getRequestMapping(Class cl){ Annotation annotation = cl.getAnnotation(RequestMapping.class); if(annotation instanceof RequestMapping){ return (RequestMapping) annotation; } return null; } private static RequestMapping getRequestMapping(Method method){ Annotation annotation = method.getAnnotation(RequestMapping.class); if(annotation instanceof RequestMapping){ return (RequestMapping) annotation; } return null; } private static List<String> traverseFolder2(String path) { //路径转为文件 File file = new File(path); List<String> classFiles=new ArrayList<>(); if (file.exists()) { //新建list用来存放文件夹 LinkedList<File> list = new LinkedList<File>(); File[] files = file.listFiles(); //遍历 for (File file2 : files) { //只要是文件夹就添加进list if (file2.isDirectory()) { list.add(file2); } else { //不是文件夹就放到clssFiles中 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 { } //获得了所有的文件的路径 return classFiles; } }
大致思想:
- 先扫包,如果是文件夹就放到list中,如果不是文件夹就是文件就放到classFiles中,判断list是否为空,如果不为空就把存进的文件夹的文件展示出来继续遍历,同时把此文件夹从list中取出,经过几次之后,就可以获得所有得到类文件的路径
- 遍历classFiles,拿到包名,对遍历出的类文件的路径进行替换和截取,获得了类的全限定名,判断加没加@Controller注解,再判断加没加@RequestMapping注解,判断@RequeatMapping注解中的value是否重复,如果不重复就把此value存起来,并对此类中的方法进行遍历,如果方法加了@RequestMapping,就用map把方法的value也存起来
//存类的方法 //第一个String是类的@RequestMapping中的value值,第二个String是方法的@RequestMapping中的value值 private static HashMap<String, Map<String,Method>> map=new HashMap<>(); //存类的实例 private static HashMap<String, Object> objMap=new HashMap<>();
注解
Controller注解
/** * test 的controller声明 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @ interface Controller { }
RequestMapping注解
/** * @author sangyinghao * */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE,ElementType.METHOD}) public @interface RequestMapping { /** * * @return */ String value() default ""; }
TestController
@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 ""; } }