赞
踩
代码地址(需要自取):mvc_Imitation: 简单仿写实现MVC (gitee.com)
项目目录
先把架子搭好
Controller注解
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- public @ interface Controller {
- }
RequestMapping
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.TYPE,ElementType.METHOD})
- public @interface RequestMapping {
- /**
- *
- * @return
- */
- String value() default "";
- }
HydController
- @Controller
- @RequestMapping("hyd")
- public class HydController {
- @RequestMapping
- public String index(){
- System.out.println("RequestMapping为“hyd, ”的方法已执行");
- return "";
- }
- @RequestMapping("hyd2")
- public String index1(){
- System.out.println("RequestMapping为“hyd,hyd2”的方法已执行");
- return "";
- }
- }
indexController
- @Controller
- @RequestMapping
- public class IndexController {
- @RequestMapping
- public void index() {
- System.out.println("RequestMapping为“ , ”的方法已执行");
- }
- }
Main
- public class Main {
- static {
- // 获取Main的路径
- String path = Main.class.getResource("").getPath();
- // 获取Main的包名
- String packageName = Main.class.getPackage().getName();
-
- HydMVC.scanner(path, packageName);
- }
-
- public static void main(String[] args) {
- HydMVC.mehtod_go("","");
- HydMVC.mehtod_go("hyd","");
- HydMVC.mehtod_go("hyd","hyd2");
- HydMVC.mehtod_go("232323","23131");
- HydMVC.mehtod_go("hyd","23131");
- }
-
- }
HydMVC
- public class HydMVC {
- // 存放 一级注解-二级注解-方法 的map
- private static HashMap<String,HashMap<String, Method>> map_method = new HashMap<>();
- // 存放 一级注解-类的实例化对象 的map
- private static HashMap<String, Object> map_object = new HashMap<>();
-
- /**
- * 方法执行函数
- * @param first_path 第一路径
- * @param second_path 第二路径
- */
- public static void mehtod_go(String first_path,String second_path){
- // 如果map_object中没有fisrt_path,则不存在该注解的类
- if (map_object.get(first_path)==null){
- System.out.println("没有一个类有"+first_path+"注解");
- }else {
- if (map_method.get(first_path).get(second_path)==null){
- System.out.println(first_path+"下没有"+second_path+"注解"+"的方法");
- }else{
- try {
- map_method.get(first_path).get(second_path).invoke(map_object.get(first_path));
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- /**
- * 扫描获取类实例化对象以及方法
- * @param path
- * @param packageName 包名
- */
- public static void scanner(String path,String packageName){
- // 扫描当前所有的文件
- List<String> paths = traverseFolder2(path);
- // 遍历拿到的文件路径
- for (String path1 : paths) {
- // path1为:C:\ttt\imitating_spring_mvc\out\production\imitating_spring_mvc\com\heaboy\IndexController.class
- // 先拿到文件名 例:IndexController.class
- path1=path1.substring(path.length()-1);
- try{
- // 构建类名
- // 因为可能存在多级路径,例如:www/IndexController.class,所以还需要进行一些小处理,不能直接拼接
- // File.separator代表文件分隔符
- // Matcher.quoteReplacement确保了文件分隔符在替换过程中被正确地转义,以防包含任何正则表达式的特殊字符。它返回一个适合用于正则表达式替换的字符串。
- String ClassName = packageName + "." + path1.replaceAll(Matcher.quoteReplacement(File.separator),".");
- // 去掉文件名中的.class后缀
- String load_className = ClassName.replace(".class","");
- // 通过类加载器加载类
- Class<?> cl = ClassLoader.getSystemClassLoader().loadClass(load_className);
- // 用写好的检查注解方法(isController)判断cl是否有Controller注解
- if(isController(cl)){
- // 用写好的检查注解方法(isRequestMapping)判断cl是否有RequestMapping注解
- if (isRequestMapping(cl)){
- // 如果有就获取类上RequestMapping注解的实例
- RequestMapping requestMapping_first = getRequestMapping(cl);
- // 判断map_method中是否已经存在了该一级注解
- if (map_method.containsKey(requestMapping_first.value())){
- // 已经存在该一级注解,则抛出异常
- throw new RuntimeException("包含多个注解:"+requestMapping_first.value());
- }else {
- // 不存在,添加至map_method中
- map_method.put(requestMapping_first.value(),new HashMap<>());
- // 添加类的实例化对象到
- map_object.put(requestMapping_first.value(),cl.newInstance());
- }
- // 获取类中所有的方法
- Method[] declareMethods = cl.getDeclaredMethods();
- // 遍历所有方法
- for (Method method : declareMethods) {
- if (isRequestMapping(method)){
- RequestMapping requestMapping_second = getRequestMapping(method);
- // 判断该二级注解是否已经存在
- if (map_method.get(requestMapping_first.value()).containsKey(requestMapping_second.value())){
- // 存在抛出错误
- throw new RuntimeException("方法注解已经存在:"+requestMapping_second.value());
- }else {
- // 不存在就将方法放入map_method
- map_method.get(requestMapping_first.value()).put(requestMapping_second.value(),method);
- }
- }
- }
- }else{
- throw new RuntimeException("该类有没RequestMapping注解");
- }
- }
- }catch (Exception e){
- System.out.println(e);
- }
- }
-
- }
-
-
-
- /**
- * 扫描文件
- * @param path 绝对路径
- * @return List<String> 文件绝对路径集合
- * C:\ttt\imitating_spring_mvc\out\production\imitating_spring_mvc\com\heaboy\IndexController.class
- */
- private static List<String> traverseFolder2(String path) {
- // 当前路径下的文件和文件夹
- File file = new File(path);
- // 返回的文件集合
- List<String> file_list = new ArrayList<>();
-
- if (file.exists()){
- // 放文件夹
- LinkedList<File> list = new LinkedList<>();
-
- // 存储过程中要处理的文件
- File[] files = file.listFiles();
-
- for (File file1 : files) {
- // 如果当前文件是文件夹就把它放到list里面
- if (file1.isDirectory()){
- list.add(file1);
- }else { //不是就将该文件的绝对路径放到返回列表中file_list
- file_list.add(file1.getAbsolutePath());
- }
- }
- // 申请一个临时变量
- File file_temp;
- // 当存放文件夹的队列不为空时,执行以下操作
- while (!list.isEmpty()){
- // 取出第一个文件夹来处理
- file_temp=list.removeFirst();
- // 使用上面申请的FIle[]来存放file_temp中的文件
- files=file_temp.listFiles();
- // 处理files中的文件,同上,文件夹放到list中,文件放到file_list中
- for (File file1 : files) {
- if (file1.isDirectory()){
- list.add(file1);
- }else {
- file_list.add(file1.getAbsolutePath());
- }
- }
- }
- }else{
- // 如果没有任何文件,则不做处理
- }
- return file_list;
- }
-
- // 判断类是否有Controller注解
- private static boolean isController(Class cl){
- Annotation annotation = cl.getAnnotation(Controller.class);
- if(annotation!=null){
- return true;
- }
- return false;
- }
-
- // 判断类是否有RequestMapping注解
- private static boolean isRequestMapping(Class cl){
- Annotation annotation = cl.getAnnotation(RequestMapping.class);
- if(annotation!=null){
- return true;
- }
- return false;
- }
- // 获取类的RequestMapping注解的实例
- private static RequestMapping getRequestMapping(Class<?> cl) {
- Annotation annotation = cl.getAnnotation(RequestMapping.class);
- if (annotation instanceof RequestMapping){
- return (RequestMapping) annotation;
- }
- return null;
- }
-
- // 判断方法是否有RequestMapping注解
- private static boolean isRequestMapping(Method method) {
- Annotation annotation = method.getAnnotation(RequestMapping.class);
- if (annotation!=null){
- return true;
- }
- return false;
- }
- // 获取方法上的RequestMapping注解的实例
- private static RequestMapping getRequestMapping(Method method) {
- Annotation annotation = method.getAnnotation(RequestMapping.class);
- if (annotation instanceof RequestMapping){
- return (RequestMapping) annotation;
- }
- return null;
- }
-
- }
整体思路流程,先对路径下的文件进行扫描,拿到.class后缀的文件,然后根据不同的注解进行不同的操作,将实例化对象和方法都存到map中,再从map中获取调用。具体详细的解释可以查看代码及其注释。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。