天天看点

自定义一个简单的SpringMVC框架

思路分析

  • 在服务器启动时,就扫描包下所有类:得到有注解

    @Controller

    的类
    • 反射生成这个类的实例对象:

      object

    • 遍历类里所有的方法,得到方法对象:

      method

    • 获取每个方法上

      @RequestMapping

      配置的映射路径:

      mappingPath

    • 把方法对象

      method

      和类实例对象

      object

      ,封装成对象:

      MvcMethod

    • mappingPath

      为key,

      MvcMethod

      对象为value,保存到一个Map中
  • 当客户端请求到

    DispatcherServlet

    • 获取请求的资源路径:path
    • 从Map容器中找到对应的

      MvcMethod

    • 反射执行

      MvcMethod

      中的方法对象

实现

@Controller

注解
package com.lily.SpringMVC_02;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)  //运行在类上
@Retention(RetentionPolicy.RUNTIME)   //存活到运行
public @interface Controller {
}
           

@RequestMapping

package com.lily.SpringMVC_02;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 功能描述:〈用在业务控制器的方法上,用来声明 方法的路径〉
 */
@Target(ElementType.METHOD)             //元注解: 表示在方法总运行
@Retention(RetentionPolicy.RUNTIME)   //元注解: 表示保留到运行阶段
public @interface RequestMapping {
    String value();                     //配置的映射路径
}
           

MvcMethod

package com.lily.SpringMVC_02;/*
@Author:李正铠
@Date:2020年03月02日21时13分
*/
import java.lang.reflect.Method;
public class MvcMethod {
    private Method method;
    private Object object;

    public MvcMethod() {
    }

    public MvcMethod(Method method, Object object) {
        this.method = method;
        this.object = object;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }
}
           

DispatcherServlet

/**
package com.lily.SpringMVC_02;/*
@Author:李正铠
@Date:2020年03月02日22时26分
*/

import com.lily.util.ClassScannerUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebServlet(urlPatterns = "*.do", loadOnStartup = 1)
public class DispatcherServlet extends HttpServlet {
    /**
     * 功能描述:〈重写init方法,配置注解:loadOnStartup,当值是整数,代表服务器启动时执行init方法〉
     */
    private Map<String, MvcMethod> map = new HashMap<>();

    @Override
    public void init() throws ServletException {
        try {
            List<Class<?>> classsFromPackage = ClassScannerUtils.getClasssFromPackage("com.lily.web");
            for (Class<?> clazz : classsFromPackage) {
                boolean isController = clazz.isAnnotationPresent(Controller.class);
                if (!isController) {
                    System.out.println(clazz + "类没有Controller注解");
                    continue;
                }
                Object object = clazz.newInstance();
                Method[] methods = clazz.getMethods();
                for (Method method : methods) {
                    boolean isRequestMapping = method.isAnnotationPresent(RequestMapping.class);
                    if (isRequestMapping) {
                        RequestMapping getRequestMapping = method.getAnnotation(RequestMapping.class);
                        String MappingPath = getRequestMapping.value();
                        MvcMethod mvcMethod = new MvcMethod(method, object);
                        map.put(MappingPath, mvcMethod);
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();
        String substring = uri.substring(contextPath.length(), uri.lastIndexOf("."));
        MvcMethod mvcMethod = map.get(substring);
        try {
            mvcMethod.getMethod().invoke(mvcMethod.getObject(), request, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

           

ClassScannerUtils

package com.lily.util;

import java.io.File;
import java.io.FileFilter;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;


public class ClassScannerUtils {

    /**
     * 获得包下面的所有的class
     *
     * @param
     * @return List包含所有class的实例
     */
    public static List<Class<?>> getClasssFromPackage(String packageName) {
        List clazzs = new ArrayList<>();
        // 是否循环搜索子包
        boolean recursive = true;
        // 包名对应的路径名称
        String packageDirName = packageName.replace('.', '/');
        Enumeration<URL> dirs;

        try {
            dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            while (dirs.hasMoreElements()) {

                URL url = dirs.nextElement();
                String protocol = url.getProtocol();
                if ("file".equals(protocol)) {
                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                    findClassInPackageByFile(packageName, filePath, recursive, clazzs);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return clazzs;
    }

    /**
     * 在package对应的路径下找到所有的class
     */
    public static void findClassInPackageByFile(String packageName, String filePath, final boolean recursive,
                                                List<Class<?>> clazzs) {
        File dir = new File(filePath);
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }
        // 在给定的目录下找到所有的文件,并且进行条件过滤
        File[] dirFiles = dir.listFiles(new FileFilter() {

            public boolean accept(File file) {
                boolean acceptDir = recursive && file.isDirectory();// 接受dir目录
                boolean acceptClass = file.getName().endsWith("class");// 接受class文件
                return acceptDir || acceptClass;
            }
        });

        for (File file : dirFiles) {
            if (file.isDirectory()) {
                findClassInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, clazzs);
            } else {
                String className = file.getName().substring(0, file.getName().length() - 6);
                try {
                    clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


}

           

继续阅读