仿写SpringMVC中的注解和方法映射功能

本项目已开源,欢迎各位大佬访问并指正:仿写SpringMVC中的注解和方法映射功能


文章目录

    • 一、仿写流程
      • 1、初始化
      • 2、测试
    • 二、代码实现
      • 1、自定义注解Controller和RequestMapping
      • 2、扫描本项目下Controller下所有的java文件
      • 3、识别注解,完成映射
      • 4、编写Controller,准备测试
      • 5、初始化并编写main方法,开始测试
      • 6、执行,测试结果

一、仿写流程

1、初始化

  • 通过扫描某路径下的文件夹和文件 通过字符串处理得到全限定名
    • 传入指定包的地址
    • 输出 List 里边的所有java文件(”.java")
  • 反射创建对象
    • url->对象 Map
  • 识别是否有我们所需的注解,并获取注解内的值
    • 识别类上的注解Controller
    • 识别类上的注解RequestMapping,并获取value值
    • 识别该类中方法上的注解RequestMapping,并获取value值
  • 需要构建 每个类每个方法对应url的映射结构

2、测试

  • 编写自定义注解和测试类
  • 编写测试main方法,传入请求访问路径和方法,执行

二、代码实现

1、自定义注解Controller和RequestMapping

有关知识请直接点我借一步说话

  • Controller
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
	//类型+名称+默认值
    String value() default "user";
}
  • RequestMapping
@Target(value ={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
	String value() default "index";
}

2、扫描本项目下Controller下所有的java文件

有关知识请移步

public class GetAllFiles {
	static int count = 0;
	public static List<String> getAllFiles(String path) {
		System.out.println(path);
		List<String> qualifiedPaths = new ArrayList<String>();
		String fileType = ".java";// 指定文件类型
        File file = new File(path);
        
        long start = System.currentTimeMillis();
        listAllFiles(file, fileType, qualifiedPaths);
        long end = System.currentTimeMillis();
        System.out.println("共花费:" + (end - start) + "毫秒");
        System.out.println("有" + count + "个文件");
        return qualifiedPaths;
	}
	public static void listAllFiles(File file, String fileType, List<String> qualifiedPaths){
        if (file.isFile()){
            count++;
            System.out.println(file);

            String path = file.getPath().replace('\\', '.');
            int begin = path.indexOf("Controller");
            int end = path.indexOf(".java");
            String qualifiedPath = path.substring(begin, end);
            qualifiedPaths.add(qualifiedPath);
            System.out.println(qualifiedPath);
        } else {
            if (file.exists() && file.isDirectory()){
                File[] files = file.listFiles();
                for (File file1 : files){
                    listAllFiles(file1, fileType,qualifiedPaths);
                }
            }
        }
    }
}

3、识别注解,完成映射

public class SpringMVC {
	//设置mapobj,key:拥有Controller注解的类的RequestMapping值,value:拥有Controller注解的类的class类实例
	//记录注解value值和Controller类的class实例的映射
	private static Map<String, Object> mapobj = new HashMap<String, Object>();
	//设置map,key:Controller类的RequestMapping的vaule值,
	//value:记录RequestMapping的value值和对应方法的映射
	private static Map<String, HashMap<String, Method>> map = new HashMap<>();
	
	//模拟服务器中DispatherServlet对前端传来的请求路径进行转发给各个Controller
	 public static void exec(String classPath,String methodPath){
	        if(mapobj.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(mapobj.get(classPath));
	            } catch (IllegalAccessException e) {
	                e.printStackTrace();
	            } catch (InvocationTargetException e) {
	                e.printStackTrace();
	            }
	        }
	    }
	
	}
	public static void springmvc(String path) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		path = "D:\\appdata\\ssm-workspace\\Spring\\src\\Controller";
		
		List<String> classNames = GetAllFiles.getAllFiles(path);

		for (String className:classNames) {
			Class cl = Class.forName(className);
			//System.out.println(cl.getName());
			
			//观察该类的所有注解,没鸟用,纯闲的
			Annotation[] annotations = cl.getAnnotations();
	        for (Annotation annotation : annotations) {
	            System.out.println(annotation);
	        }
	        
	        //判断java文件是否是Controller
	        Controller controller = (Controller) cl.getAnnotation(Controller.class);
	        if (controller!=null) {
	        	//如果是Controller,找到注解在该类上的RequestMapping中的value值,将映射加入到mapobj,将value值加入到map的key中
	        	RequestMapping mapping = (RequestMapping) cl.getAnnotation(RequestMapping.class);
	        	mapobj.put(mapping.value(), cl.newInstance());
	        	map.put(mapping.value(), new HashMap<String, Method>());
	        	//遍历其中的所有方法,将每一个方法上的RequestMapping注解的value值和该方法完成映射绑定
	        	Method[] methods = cl.getDeclaredMethods(); 
				for (Method m:methods) {
					Annotation[] annotations_m = m.getAnnotations();
					for (Annotation annotation : annotations_m) {
			            RequestMapping requestMapping = (RequestMapping) m.getAnnotation(RequestMapping.class);
			            map.get(mapping.value()).put(requestMapping.value(), m);
			        }
				}
	        }
		}
		//System.out.println(map.size());
		System.out.println("映射结果:");
		//1. 使用keySet方法遍历key,再通过key获取value
        for(String key:map.keySet()){  
            System.out.println(key+" "+map.get(key));
        }
		
	}
}

4、编写Controller,准备测试

  • 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 "";
    }
}
  • TestController2类
@Controller
@RequestMapping("test2")
public class TestController2 {
	@RequestMapping("index2")
	public void index2() {
		System.out.println("test2->index2");
	}
}

5、初始化并编写main方法,开始测试

public class Main {

	static {
		String path = Main.class.getResource("").getPath();
        String packageName = Main.class.getPackage().getName();
        String scannerPath = path.replaceAll(packageName, "Controller");
        try {
			SpringMVC.springmvc(scannerPath);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		System.out.println("测试结果:");
		SpringMVC.exec("test", "index");
		SpringMVC.exec("test", "index1");
		SpringMVC.exec("test2", "index2");
	}

}

6、执行,测试结果

在这里插入图片描述
可以看到完整的映射结果,几个样例的执行也没有问题,扣一波牛波一!!!

你可能感兴趣的:(spring,SpringMVC,反射)